diff --git a/fixtures/art/VectorWidget.js b/fixtures/art/VectorWidget.js index dda64bee188db..da5cde9e4be3f 100644 --- a/fixtures/art/VectorWidget.js +++ b/fixtures/art/VectorWidget.js @@ -24,13 +24,11 @@ var BASE_VEL = 0.15; /** * An animated SVG component. */ -var VectorWidget = React.createClass({ +class VectorWidget extends React.Component { /** * Initialize state members. */ - getInitialState: function() { - return {degrees: 0, velocity: 0, drag: MOUSE_UP_DRAG}; - }, + state = {degrees: 0, velocity: 0, drag: MOUSE_UP_DRAG}; /** * When the component is mounted into the document - this is similar to a @@ -39,40 +37,40 @@ var VectorWidget = React.createClass({ * method. Binding of `this.onTick` is not needed because all React methods * are automatically bound before being mounted. */ - componentDidMount: function() { + componentDidMount() { this._interval = window.setInterval(this.onTick, 20); - }, + } - componentWillUnmount: function() { + componentWillUnmount() { window.clearInterval(this._interval); - }, + } - onTick: function() { + onTick = () => { var nextDegrees = this.state.degrees + BASE_VEL + this.state.velocity; var nextVelocity = this.state.velocity * this.state.drag; this.setState({degrees: nextDegrees, velocity: nextVelocity}); - }, + }; /** * When mousing down, we increase the friction down the velocity. */ - handleMouseDown: function() { + handleMouseDown = () => { this.setState({drag: MOUSE_DOWN_DRAG}); - }, + }; /** * Cause the rotation to "spring". */ - handleMouseUp: function() { + handleMouseUp = () => { var nextVelocity = Math.min(this.state.velocity + CLICK_ACCEL, MAX_VEL); this.setState({velocity: nextVelocity, drag: MOUSE_UP_DRAG}); - }, + }; /** * This is the "main" method for any component. The React API allows you to * describe the structure of your UI component at *any* point in time. */ - render: function() { + render() { return ( ); - }, + } /** * Better SVG support for React coming soon. */ - renderGraphic: function(rotation) { + renderGraphic = (rotation) => { return ( ); - } -}); + }; +} var BORDER_PATH = "M3.00191459,4 C1.34400294,4 0,5.34785514 0,7.00550479 L0,220.994495 C0,222.65439 1.34239483,224 3.00191459,224 L276.998085,224 C278.655997,224 280,222.652145 280,220.994495 L280,7.00550479 C280,5.34561033 278.657605,4 276.998085,4 L3.00191459,4 Z M3.00191459,4"; var BG_PATH = "M3.00191459,1 C1.34400294,1 0,2.34785514 0,4.00550479 L0,217.994495 C0,219.65439 1.34239483,221 3.00191459,221 L276.998085,221 C278.655997,221 280,219.652145 280,217.994495 L280,4.00550479 C280,2.34561033 278.657605,1 276.998085,1 L3.00191459,1 Z M3.00191459,1"; diff --git a/fixtures/dom/package.json b/fixtures/dom/package.json index 07a70c4dc1d74..214de66fb73a6 100644 --- a/fixtures/dom/package.json +++ b/fixtures/dom/package.json @@ -8,6 +8,7 @@ "dependencies": { "classnames": "^2.2.5", "query-string": "^4.2.3", + "prop-types": "^15.5.6", "react": "^15.4.1", "react-dom": "^15.4.1", "semver": "^5.3.0" diff --git a/fixtures/dom/public/index.html b/fixtures/dom/public/index.html index a131a92882520..ed1922517a1b9 100644 --- a/fixtures/dom/public/index.html +++ b/fixtures/dom/public/index.html @@ -14,6 +14,7 @@ Learn how to configure a non-root public URL by running `npm run build`. --> React App + diff --git a/fixtures/dom/src/components/App.js b/fixtures/dom/src/components/App.js index 92550c638cff9..a22b1d918c4f6 100644 --- a/fixtures/dom/src/components/App.js +++ b/fixtures/dom/src/components/App.js @@ -4,17 +4,15 @@ import Fixtures from './fixtures'; import '../style.css'; -const App = React.createClass({ - render() { - return ( -
-
-
- -
+function App () { + return ( +
+
+
+
- ); - }, -}); +
+ ); +} export default App; diff --git a/fixtures/dom/src/components/Fixture.js b/fixtures/dom/src/components/Fixture.js index 1f6ef9ba09997..6074fa7d44c4e 100644 --- a/fixtures/dom/src/components/Fixture.js +++ b/fixtures/dom/src/components/Fixture.js @@ -1,7 +1,8 @@ +const PropTypes = window.PropTypes; const React = window.React; const propTypes = { - children: React.PropTypes.node.isRequired, + children: PropTypes.node.isRequired, }; class Fixture extends React.Component { diff --git a/fixtures/dom/src/components/FixtureSet.js b/fixtures/dom/src/components/FixtureSet.js index 9c6e8581eba4b..ff98b2884c1bb 100644 --- a/fixtures/dom/src/components/FixtureSet.js +++ b/fixtures/dom/src/components/FixtureSet.js @@ -1,8 +1,9 @@ import React from 'react'; +import PropTypes from 'prop-types'; const propTypes = { - title: React.PropTypes.node.isRequired, - description: React.PropTypes.node.isRequired, + title: PropTypes.node.isRequired, + description: PropTypes.node.isRequired, }; class FixtureSet extends React.Component { diff --git a/fixtures/dom/src/components/Header.js b/fixtures/dom/src/components/Header.js index d9732165c4248..6d1b32599fa8a 100644 --- a/fixtures/dom/src/components/Header.js +++ b/fixtures/dom/src/components/Header.js @@ -2,13 +2,14 @@ import { parse, stringify } from 'query-string'; import getVersionTags from '../tags'; const React = window.React; -const Header = React.createClass({ - getInitialState() { +class Header extends React.Component { + constructor(props, context) { + super(props, context); const query = parse(window.location.search); const version = query.version || 'local'; const versions = [version]; - return { version, versions }; - }, + this.state = { version, versions }; + } componentWillMount() { getVersionTags() .then(tags => { @@ -16,7 +17,7 @@ const Header = React.createClass({ versions = [`local`, ...versions]; this.setState({ versions }); }) - }, + } handleVersionChange(event) { const query = parse(window.location.search); query.version = event.target.value; @@ -24,10 +25,10 @@ const Header = React.createClass({ delete query.version; } window.location.search = stringify(query); - }, + } handleFixtureChange(event) { window.location.pathname = event.target.value; - }, + } render() { return (
@@ -66,7 +67,7 @@ const Header = React.createClass({
); - }, -}); + } +} export default Header; diff --git a/fixtures/dom/src/components/TestCase.js b/fixtures/dom/src/components/TestCase.js index 79c46a975afbc..053eac9467884 100644 --- a/fixtures/dom/src/components/TestCase.js +++ b/fixtures/dom/src/components/TestCase.js @@ -1,14 +1,15 @@ import cn from 'classnames'; import semver from 'semver'; import React from 'react'; +import PropTypes from 'prop-types'; import { parse } from 'query-string'; -import { semverString } from './propTypes' +import { semverString } from './propTypes'; const propTypes = { - children: React.PropTypes.node.isRequired, - title: React.PropTypes.node.isRequired, + children: PropTypes.node.isRequired, + title: PropTypes.node.isRequired, resolvedIn: semverString, - resolvedBy: React.PropTypes.string + resolvedBy: PropTypes.string }; class TestCase extends React.Component { diff --git a/fixtures/dom/src/components/fixtures/buttons/index.js b/fixtures/dom/src/components/fixtures/buttons/index.js index 4991f4e4d8c6b..e7182280d637b 100644 --- a/fixtures/dom/src/components/fixtures/buttons/index.js +++ b/fixtures/dom/src/components/fixtures/buttons/index.js @@ -10,7 +10,7 @@ function onButtonClick() { export default class ButtonTestCases extends React.Component { render() { return ( - + diff --git a/fixtures/dom/src/components/fixtures/index.js b/fixtures/dom/src/components/fixtures/index.js index adc5a3d16208e..27be0fe24f284 100644 --- a/fixtures/dom/src/components/fixtures/index.js +++ b/fixtures/dom/src/components/fixtures/index.js @@ -12,29 +12,27 @@ import ButtonFixtures from './buttons'; * A simple routing component that renders the appropriate * fixture based on the location pathname. */ -const FixturesPage = React.createClass({ - render() { - switch (window.location.pathname) { - case '/text-inputs': - return ; - case '/range-inputs': - return ; - case '/selects': - return ; - case '/textareas': - return ; - case '/input-change-events': - return ; - case '/number-inputs': - return ; - case '/password-inputs': - return ; - case '/buttons': - return - default: - return

Please select a test fixture.

; - } - }, -}); +function FixturesPage() { + switch (window.location.pathname) { + case '/text-inputs': + return ; + case '/range-inputs': + return ; + case '/selects': + return ; + case '/textareas': + return ; + case '/input-change-events': + return ; + case '/number-inputs': + return ; + case '/password-inputs': + return ; + case '/buttons': + return + default: + return

Please select a test fixture.

; + } +} module.exports = FixturesPage; diff --git a/fixtures/dom/src/components/fixtures/number-inputs/NumberTestCase.js b/fixtures/dom/src/components/fixtures/number-inputs/NumberTestCase.js index 2c072d478ebe4..1a3025c49323b 100644 --- a/fixtures/dom/src/components/fixtures/number-inputs/NumberTestCase.js +++ b/fixtures/dom/src/components/fixtures/number-inputs/NumberTestCase.js @@ -2,16 +2,14 @@ const React = window.React; import Fixture from '../../Fixture'; -const NumberTestCase = React.createClass({ - getInitialState() { - return { value: '' }; - }, - onChange(event) { +class NumberTestCase extends React.Component { + state = { value: '' }; + onChange = (event) => { const parsed = parseFloat(event.target.value, 10) const value = isNaN(parsed) ? '' : parsed this.setState({ value }) - }, + } render() { return ( @@ -31,7 +29,7 @@ const NumberTestCase = React.createClass({ ); - }, -}); + } +} export default NumberTestCase; diff --git a/fixtures/dom/src/components/fixtures/number-inputs/index.js b/fixtures/dom/src/components/fixtures/number-inputs/index.js index 2c88c333edeb3..7900bd8594345 100644 --- a/fixtures/dom/src/components/fixtures/number-inputs/index.js +++ b/fixtures/dom/src/components/fixtures/number-inputs/index.js @@ -4,164 +4,162 @@ import FixtureSet from '../../FixtureSet'; import TestCase from '../../TestCase'; import NumberTestCase from './NumberTestCase'; -const NumberInputs = React.createClass({ - render() { - return ( - + - - -
  • Type "3.1"
  • -
  • Press backspace, eliminating the "1"
  • -
    - - - The field should read "3.", preserving the decimal place - - - - -

    - Notes: Chrome and Safari clear trailing - decimals on blur. React makes this concession so that the - value attribute remains in sync with the value property. -

    -
    - - - -
  • Type "0.01"
  • -
    - - - The field should read "0.01" - - - -
    - - - -
  • Type "2e"
  • -
  • Type 4, to read "2e4"
  • -
    - - - The field should read "2e4". The parsed value should read "20000" - - - -
    - - - -
  • Type "3.14"
  • -
  • Press "e", so that the input reads "3.14e"
  • -
    - - - The field should read "3.14e", the parsed value should be empty - - - -
    - - - -
  • Type "3.14"
  • -
  • Move the text cursor to after the decimal place
  • -
  • Press "e" twice, so that the value reads "3.ee14"
  • -
    - - - The field should read "3.ee14" - - - -
    - - - -
  • Type "3.0"
  • -
    - - - The field should read "3.0" - - - -
    - - - -
  • Type "300"
  • -
  • Move the cursor to after the "3"
  • -
  • Type "."
  • -
    - - - The field should read "3.00", not "3" - - -
    - - - -
  • Type "3"
  • -
  • Select the entire value"
  • -
  • Type '-' to replace '3' with '-'
  • -
    - - - The field should read "-", not be blank. - - -
    - - - -
  • Type "-"
  • -
  • Type '3'
  • -
    - - - The field should read "-3". - - -
    -
    - ); - }, -}); + +
  • Type "3.1"
  • +
  • Press backspace, eliminating the "1"
  • +
    + + + The field should read "3.", preserving the decimal place + + + + +

    + Notes: Chrome and Safari clear trailing + decimals on blur. React makes this concession so that the + value attribute remains in sync with the value property. +

    +
    + + + +
  • Type "0.01"
  • +
    + + + The field should read "0.01" + + + +
    + + + +
  • Type "2e"
  • +
  • Type 4, to read "2e4"
  • +
    + + + The field should read "2e4". The parsed value should read "20000" + + + +
    + + + +
  • Type "3.14"
  • +
  • Press "e", so that the input reads "3.14e"
  • +
    + + + The field should read "3.14e", the parsed value should be empty + + + +
    + + + +
  • Type "3.14"
  • +
  • Move the text cursor to after the decimal place
  • +
  • Press "e" twice, so that the value reads "3.ee14"
  • +
    + + + The field should read "3.ee14" + + + +
    + + + +
  • Type "3.0"
  • +
    + + + The field should read "3.0" + + + +
    + + + +
  • Type "300"
  • +
  • Move the cursor to after the "3"
  • +
  • Type "."
  • +
    + + + The field should read "3.00", not "3" + + +
    + + + +
  • Type "3"
  • +
  • Select the entire value"
  • +
  • Type '-' to replace '3' with '-'
  • +
    + + + The field should read "-", not be blank. + + +
    + + + +
  • Type "-"
  • +
  • Type '3'
  • +
    + + + The field should read "-3". + + +
    +
    + ); +} export default NumberInputs; diff --git a/fixtures/dom/src/components/fixtures/password-inputs/PasswordTestCase.js b/fixtures/dom/src/components/fixtures/password-inputs/PasswordTestCase.js index 76f511776369d..085ff760b646b 100644 --- a/fixtures/dom/src/components/fixtures/password-inputs/PasswordTestCase.js +++ b/fixtures/dom/src/components/fixtures/password-inputs/PasswordTestCase.js @@ -2,13 +2,11 @@ const React = window.React; import Fixture from '../../Fixture'; -const PasswordTestCase = React.createClass({ - getInitialState() { - return { value: '' }; - }, - onChange(event) { +class PasswordTestCase extends React.Component { + state = { value: '' }; + onChange = (event) => { this.setState({ value: event.target.value }) - }, + } render() { return ( @@ -28,7 +26,7 @@ const PasswordTestCase = React.createClass({ ); - }, -}); + } +} export default PasswordTestCase; diff --git a/fixtures/dom/src/components/fixtures/password-inputs/index.js b/fixtures/dom/src/components/fixtures/password-inputs/index.js index 7c4094534bdad..bec39919781bf 100644 --- a/fixtures/dom/src/components/fixtures/password-inputs/index.js +++ b/fixtures/dom/src/components/fixtures/password-inputs/index.js @@ -4,30 +4,28 @@ import FixtureSet from '../../FixtureSet'; import TestCase from '../../TestCase'; import PasswordTestCase from './PasswordTestCase' -const NumberInputs = React.createClass({ - render() { - return ( - - - -
  • Type any string (not an actual password
  • -
    +function NumberInputs() { + return ( + + + +
  • Type any string (not an actual password
  • +
    - - The field should include the "unmasking password" icon. - + + The field should include the "unmasking password" icon. + - -
    -
    - ); - }, -}); + +
    +
    + ); +} export default NumberInputs; diff --git a/fixtures/dom/src/components/fixtures/range-inputs/index.js b/fixtures/dom/src/components/fixtures/range-inputs/index.js index e3be8ad2ce546..bea61f453e15b 100644 --- a/fixtures/dom/src/components/fixtures/range-inputs/index.js +++ b/fixtures/dom/src/components/fixtures/range-inputs/index.js @@ -1,12 +1,10 @@ const React = window.React; -const RangeInputs = React.createClass({ - getInitialState() { - return { value: 0.5 }; - }, - onChange(event) { +class RangeInputs extends React.Component { + state = { value: 0.5 }; + onChange = (event) => { this.setState({ value: event.target.value }); - }, + } render() { return (
    @@ -22,7 +20,7 @@ const RangeInputs = React.createClass({
    ); - }, -}); + } +} export default RangeInputs; diff --git a/fixtures/dom/src/components/fixtures/selects/index.js b/fixtures/dom/src/components/fixtures/selects/index.js index c991da7ce381f..a520e40c3b92f 100644 --- a/fixtures/dom/src/components/fixtures/selects/index.js +++ b/fixtures/dom/src/components/fixtures/selects/index.js @@ -1,12 +1,10 @@ const React = window.React; -const SelectFixture = React.createClass({ - getInitialState() { - return { value: '' }; - }, - onChange(event) { +class SelectFixture extends React.Component { + state = { value: '' }; + onChange = (event) => { this.setState({ value: event.target.value }); - }, + } render() { return (
    @@ -31,7 +29,7 @@ const SelectFixture = React.createClass({
    ); - }, -}); + } +} export default SelectFixture; diff --git a/fixtures/dom/src/components/fixtures/text-inputs/index.js b/fixtures/dom/src/components/fixtures/text-inputs/index.js index 2db132bcb1032..a1683672ce66b 100644 --- a/fixtures/dom/src/components/fixtures/text-inputs/index.js +++ b/fixtures/dom/src/components/fixtures/text-inputs/index.js @@ -1,13 +1,11 @@ const React = window.React; -const TextInputFixtures = React.createClass({ - getInitialState() { - return { - color: '#ffaaee', - }; - }, +class TextInputFixtures extends React.Component { + state = { + color: '#ffaaee', + }; - renderControlled(type) { + renderControlled = (type) => { let id = `controlled_${type}`; let onChange = e => { @@ -29,9 +27,9 @@ const TextInputFixtures = React.createClass({   → {JSON.stringify(state)} ); - }, + } - renderUncontrolled(type) { + renderUncontrolled = (type) => { let id = `uncontrolled_${type}`; return (
    @@ -39,7 +37,7 @@ const TextInputFixtures = React.createClass({
    ); - }, + } render() { // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input @@ -60,7 +58,7 @@ const TextInputFixtures = React.createClass({ ); - }, -}); + } +} module.exports = TextInputFixtures; diff --git a/fixtures/dom/src/components/fixtures/textareas/index.js b/fixtures/dom/src/components/fixtures/textareas/index.js index e39b2e2abf7f7..e2508f32b52c5 100644 --- a/fixtures/dom/src/components/fixtures/textareas/index.js +++ b/fixtures/dom/src/components/fixtures/textareas/index.js @@ -1,12 +1,10 @@ const React = window.React; -const TextAreaFixtures = React.createClass({ - getInitialState() { - return { value: '' }; - }, - onChange(event) { +class TextAreaFixtures extends React.Component { + state = { value: '' }; + onChange = (event) => { this.setState({ value: event.target.value }); - }, + } render() { return (
    @@ -30,7 +28,7 @@ const TextAreaFixtures = React.createClass({
    ); - }, -}); + } +} module.exports = TextAreaFixtures; diff --git a/fixtures/dom/src/components/propTypes.js b/fixtures/dom/src/components/propTypes.js index 42f4f4cf3ae27..dfb80d0a99b81 100644 --- a/fixtures/dom/src/components/propTypes.js +++ b/fixtures/dom/src/components/propTypes.js @@ -1,11 +1,10 @@ +import PropTypes from 'prop-types'; import semver from 'semver'; -const React = window.React; - export function semverString (props, propName, componentName) { let version = props[propName]; - let error = React.PropTypes.string(...arguments); + let error = PropTypes.string(...arguments); if (!error && version != null && !semver.valid(version)) error = new Error( `\`${propName}\` should be a valid "semantic version" matching ` + diff --git a/fixtures/dom/yarn.lock b/fixtures/dom/yarn.lock index e45c4a70540d7..762b52cfc093b 100644 --- a/fixtures/dom/yarn.lock +++ b/fixtures/dom/yarn.lock @@ -4239,6 +4239,12 @@ promise@7.1.1, promise@^7.1.1: dependencies: asap "~2.0.3" +prop-types@^15.5.6: + version "15.5.6" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.6.tgz#797a915b1714b645ebb7c5d6cc690346205bd2aa" + dependencies: + fbjs "^0.8.9" + proxy-addr@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.2.tgz#b4cc5f22610d9535824c123aef9d3cf73c40ba37" diff --git a/package.json b/package.json index 35589b84c6e68..96442524b43d8 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "coffee-script": "^1.8.0", "core-js": "^2.2.1", "coveralls": "^2.11.6", - "create-react-class": "^15.5.0", + "create-react-class": "^15.5.2", "del": "^2.0.2", "derequire": "^2.0.3", "escape-string-regexp": "^1.0.5", @@ -73,6 +73,7 @@ "object-assign": "^4.1.1", "platform": "^1.1.0", "prettier": "^0.22.0", + "prop-types": "^15.5.6", "rimraf": "^2.6.1", "rollup": "^0.41.6", "rollup-plugin-alias": "^1.2.1", diff --git a/packages/react-dom/package.json b/packages/react-dom/package.json index a4a7f48e9a93e..0dae9585dfe72 100644 --- a/packages/react-dom/package.json +++ b/packages/react-dom/package.json @@ -15,7 +15,8 @@ "dependencies": { "fbjs": "^0.8.9", "loose-envify": "^1.1.0", - "object-assign": "^4.1.0" + "object-assign": "^4.1.0", + "prop-types": "^15.5.6" }, "peerDependencies": { "react": "^16.0.0-alpha.8" diff --git a/packages/react/package.json b/packages/react/package.json index 1fc717340ef0f..134466884dc89 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -22,9 +22,11 @@ "node": ">=0.10.0" }, "dependencies": { + "create-react-class": "^15.5.2", "fbjs": "^0.8.9", "loose-envify": "^1.1.0", - "object-assign": "^4.1.0" + "object-assign": "^4.1.0", + "prop-types": "^15.5.6" }, "browserify": { "transform": [ diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index 89dc4c89febb1..485f3921f4f45 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -45,6 +45,8 @@ scripts/shared/__tests__/evalToString-test.js src/isomorphic/__tests__/React-test.js * should log a deprecation warning once when using React.createMixin * should warn once when attempting to access React.createClass +* should warn once when attempting to access React.PropTypes +* should warn once when attempting to access React.checkPropTypes src/isomorphic/children/__tests__/ReactChildren-test.js * should support identity for simple @@ -278,19 +280,6 @@ src/isomorphic/classic/types/__tests__/ReactPropTypes-test.js * should have received the validator's return value * should not warn if the validator returned null -src/isomorphic/classic/types/__tests__/ReactPropTypesProduction-test.js -* should be a no-op -* should be a no-op -* should be a no-op -* should be a no-op -* should be a no-op -* should be a no-op -* should be a no-op -* should be a no-op -* should be a no-op -* should be a no-op -* should not have been called - src/isomorphic/modern/class/__tests__/ReactClassEquivalence-test.js * tests the same thing for es6 classes and CoffeeScript * tests the same thing for es6 classes and TypeScript diff --git a/scripts/jest/ts-preprocessor.js b/scripts/jest/ts-preprocessor.js index b4fe74552c40f..29ad307a9a392 100644 --- a/scripts/jest/ts-preprocessor.js +++ b/scripts/jest/ts-preprocessor.js @@ -23,7 +23,7 @@ function compile(content, contentFilename) { getSourceFile(filename, languageVersion) { var source; var jestRegex = /jest\.d\.ts/; - var reactRegex = /(?:React|ReactDOM)(?:\.d)?\.ts$/; + var reactRegex = /(?:React|ReactDOM|PropTypes)(?:\.d)?\.ts$/; // `path.normalize` is used to turn forward slashes in // the file path into backslashes on Windows. diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index 69b04f0b73d0f..cc33df8d123e8 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -45,7 +45,12 @@ const bundles = [ sourceMap: false, }, entry: 'src/isomorphic/React.js', - externals: [], + externals: [ + 'create-react-class/factory', + 'prop-types', + 'prop-types/checkPropTypes', + 'prop-types/factory', + ], fbEntry: 'src/fb/ReactFBEntry.js', hasteName: 'React', isRenderer: false, @@ -74,7 +79,7 @@ const bundles = [ sourceMap: false, }, entry: 'src/renderers/dom/ReactDOM.js', - externals: [], + externals: ['prop-types', 'prop-types/checkPropTypes'], fbEntry: 'src/fb/ReactDOMFBEntry.js', hasteName: 'ReactDOMStack', isRenderer: true, @@ -86,6 +91,7 @@ const bundles = [ 'src/renderers/shared/**/*.js', 'src/test/**/*.js', // ReactTestUtils is currently very coupled to DOM. + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], @@ -102,7 +108,7 @@ const bundles = [ sourceMap: false, }, entry: 'src/renderers/dom/fiber/ReactDOMFiber.js', - externals: [], + externals: ['prop-types', 'prop-types/checkPropTypes'], fbEntry: 'src/fb/ReactDOMFiberFBEntry.js', hasteName: 'ReactDOMFiber', isRenderer: true, @@ -114,6 +120,7 @@ const bundles = [ 'src/renderers/shared/**/*.js', 'src/test/**/*.js', // ReactTestUtils is currently very coupled to DOM. + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], @@ -133,7 +140,7 @@ const bundles = [ sourceMap: false, }, entry: 'src/renderers/dom/ReactDOMServer.js', - externals: [], + externals: ['prop-types', 'prop-types/checkPropTypes'], fbEntry: 'src/renderers/dom/ReactDOMServer.js', hasteName: 'ReactDOMServerStack', isRenderer: true, @@ -144,6 +151,7 @@ const bundles = [ 'src/renderers/dom/**/*.js', 'src/renderers/shared/**/*.js', + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], @@ -169,6 +177,7 @@ const bundles = [ 'art/modes/current', 'art/modes/fast-noSideEffects', 'art/core/transform', + 'prop-types/checkPropTypes', 'react-dom', ], fbEntry: 'src/renderers/art/ReactARTStack.js', @@ -181,6 +190,7 @@ const bundles = [ 'src/renderers/art/**/*.js', 'src/renderers/shared/**/*.js', + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], @@ -203,6 +213,7 @@ const bundles = [ 'art/modes/current', 'art/modes/fast-noSideEffects', 'art/core/transform', + 'prop-types/checkPropTypes', 'react-dom', ], fbEntry: 'src/renderers/art/ReactARTFiber.js', @@ -215,6 +226,7 @@ const bundles = [ 'src/renderers/art/**/*.js', 'src/renderers/shared/**/*.js', + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], @@ -304,7 +316,7 @@ const bundles = [ sourceMap: false, }, entry: 'src/renderers/testing/ReactTestRendererFiber', - externals: [], + externals: ['prop-types/checkPropTypes'], fbEntry: 'src/renderers/testing/ReactTestRendererFiber', hasteName: 'ReactTestRendererFiber', isRenderer: true, @@ -316,6 +328,7 @@ const bundles = [ 'src/renderers/shared/**/*.js', 'src/renderers/testing/**/*.js', + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], @@ -330,7 +343,7 @@ const bundles = [ sourceMap: false, }, entry: 'src/renderers/testing/stack/ReactTestRendererStack', - externals: [], + externals: ['prop-types/checkPropTypes'], fbEntry: 'src/renderers/testing/stack/ReactTestRendererStack', hasteName: 'ReactTestRendererStack', isRenderer: true, @@ -342,6 +355,7 @@ const bundles = [ 'src/renderers/shared/**/*.js', 'src/renderers/testing/**/*.js', + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], @@ -360,7 +374,7 @@ const bundles = [ sourceMap: false, }, entry: 'src/renderers/noop/ReactNoop.js', - externals: [], + externals: ['prop-types/checkPropTypes'], isRenderer: true, label: 'noop-fiber', manglePropertiesOnProd: false, @@ -369,6 +383,7 @@ const bundles = [ 'src/renderers/noop/**/*.js', 'src/renderers/shared/**/*.js', + 'src/isomorphic/classic/types/checkPropTypes.js', 'src/ReactVersion.js', 'src/shared/**/*.js', ], diff --git a/scripts/rollup/modules.js b/scripts/rollup/modules.js index 801b94e3c4f43..985fe8869087a 100644 --- a/scripts/rollup/modules.js +++ b/scripts/rollup/modules.js @@ -52,6 +52,14 @@ const devOnlyFilesToStubOut = [ "'ReactTestUtils'", ]; +const legacyModules = [ + 'create-react-class', + 'create-react-class/factory', + 'prop-types', + 'prop-types/checkPropTypes', + 'prop-types/factory', +]; + // this function builds up a very niave Haste-like moduleMap // that works to create up an alias map for modules to link // up to their actual disk location so Rollup can properly @@ -230,6 +238,29 @@ function replaceDevOnlyStubbedModules(bundleType) { } } +function replaceLegacyModuleAliases(bundleType) { + switch (bundleType) { + case UMD_DEV: + case UMD_PROD: + const modulesAlias = {}; + legacyModules.forEach(legacyModule => { + const modulePath = legacyModule.includes('/') + ? legacyModule + : `${legacyModule}/index`; + const resolvedPath = resolve(`./node_modules/${modulePath}`); + modulesAlias[`'${legacyModule}'`] = `'${resolvedPath}'`; + }); + return modulesAlias; + case NODE_DEV: + case NODE_PROD: + case FB_DEV: + case FB_PROD: + case RN_DEV: + case RN_PROD: + return {}; + } +} + function getAliases(paths, bundleType, isRenderer, extractErrors) { return Object.assign( createModuleMap( @@ -247,7 +278,8 @@ function getDefaultReplaceModules(bundleType) { return Object.assign( {}, replaceFbjsModuleAliases(bundleType), - replaceDevOnlyStubbedModules(bundleType) + replaceDevOnlyStubbedModules(bundleType), + replaceLegacyModuleAliases(bundleType) ); } diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 88406fe9dfaaf..d676282dc3bff 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -1,117 +1,117 @@ { - "branch": "bundle-fixes", + "branch": "prop-types", "bundleSizes": { "react.development.js (UMD_DEV)": { - "size": 116098, - "gzip": 29520 + "size": 121474, + "gzip": 30524 }, "react.production.min.js (UMD_PROD)": { - "size": 13707, - "gzip": 5073 + "size": 15685, + "gzip": 5765 }, "react-dom.development.js (UMD_DEV)": { - "size": 563844, - "gzip": 130190 + "size": 583352, + "gzip": 134572 }, "react-dom.production.min.js (UMD_PROD)": { - "size": 120191, - "gzip": 37860 + "size": 120740, + "gzip": 38092 }, "react-dom-server.development.js (UMD_DEV)": { - "size": 476049, - "gzip": 115267 + "size": 495558, + "gzip": 119685 }, "react-dom-server.production.min.js (UMD_PROD)": { - "size": 106489, - "gzip": 33035 + "size": 107033, + "gzip": 33273 }, "react-art.development.js (UMD_DEV)": { - "size": 339929, - "gzip": 76018 + "size": 342770, + "gzip": 76828 }, "react-art.production.min.js (UMD_PROD)": { "size": 95013, - "gzip": 28991 + "gzip": 28990 }, "react.development.js (NODE_DEV)": { - "size": 109110, - "gzip": 27479 + "size": 70286, + "gzip": 17600 }, "react.production.min.js (NODE_PROD)": { - "size": 12598, - "gzip": 4649 + "size": 9226, + "gzip": 3626 }, "React-dev.js (FB_DEV)": { - "size": 110875, - "gzip": 28140 + "size": 72143, + "gzip": 18236 }, "React-prod.js (FB_PROD)": { - "size": 56406, - "gzip": 14416 + "size": 36643, + "gzip": 9256 }, "ReactDOMStack-dev.js (FB_DEV)": { - "size": 522626, - "gzip": 124708 + "size": 522763, + "gzip": 124727 }, "ReactDOMStack-prod.js (FB_PROD)": { - "size": 352708, - "gzip": 84660 + "size": 352776, + "gzip": 84675 }, "react-dom.development.js (NODE_DEV)": { - "size": 542218, - "gzip": 125162 + "size": 542350, + "gzip": 125199 }, "react-dom.production.min.js (NODE_PROD)": { - "size": 116858, - "gzip": 36717 + "size": 116925, + "gzip": 36732 }, "ReactDOMFiber-dev.js (FB_DEV)": { - "size": 797268, - "gzip": 184134 + "size": 797397, + "gzip": 184161 }, "ReactDOMFiber-prod.js (FB_PROD)": { - "size": 407540, - "gzip": 93567 + "size": 407613, + "gzip": 93586 }, "react-dom-server.development.js (NODE_DEV)": { - "size": 445452, - "gzip": 107574 + "size": 445589, + "gzip": 107597 }, "react-dom-server.production.min.js (NODE_PROD)": { - "size": 101344, - "gzip": 31273 + "size": 101411, + "gzip": 31292 }, "ReactDOMServerStack-dev.js (FB_DEV)": { - "size": 444144, - "gzip": 107423 + "size": 444281, + "gzip": 107443 }, "ReactDOMServerStack-prod.js (FB_PROD)": { - "size": 333744, - "gzip": 80424 + "size": 334166, + "gzip": 80444 }, "ReactARTStack-dev.js (FB_DEV)": { - "size": 141589, - "gzip": 32280 + "size": 142986, + "gzip": 32714 }, "ReactARTStack-prod.js (FB_PROD)": { - "size": 99762, - "gzip": 22576 + "size": 101143, + "gzip": 22993 }, "react-art.development.js (NODE_DEV)": { - "size": 265123, - "gzip": 56951 + "size": 265214, + "gzip": 56974 }, "react-art.production.min.js (NODE_PROD)": { - "size": 56591, - "gzip": 17132 + "size": 56628, + "gzip": 17152 }, "ReactARTFiber-dev.js (FB_DEV)": { - "size": 264301, - "gzip": 56758 + "size": 264392, + "gzip": 56780 }, "ReactARTFiber-prod.js (FB_PROD)": { - "size": 205292, - "gzip": 43132 + "size": 205336, + "gzip": 43154 }, "ReactNativeStack.js (RN)": { "size": 233993, @@ -122,20 +122,20 @@ "gzip": 84001 }, "ReactTestRendererFiber-dev.js (FB_DEV)": { - "size": 262210, - "gzip": 55722 + "size": 262301, + "gzip": 55747 }, "ReactTestRendererStack-dev.js (FB_DEV)": { - "size": 151425, - "gzip": 34728 + "size": 151521, + "gzip": 34765 }, "react-noop-renderer.development.js (NODE_DEV)": { - "size": 254207, - "gzip": 53701 + "size": 254298, + "gzip": 53728 }, "react-test-renderer.development.js (NODE_DEV)": { - "size": 263041, - "gzip": 55919 + "size": 263132, + "gzip": 55938 } } } \ No newline at end of file diff --git a/src/isomorphic/React.js b/src/isomorphic/React.js index ccc351225edb8..807a1c369f4f5 100644 --- a/src/isomorphic/React.js +++ b/src/isomorphic/React.js @@ -20,6 +20,7 @@ var ReactVersion = require('ReactVersion'); var onlyChild = require('onlyChild'); var checkPropTypes = require('checkPropTypes'); +var createReactClass = require('createClass'); var createElement = ReactElement.createElement; var createFactory = ReactElement.createFactory; @@ -56,11 +57,13 @@ var React = { cloneElement: cloneElement, isValidElement: ReactElement.isValidElement, + // TODO (bvaughn) Remove these getters in 16.0.0-alpha.10 + PropTypes: ReactPropTypes, checkPropTypes: checkPropTypes, + createClass: createReactClass, // Classic - PropTypes: ReactPropTypes, createFactory: createFactory, createMixin: createMixin, @@ -82,8 +85,10 @@ if (__DEV__) { ReactDebugCurrentFrame: require('ReactDebugCurrentFrame'), }); + let warnedForCheckPropTypes = false; let warnedForCreateMixin = false; let warnedForCreateClass = false; + let warnedForPropTypes = false; React.createMixin = function(mixin) { warning( @@ -95,18 +100,49 @@ if (__DEV__) { return mixin; }; + // TODO (bvaughn) Remove both of these deprecation warnings in 16.0.0-alpha.10 if (canDefineProperty) { + Object.defineProperty(React, 'checkPropTypes', { + get() { + warning( + warnedForCheckPropTypes, + 'checkPropTypes has been moved to a separate package. ' + + 'Accessing React.checkPropTypes is no longer supported ' + + 'and will be removed completely in React 16. ' + + 'Use the prop-types package on npm instead. ' + + '(https://fb.me/migrating-from-react-proptypes)', + ); + warnedForCheckPropTypes = true; + return ReactPropTypes; + }, + }); + Object.defineProperty(React, 'createClass', { get: function() { warning( warnedForCreateClass, 'React.createClass is no longer supported. Use a plain JavaScript ' + "class instead. If you're not yet ready to migrate, " + - 'create-react-class is available on npm as a temporary, ' + - 'drop-in replacement.', + 'create-react-class is available on npm as a drop-in replacement. ' + + '(https://fb.me/migrating-from-react-create-class)', ); warnedForCreateClass = true; - return undefined; + return createReactClass; + }, + }); + + Object.defineProperty(React, 'PropTypes', { + get() { + warning( + warnedForPropTypes, + 'PropTypes has been moved to a separate package. ' + + 'Accessing React.PropTypes is no longer supported ' + + 'and will be removed completely in React 16. ' + + 'Use the prop-types package on npm instead. ' + + '(https://fb.me/migrating-from-react-proptypes)', + ); + warnedForPropTypes = true; + return ReactPropTypes; }, }); } diff --git a/src/isomorphic/__tests__/React-test.js b/src/isomorphic/__tests__/React-test.js index f2ea926dd9a08..bd5d5bc1aaa4b 100644 --- a/src/isomorphic/__tests__/React-test.js +++ b/src/isomorphic/__tests__/React-test.js @@ -32,13 +32,43 @@ describe('React', () => { spyOn(console, 'error'); let createClass = React.createClass; createClass = React.createClass; - expect(createClass).toBe(undefined); + expect(createClass).not.toBe(undefined); expectDev(console.error.calls.count()).toBe(1); expectDev(console.error.calls.argsFor(0)[0]).toContain( - 'React.createClass is no longer supported. Use a plain ' + - "JavaScript class instead. If you're not yet ready to migrate, " + - 'create-react-class is available on npm as a temporary, ' + - 'drop-in replacement.', + 'React.createClass is no longer supported. Use a plain JavaScript ' + + "class instead. If you're not yet ready to migrate, " + + 'create-react-class is available on npm as a drop-in replacement. ' + + '(https://fb.me/migrating-from-react-create-class)', + ); + }); + + it('should warn once when attempting to access React.PropTypes', () => { + spyOn(console, 'error'); + let PropTypes = React.PropTypes; + PropTypes = React.PropTypes; + expect(PropTypes).not.toBe(undefined); + expectDev(console.error.calls.count()).toBe(1); + expectDev(console.error.calls.argsFor(0)[0]).toContain( + 'PropTypes has been moved to a separate package. ' + + 'Accessing React.PropTypes is no longer supported ' + + 'and will be removed completely in React 16. ' + + 'Use the prop-types package on npm instead. ' + + '(https://fb.me/migrating-from-react-proptypes)', + ); + }); + + it('should warn once when attempting to access React.checkPropTypes', () => { + spyOn(console, 'error'); + let checkPropTypes = React.checkPropTypes; + checkPropTypes = React.checkPropTypes; + expect(checkPropTypes).not.toBe(undefined); + expectDev(console.error.calls.count()).toBe(1); + expectDev(console.error.calls.argsFor(0)[0]).toContain( + 'checkPropTypes has been moved to a separate package. ' + + 'Accessing React.checkPropTypes is no longer supported ' + + 'and will be removed completely in React 16. ' + + 'Use the prop-types package on npm instead. ' + + '(https://fb.me/migrating-from-react-proptypes)', ); }); }); diff --git a/src/isomorphic/classic/__tests__/ReactContextValidator-test.js b/src/isomorphic/classic/__tests__/ReactContextValidator-test.js index 84a220877f8cb..0630f588cc7a2 100644 --- a/src/isomorphic/classic/__tests__/ReactContextValidator-test.js +++ b/src/isomorphic/classic/__tests__/ReactContextValidator-test.js @@ -17,6 +17,7 @@ 'use strict'; +var PropTypes; var React; var ReactDOM; var ReactTestUtils; @@ -29,6 +30,7 @@ describe('ReactContextValidator', () => { beforeEach(() => { jest.resetModules(); + PropTypes = require('prop-types'); React = require('react'); ReactDOM = require('react-dom'); ReactTestUtils = require('ReactTestUtils'); @@ -44,7 +46,7 @@ describe('ReactContextValidator', () => { } } Component.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; class ComponentInFooBarContext extends React.Component { @@ -60,8 +62,8 @@ describe('ReactContextValidator', () => { } } ComponentInFooBarContext.childContextTypes = { - foo: React.PropTypes.string, - bar: React.PropTypes.number, + foo: PropTypes.string, + bar: PropTypes.number, }; var instance = ReactTestUtils.renderIntoDocument( @@ -88,8 +90,8 @@ describe('ReactContextValidator', () => { } } Parent.childContextTypes = { - foo: React.PropTypes.string.isRequired, - bar: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, + bar: PropTypes.string.isRequired, }; class Component extends React.Component { @@ -112,7 +114,7 @@ describe('ReactContextValidator', () => { } } Component.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; var container = document.createElement('div'); @@ -139,8 +141,8 @@ describe('ReactContextValidator', () => { } } Parent.childContextTypes = { - foo: React.PropTypes.string.isRequired, - bar: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, + bar: PropTypes.string.isRequired, }; class Component extends React.Component { @@ -153,7 +155,7 @@ describe('ReactContextValidator', () => { } } Component.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; var container = document.createElement('div'); @@ -171,7 +173,7 @@ describe('ReactContextValidator', () => { } } Component.contextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; ReactTestUtils.renderIntoDocument(); @@ -196,7 +198,7 @@ describe('ReactContextValidator', () => { } } ComponentInFooStringContext.childContextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; ReactTestUtils.renderIntoDocument( @@ -218,7 +220,7 @@ describe('ReactContextValidator', () => { } } ComponentInFooNumberContext.childContextTypes = { - foo: React.PropTypes.number, + foo: PropTypes.number, }; ReactTestUtils.renderIntoDocument( @@ -248,8 +250,8 @@ describe('ReactContextValidator', () => { } } Component.childContextTypes = { - foo: React.PropTypes.string.isRequired, - bar: React.PropTypes.number, + foo: PropTypes.string.isRequired, + bar: PropTypes.number, }; ReactTestUtils.renderIntoDocument(); @@ -288,7 +290,7 @@ describe('ReactContextValidator', () => { class ComponentA extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; render() { return
    ; @@ -296,7 +298,7 @@ describe('ReactContextValidator', () => { } class ComponentB extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; render() { return
    ; @@ -330,7 +332,7 @@ describe('ReactContextValidator', () => { class ParentContextProvider extends React.Component { static childContextTypes = { - foo: React.PropTypes.number, + foo: PropTypes.number, }; getChildContext() { return { @@ -344,7 +346,7 @@ describe('ReactContextValidator', () => { class MiddleMissingContext extends React.Component { static childContextTypes = { - bar: React.PropTypes.string.isRequired, + bar: PropTypes.string.isRequired, }; render() { return ; @@ -359,8 +361,8 @@ describe('ReactContextValidator', () => { } } ChildContextConsumer.contextTypes = { - bar: React.PropTypes.string.isRequired, - foo: React.PropTypes.string.isRequired, + bar: PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; ReactTestUtils.renderIntoDocument(); diff --git a/src/isomorphic/classic/class/__tests__/create-react-class-integration-test.js b/src/isomorphic/classic/class/__tests__/create-react-class-integration-test.js index 3eddc9730524c..55fb8c1ed8a49 100644 --- a/src/isomorphic/classic/class/__tests__/create-react-class-integration-test.js +++ b/src/isomorphic/classic/class/__tests__/create-react-class-integration-test.js @@ -11,6 +11,7 @@ 'use strict'; +var PropTypes; var React; var ReactDOM; var ReactTestUtils; @@ -18,8 +19,9 @@ var createReactClass; describe('create-react-class-integration', () => { beforeEach(() => { - React = require('React'); - ReactDOM = require('ReactDOM'); + PropTypes = require('prop-types'); + React = require('react'); + ReactDOM = require('react-dom'); ReactTestUtils = require('ReactTestUtils'); var createReactClassFactory = require('create-react-class/factory'); createReactClass = createReactClassFactory( @@ -188,13 +190,13 @@ describe('create-react-class-integration', () => { createReactClass({ mixins: [{}], propTypes: { - foo: React.PropTypes.string, + foo: PropTypes.string, }, contextTypes: { - foo: React.PropTypes.string, + foo: PropTypes.string, }, childContextTypes: { - foo: React.PropTypes.string, + foo: PropTypes.string, }, render: function() { return
    ; @@ -268,7 +270,7 @@ describe('create-react-class-integration', () => { it('renders based on context getInitialState', () => { var Foo = createReactClass({ contextTypes: { - className: React.PropTypes.string, + className: PropTypes.string, }, getInitialState() { return {className: this.context.className}; @@ -280,7 +282,7 @@ describe('create-react-class-integration', () => { var Outer = createReactClass({ childContextTypes: { - className: React.PropTypes.string, + className: PropTypes.string, }, getChildContext() { return {className: 'foo'}; diff --git a/src/isomorphic/classic/class/createClass.js b/src/isomorphic/classic/class/createClass.js new file mode 100644 index 0000000000000..3791e5392dc0a --- /dev/null +++ b/src/isomorphic/classic/class/createClass.js @@ -0,0 +1,19 @@ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule createClass + */ + +'use strict'; + +var {Component} = require('ReactBaseClasses'); +var {isValidElement} = require('ReactElement'); +var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue'); +var factory = require('create-react-class/factory'); + +module.exports = factory(Component, isValidElement, ReactNoopUpdateQueue); diff --git a/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js b/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js index 827509b196ea4..365b187d24391 100644 --- a/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js +++ b/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js @@ -11,6 +11,7 @@ 'use strict'; +var PropTypes; var React; var ReactDOM; var ReactTestUtils; @@ -19,6 +20,7 @@ describe('ReactElementClone', () => { var ComponentClass; beforeEach(() => { + PropTypes = require('prop-types'); React = require('react'); ReactDOM = require('react-dom'); ReactTestUtils = require('ReactTestUtils'); @@ -288,13 +290,13 @@ describe('ReactElementClone', () => { it('should check declared prop types after clone', () => { spyOn(console, 'error'); class Component extends React.Component { + static propTypes = { + color: PropTypes.string.isRequired, + }; render() { return React.createElement('div', null, 'My color is ' + this.color); } } - Component.propTypes = { - color: React.PropTypes.string.isRequired, - }; class Parent extends React.Component { render() { return React.cloneElement(this.props.child, {color: 123}); diff --git a/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js b/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js index ada2bb20fa7ec..69bb8fd512b8d 100644 --- a/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js +++ b/src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js @@ -14,6 +14,7 @@ // NOTE: We're explicitly not using JSX in this file. This is intended to test // classic JS without JSX. +var PropTypes; var React; var ReactDOM; var ReactTestUtils; @@ -28,6 +29,7 @@ describe('ReactElementValidator', () => { beforeEach(() => { jest.resetModules(); + PropTypes = require('prop-types'); React = require('react'); ReactDOM = require('react-dom'); ReactTestUtils = require('ReactTestUtils'); @@ -247,7 +249,7 @@ describe('ReactElementValidator', () => { return React.createElement('div', null, 'My color is ' + props.color); } MyComp.propTypes = { - color: React.PropTypes.string, + color: PropTypes.string, }; function ParentComp() { return React.createElement(MyComp, {color: 123}); @@ -332,12 +334,12 @@ describe('ReactElementValidator', () => { spyOn(console, 'error'); class Component extends React.Component { + static propTypes = {prop: PropTypes.string.isRequired}; + static defaultProps = {prop: null}; render() { return React.createElement('span', null, this.props.prop); } } - Component.propTypes = {prop: React.PropTypes.string.isRequired}; - Component.defaultProps = {prop: null}; ReactTestUtils.renderIntoDocument(React.createElement(Component)); @@ -353,12 +355,12 @@ describe('ReactElementValidator', () => { spyOn(console, 'error'); class Component extends React.Component { + static propTypes = {prop: PropTypes.string.isRequired}; + static defaultProps = {prop: 'text'}; render() { return React.createElement('span', null, this.props.prop); } } - Component.propTypes = {prop: React.PropTypes.string.isRequired}; - Component.defaultProps = {prop: 'text'}; ReactTestUtils.renderIntoDocument( React.createElement(Component, {prop: null}), @@ -376,13 +378,13 @@ describe('ReactElementValidator', () => { spyOn(console, 'error'); class Component extends React.Component { + static propTypes = { + prop: PropTypes.string.isRequired, + }; render() { return React.createElement('span', null, this.props.prop); } } - Component.propTypes = { - prop: React.PropTypes.string.isRequired, - }; ReactTestUtils.renderIntoDocument(React.createElement(Component)); ReactTestUtils.renderIntoDocument( @@ -416,13 +418,13 @@ describe('ReactElementValidator', () => { spyOn(console, 'error'); class Component extends React.Component { + static propTypes = { + myProp: PropTypes.shape, + }; render() { return React.createElement('span', null, this.props.myProp.value); } } - Component.propTypes = { - myProp: React.PropTypes.shape, - }; ReactTestUtils.renderIntoDocument( React.createElement(Component, {myProp: {value: 'hi'}}), diff --git a/src/isomorphic/classic/types/ReactPropTypes.js b/src/isomorphic/classic/types/ReactPropTypes.js index 01710a0086694..5c0ca77351039 100644 --- a/src/isomorphic/classic/types/ReactPropTypes.js +++ b/src/isomorphic/classic/types/ReactPropTypes.js @@ -11,548 +11,7 @@ 'use strict'; -var ReactElement = require('ReactElement'); -var ReactPropTypesSecret = require('ReactPropTypesSecret'); +var {isValidElement} = require('ReactElement'); +var factory = require('prop-types/factory'); -var emptyFunction = require('fbjs/lib/emptyFunction'); -var getIteratorFn = require('getIteratorFn'); -var invariant = require('fbjs/lib/invariant'); -var warning = require('fbjs/lib/warning'); - -/** - * Collection of methods that allow declaration and validation of props that are - * supplied to React components. Example usage: - * - * var Props = require('ReactPropTypes'); - * var MyArticle = React.createClass({ - * propTypes: { - * // An optional string prop named "description". - * description: Props.string, - * - * // A required enum prop named "category". - * category: Props.oneOf(['News','Photos']).isRequired, - * - * // A prop named "dialog" that requires an instance of Dialog. - * dialog: Props.instanceOf(Dialog).isRequired - * }, - * render: function() { ... } - * }); - * - * A more formal specification of how these methods are used: - * - * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) - * decl := ReactPropTypes.{type}(.isRequired)? - * - * Each and every declaration produces a function with the same signature. This - * allows the creation of custom validation functions. For example: - * - * var MyLink = React.createClass({ - * propTypes: { - * // An optional string or URI prop named "href". - * href: function(props, propName, componentName) { - * var propValue = props[propName]; - * if (propValue != null && typeof propValue !== 'string' && - * !(propValue instanceof URI)) { - * return new Error( - * 'Expected a string or an URI for ' + propName + ' in ' + - * componentName - * ); - * } - * } - * }, - * render: function() {...} - * }); - * - * @internal - */ - -var ANONYMOUS = '<>'; - -var ReactPropTypes; - -if (__DEV__) { - // Keep in sync with production version below - ReactPropTypes = { - array: createPrimitiveTypeChecker('array'), - bool: createPrimitiveTypeChecker('boolean'), - func: createPrimitiveTypeChecker('function'), - number: createPrimitiveTypeChecker('number'), - object: createPrimitiveTypeChecker('object'), - string: createPrimitiveTypeChecker('string'), - symbol: createPrimitiveTypeChecker('symbol'), - - any: createAnyTypeChecker(), - arrayOf: createArrayOfTypeChecker, - element: createElementTypeChecker(), - instanceOf: createInstanceTypeChecker, - node: createNodeChecker(), - objectOf: createObjectOfTypeChecker, - oneOf: createEnumTypeChecker, - oneOfType: createUnionTypeChecker, - shape: createShapeTypeChecker, - }; -} else { - var productionTypeChecker = function() { - invariant( - false, - 'React.PropTypes type checking code is stripped in production.', - ); - }; - productionTypeChecker.isRequired = productionTypeChecker; - var getProductionTypeChecker = () => productionTypeChecker; - // Keep in sync with development version above - ReactPropTypes = { - array: productionTypeChecker, - bool: productionTypeChecker, - func: productionTypeChecker, - number: productionTypeChecker, - object: productionTypeChecker, - string: productionTypeChecker, - symbol: productionTypeChecker, - - any: productionTypeChecker, - arrayOf: getProductionTypeChecker, - element: productionTypeChecker, - instanceOf: getProductionTypeChecker, - node: productionTypeChecker, - objectOf: getProductionTypeChecker, - oneOf: getProductionTypeChecker, - oneOfType: getProductionTypeChecker, - shape: getProductionTypeChecker, - }; -} - -/** - * inlined Object.is polyfill to avoid requiring consumers ship their own - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is - */ -/*eslint-disable no-self-compare*/ -function is(x, y) { - // SameValue algorithm - if (x === y) { - // Steps 1-5, 7-10 - // Steps 6.b-6.e: +0 != -0 - return x !== 0 || 1 / x === 1 / y; - } else { - // Step 6.a: NaN == NaN - return x !== x && y !== y; - } -} -/*eslint-enable no-self-compare*/ - -/** - * We use an Error-like object for backward compatibility as people may call - * PropTypes directly and inspect their output. However, we don't use real - * Errors anymore. We don't inspect their stack anyway, and creating them - * is prohibitively expensive if they are created too often, such as what - * happens in oneOfType() for any type before the one that matched. - */ -function PropTypeError(message) { - this.message = message; - this.stack = ''; -} -// Make `instanceof Error` still work for returned errors. -PropTypeError.prototype = Error.prototype; - -function createChainableTypeChecker(validate) { - if (__DEV__) { - var manualPropTypeCallCache = {}; - } - function checkType( - isRequired, - props, - propName, - componentName, - location, - propFullName, - secret, - ) { - componentName = componentName || ANONYMOUS; - propFullName = propFullName || propName; - if (__DEV__) { - if (secret !== ReactPropTypesSecret && typeof console !== 'undefined') { - var cacheKey = `${componentName}:${propName}`; - if (!manualPropTypeCallCache[cacheKey]) { - warning( - false, - 'You are manually calling a React.PropTypes validation ' + - 'function for the `%s` prop on `%s`. This is deprecated ' + - 'and will not work in production with the next major version. ' + - 'You may be seeing this warning due to a third-party PropTypes ' + - 'library. See https://fb.me/react-warning-dont-call-proptypes ' + - 'for details.', - propFullName, - componentName, - ); - manualPropTypeCallCache[cacheKey] = true; - } - } - } - if (props[propName] == null) { - if (isRequired) { - if (props[propName] === null) { - return new PropTypeError( - `The ${location} \`${propFullName}\` is marked as required ` + - `in \`${componentName}\`, but its value is \`null\`.`, - ); - } - return new PropTypeError( - `The ${location} \`${propFullName}\` is marked as required in ` + - `\`${componentName}\`, but its value is \`undefined\`.`, - ); - } - return null; - } else { - return validate(props, propName, componentName, location, propFullName); - } - } - - var chainedCheckType = checkType.bind(null, false); - chainedCheckType.isRequired = checkType.bind(null, true); - - return chainedCheckType; -} - -function createPrimitiveTypeChecker(expectedType) { - function validate( - props, - propName, - componentName, - location, - propFullName, - secret, - ) { - var propValue = props[propName]; - var propType = getPropType(propValue); - if (propType !== expectedType) { - // `propValue` being instance of, say, date/regexp, pass the 'object' - // check, but we can offer a more precise error message here rather than - // 'of type `object`'. - var preciseType = getPreciseType(propValue); - - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` of type ` + - `\`${preciseType}\` supplied to \`${componentName}\`, expected ` + - `\`${expectedType}\`.`, - ); - } - return null; - } - return createChainableTypeChecker(validate); -} - -function createAnyTypeChecker() { - return createChainableTypeChecker(emptyFunction.thatReturnsNull); -} - -function createArrayOfTypeChecker(typeChecker) { - function validate(props, propName, componentName, location, propFullName) { - if (typeof typeChecker !== 'function') { - return new PropTypeError( - `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside arrayOf.`, - ); - } - var propValue = props[propName]; - if (!Array.isArray(propValue)) { - var propType = getPropType(propValue); - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` of type ` + - `\`${propType}\` supplied to \`${componentName}\`, expected an array.`, - ); - } - for (var i = 0; i < propValue.length; i++) { - var error = typeChecker( - propValue, - i, - componentName, - location, - `${propFullName}[${i}]`, - ReactPropTypesSecret, - ); - if (error instanceof Error) { - return error; - } - } - return null; - } - return createChainableTypeChecker(validate); -} - -function createElementTypeChecker() { - function validate(props, propName, componentName, location, propFullName) { - var propValue = props[propName]; - if (!ReactElement.isValidElement(propValue)) { - var propType = getPropType(propValue); - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` of type ` + - `\`${propType}\` supplied to \`${componentName}\`, expected a single ReactElement.`, - ); - } - return null; - } - return createChainableTypeChecker(validate); -} - -function createInstanceTypeChecker(expectedClass) { - function validate(props, propName, componentName, location, propFullName) { - if (!(props[propName] instanceof expectedClass)) { - var expectedClassName = expectedClass.name || ANONYMOUS; - var actualClassName = getClassName(props[propName]); - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` of type ` + - `\`${actualClassName}\` supplied to \`${componentName}\`, expected ` + - `instance of \`${expectedClassName}\`.`, - ); - } - return null; - } - return createChainableTypeChecker(validate); -} - -function createEnumTypeChecker(expectedValues) { - if (!Array.isArray(expectedValues)) { - warning( - false, - 'Invalid argument supplied to oneOf, expected an instance of array.', - ); - return emptyFunction.thatReturnsNull; - } - - function validate(props, propName, componentName, location, propFullName) { - var propValue = props[propName]; - for (var i = 0; i < expectedValues.length; i++) { - if (is(propValue, expectedValues[i])) { - return null; - } - } - - var valuesString = JSON.stringify(expectedValues); - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` of value \`${propValue}\` ` + - `supplied to \`${componentName}\`, expected one of ${valuesString}.`, - ); - } - return createChainableTypeChecker(validate); -} - -function createObjectOfTypeChecker(typeChecker) { - function validate(props, propName, componentName, location, propFullName) { - if (typeof typeChecker !== 'function') { - return new PropTypeError( - `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside objectOf.`, - ); - } - var propValue = props[propName]; - var propType = getPropType(propValue); - if (propType !== 'object') { - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` of type ` + - `\`${propType}\` supplied to \`${componentName}\`, expected an object.`, - ); - } - for (var key in propValue) { - if (propValue.hasOwnProperty(key)) { - var error = typeChecker( - propValue, - key, - componentName, - location, - `${propFullName}.${key}`, - ReactPropTypesSecret, - ); - if (error instanceof Error) { - return error; - } - } - } - return null; - } - return createChainableTypeChecker(validate); -} - -function createUnionTypeChecker(arrayOfTypeCheckers) { - if (!Array.isArray(arrayOfTypeCheckers)) { - warning( - false, - 'Invalid argument supplied to oneOfType, expected an instance of array.', - ); - return emptyFunction.thatReturnsNull; - } - - function validate(props, propName, componentName, location, propFullName) { - for (var i = 0; i < arrayOfTypeCheckers.length; i++) { - var checker = arrayOfTypeCheckers[i]; - if ( - checker( - props, - propName, - componentName, - location, - propFullName, - ReactPropTypesSecret, - ) == null - ) { - return null; - } - } - - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` supplied to ` + - `\`${componentName}\`.`, - ); - } - return createChainableTypeChecker(validate); -} - -function createNodeChecker() { - function validate(props, propName, componentName, location, propFullName) { - if (!isNode(props[propName])) { - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` supplied to ` + - `\`${componentName}\`, expected a ReactNode.`, - ); - } - return null; - } - return createChainableTypeChecker(validate); -} - -function createShapeTypeChecker(shapeTypes) { - function validate(props, propName, componentName, location, propFullName) { - var propValue = props[propName]; - var propType = getPropType(propValue); - if (propType !== 'object') { - return new PropTypeError( - `Invalid ${location} \`${propFullName}\` of type \`${propType}\` ` + - `supplied to \`${componentName}\`, expected \`object\`.`, - ); - } - for (var key in shapeTypes) { - var checker = shapeTypes[key]; - if (!checker) { - continue; - } - var error = checker( - propValue, - key, - componentName, - location, - `${propFullName}.${key}`, - ReactPropTypesSecret, - ); - if (error) { - return error; - } - } - return null; - } - return createChainableTypeChecker(validate); -} - -function isNode(propValue) { - switch (typeof propValue) { - case 'number': - case 'string': - case 'undefined': - return true; - case 'boolean': - return !propValue; - case 'object': - if (Array.isArray(propValue)) { - return propValue.every(isNode); - } - if (propValue === null || ReactElement.isValidElement(propValue)) { - return true; - } - - var iteratorFn = getIteratorFn(propValue); - if (iteratorFn) { - var iterator = iteratorFn.call(propValue); - var step; - if (iteratorFn !== propValue.entries) { - while (!(step = iterator.next()).done) { - if (!isNode(step.value)) { - return false; - } - } - } else { - // Iterator will provide entry [k,v] tuples rather than values. - while (!(step = iterator.next()).done) { - var entry = step.value; - if (entry) { - if (!isNode(entry[1])) { - return false; - } - } - } - } - } else { - return false; - } - - return true; - default: - return false; - } -} - -function isSymbol(propType, propValue) { - // Native Symbol. - if (propType === 'symbol') { - return true; - } - - // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' - if (propValue['@@toStringTag'] === 'Symbol') { - return true; - } - - // Fallback for non-spec compliant Symbols which are polyfilled. - if (typeof Symbol === 'function' && propValue instanceof Symbol) { - return true; - } - - return false; -} - -// Equivalent of `typeof` but with special handling for array and regexp. -function getPropType(propValue) { - var propType = typeof propValue; - if (Array.isArray(propValue)) { - return 'array'; - } - if (propValue instanceof RegExp) { - // Old webkits (at least until Android 4.0) return 'function' rather than - // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ - // passes PropTypes.object. - return 'object'; - } - if (isSymbol(propType, propValue)) { - return 'symbol'; - } - return propType; -} - -// This handles more types than `getPropType`. Only used for error messages. -// See `createPrimitiveTypeChecker`. -function getPreciseType(propValue) { - var propType = getPropType(propValue); - if (propType === 'object') { - if (propValue instanceof Date) { - return 'date'; - } else if (propValue instanceof RegExp) { - return 'regexp'; - } - } - return propType; -} - -// Returns class name of the object, if any. -function getClassName(propValue) { - if (!propValue.constructor || !propValue.constructor.name) { - return ANONYMOUS; - } - return propValue.constructor.name; -} - -module.exports = ReactPropTypes; +module.exports = factory(isValidElement); diff --git a/src/isomorphic/classic/types/__tests__/ReactPropTypesProduction-test.js b/src/isomorphic/classic/types/__tests__/ReactPropTypesProduction-test.js deleted file mode 100644 index 33ccb85bd86a7..0000000000000 --- a/src/isomorphic/classic/types/__tests__/ReactPropTypesProduction-test.js +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @emails react-core - */ - -'use strict'; - -describe('ReactPropTypesProduction', function() { - var PropTypes; - var React; - var ReactTestUtils; - var oldProcess; - - beforeEach(function() { - __DEV__ = false; - - // Mutating process.env.NODE_ENV would cause our babel plugins to do the - // wrong thing. If you change this, make sure to test with jest --no-cache. - oldProcess = process; - global.process = { - ...process, - env: {...process.env, NODE_ENV: 'production'}, - }; - - jest.resetModules(); - PropTypes = require('ReactPropTypes'); - React = require('react'); - ReactTestUtils = require('ReactTestUtils'); - }); - - afterEach(function() { - __DEV__ = true; - global.process = oldProcess; - }); - - function expectThrowsInProduction(declaration, value) { - var props = {testProp: value}; - expect(() => { - declaration(props, 'testProp', 'testComponent', 'prop'); - }).toThrowError('Minified React error #144'); - } - - describe('Primitive Types', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.array, /please/); - expectThrowsInProduction(PropTypes.array.isRequired, /please/); - expectThrowsInProduction(PropTypes.array.isRequired, null); - expectThrowsInProduction(PropTypes.array.isRequired, undefined); - expectThrowsInProduction(PropTypes.bool, []); - expectThrowsInProduction(PropTypes.bool.isRequired, []); - expectThrowsInProduction(PropTypes.bool.isRequired, null); - expectThrowsInProduction(PropTypes.bool.isRequired, undefined); - expectThrowsInProduction(PropTypes.func, false); - expectThrowsInProduction(PropTypes.func.isRequired, false); - expectThrowsInProduction(PropTypes.func.isRequired, null); - expectThrowsInProduction(PropTypes.func.isRequired, undefined); - expectThrowsInProduction(PropTypes.number, function() {}); - expectThrowsInProduction(PropTypes.number.isRequired, function() {}); - expectThrowsInProduction(PropTypes.number.isRequired, null); - expectThrowsInProduction(PropTypes.number.isRequired, undefined); - expectThrowsInProduction(PropTypes.string, 0); - expectThrowsInProduction(PropTypes.string.isRequired, 0); - expectThrowsInProduction(PropTypes.string.isRequired, null); - expectThrowsInProduction(PropTypes.string.isRequired, undefined); - expectThrowsInProduction(PropTypes.symbol, 0); - expectThrowsInProduction(PropTypes.symbol.isRequired, 0); - expectThrowsInProduction(PropTypes.symbol.isRequired, null); - expectThrowsInProduction(PropTypes.symbol.isRequired, undefined); - expectThrowsInProduction(PropTypes.object, ''); - expectThrowsInProduction(PropTypes.object.isRequired, ''); - expectThrowsInProduction(PropTypes.object.isRequired, null); - expectThrowsInProduction(PropTypes.object.isRequired, undefined); - }); - }); - - describe('Any Type', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.any, null); - expectThrowsInProduction(PropTypes.any.isRequired, null); - expectThrowsInProduction(PropTypes.any.isRequired, undefined); - }); - }); - - describe('ArrayOf Type', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.arrayOf({foo: PropTypes.string}), { - foo: 'bar', - }); - expectThrowsInProduction(PropTypes.arrayOf(PropTypes.number), [ - 1, - 2, - 'b', - ]); - expectThrowsInProduction(PropTypes.arrayOf(PropTypes.number), { - '0': 'maybe-array', - length: 1, - }); - expectThrowsInProduction( - PropTypes.arrayOf(PropTypes.number).isRequired, - null, - ); - expectThrowsInProduction( - PropTypes.arrayOf(PropTypes.number).isRequired, - undefined, - ); - }); - }); - - describe('Component Type', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.element, [
    ,
    ]); - expectThrowsInProduction(PropTypes.element, 123); - expectThrowsInProduction(PropTypes.element, 'foo'); - expectThrowsInProduction(PropTypes.element, false); - expectThrowsInProduction(PropTypes.element.isRequired, null); - expectThrowsInProduction(PropTypes.element.isRequired, undefined); - }); - }); - - describe('Instance Types', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.instanceOf(Date), {}); - expectThrowsInProduction(PropTypes.instanceOf(Date).isRequired, {}); - }); - }); - - describe('React Component Types', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.node, {}); - expectThrowsInProduction(PropTypes.node.isRequired, null); - expectThrowsInProduction(PropTypes.node.isRequired, undefined); - }); - }); - - describe('ObjectOf Type', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.objectOf({foo: PropTypes.string}), { - foo: 'bar', - }); - expectThrowsInProduction(PropTypes.objectOf(PropTypes.number), { - a: 1, - b: 2, - c: 'b', - }); - expectThrowsInProduction(PropTypes.objectOf(PropTypes.number), [1, 2]); - expectThrowsInProduction(PropTypes.objectOf(PropTypes.number), null); - expectThrowsInProduction(PropTypes.objectOf(PropTypes.number), undefined); - }); - }); - - describe('OneOf Types', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.oneOf('red', 'blue'), 'red'); - expectThrowsInProduction(PropTypes.oneOf(['red', 'blue']), true); - expectThrowsInProduction(PropTypes.oneOf(['red', 'blue']), null); - expectThrowsInProduction(PropTypes.oneOf(['red', 'blue']), undefined); - }); - }); - - describe('Union Types', function() { - it('should be a no-op', function() { - expectThrowsInProduction( - PropTypes.oneOfType(PropTypes.string, PropTypes.number), - 'red', - ); - expectThrowsInProduction( - PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - [], - ); - expectThrowsInProduction( - PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - null, - ); - expectThrowsInProduction( - PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - undefined, - ); - }); - }); - - describe('Shape Types', function() { - it('should be a no-op', function() { - expectThrowsInProduction(PropTypes.shape({}), 'some string'); - expectThrowsInProduction( - PropTypes.shape({key: PropTypes.number}).isRequired, - null, - ); - expectThrowsInProduction( - PropTypes.shape({key: PropTypes.number}).isRequired, - undefined, - ); - }); - }); - - describe('Custom validator', function() { - beforeEach(function() { - jest.resetModules(); - }); - - it('should not have been called', function() { - var spy = jest.fn(); - function Component() { - return
    ; - } - Component.propTypes = {num: spy}; - - var instance = ; - ReactTestUtils.renderIntoDocument(instance); - - expect(spy).not.toBeCalled(); - }); - }); -}); diff --git a/src/isomorphic/classic/types/checkPropTypes.js b/src/isomorphic/classic/types/checkPropTypes.js index 5168efd9c001f..32d9ecc677497 100644 --- a/src/isomorphic/classic/types/checkPropTypes.js +++ b/src/isomorphic/classic/types/checkPropTypes.js @@ -11,84 +11,4 @@ 'use strict'; -var ReactPropTypesSecret = require('ReactPropTypesSecret'); - -var invariant = require('fbjs/lib/invariant'); -var warning = require('fbjs/lib/warning'); - -var loggedTypeFailures = {}; - -/** - * Assert that the values match with the type specs. - * Error messages are memorized and will only be shown once. - * - * @param {object} typeSpecs Map of name to a ReactPropType - * @param {object} values Runtime values that need to be type-checked - * @param {string} location e.g. "prop", "context", "child context" - * @param {string} componentName Name of the component for error messages. - * @param {?Function} getStack Returns the component stack. - * @private - */ -function checkPropTypes(typeSpecs, values, location, componentName, getStack) { - if (__DEV__) { - for (var typeSpecName in typeSpecs) { - if (typeSpecs.hasOwnProperty(typeSpecName)) { - var error; - // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - invariant( - typeof typeSpecs[typeSpecName] === 'function', - '%s: %s type `%s` is invalid; it must be a function, usually from ' + - 'React.PropTypes.', - componentName || 'React class', - location, - typeSpecName, - ); - error = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - ReactPropTypesSecret, - ); - } catch (ex) { - error = ex; - } - warning( - !error || error instanceof Error, - '%s: type specification of %s `%s` is invalid; the type checker ' + - 'function must return `null` or an `Error` but returned a %s. ' + - 'You may have forgotten to pass an argument to the type checker ' + - 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + - 'shape all require an argument).', - componentName || 'React class', - location, - typeSpecName, - typeof error, - ); - if (error instanceof Error && !(error.message in loggedTypeFailures)) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error.message] = true; - - var stack = getStack ? getStack() : ''; - - warning( - false, - 'Failed %s type: %s%s', - location, - error.message, - stack != null ? stack : '', - ); - } - } - } - } -} - -module.exports = checkPropTypes; +module.exports = require('prop-types/checkPropTypes'); diff --git a/src/isomorphic/modern/class/PropTypes.d.ts b/src/isomorphic/modern/class/PropTypes.d.ts new file mode 100644 index 0000000000000..a8802e66fe859 --- /dev/null +++ b/src/isomorphic/modern/class/PropTypes.d.ts @@ -0,0 +1,19 @@ +/*! + * Copyright 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +/** + * TypeScript Definition File for React. + * + * Full type definitions are not yet officially supported. These are mostly + * just helpers for the unit test. + */ + +declare module 'prop-types' { + export var string : any; +} diff --git a/src/isomorphic/modern/class/__tests__/ReactCoffeeScriptClass-test.coffee b/src/isomorphic/modern/class/__tests__/ReactCoffeeScriptClass-test.coffee index 1880a3dc6efaf..15f5e46eab758 100644 --- a/src/isomorphic/modern/class/__tests__/ReactCoffeeScriptClass-test.coffee +++ b/src/isomorphic/modern/class/__tests__/ReactCoffeeScriptClass-test.coffee @@ -9,6 +9,7 @@ of patent rights can be found in the PATENTS file in the same directory. React = null ReactDOM = null +PropTypes = null describe 'ReactCoffeeScriptClass', -> div = null @@ -21,6 +22,7 @@ describe 'ReactCoffeeScriptClass', -> beforeEach -> React = require 'react' ReactDOM = require 'react-dom' + PropTypes = require 'prop-types' container = document.createElement 'div' attachedListener = null renderedName = null @@ -102,8 +104,8 @@ describe 'ReactCoffeeScriptClass', -> it 'renders based on context in the constructor', -> class Foo extends React.Component @contextTypes: - tag: React.PropTypes.string - className: React.PropTypes.string + tag: PropTypes.string + className: PropTypes.string constructor: (props, context) -> super props, context @@ -118,8 +120,8 @@ describe 'ReactCoffeeScriptClass', -> class Outer extends React.Component @childContextTypes: - tag: React.PropTypes.string - className: React.PropTypes.string + tag: PropTypes.string + className: PropTypes.string getChildContext: -> tag: 'span' @@ -393,13 +395,13 @@ describe 'ReactCoffeeScriptClass', -> it 'supports this.context passed via getChildContext', -> class Bar extends React.Component @contextTypes: - bar: React.PropTypes.string + bar: PropTypes.string render: -> div className: @context.bar class Foo extends React.Component @childContextTypes: - bar: React.PropTypes.string + bar: PropTypes.string getChildContext: -> bar: 'bar-through-context' render: -> diff --git a/src/isomorphic/modern/class/__tests__/ReactES6Class-test.js b/src/isomorphic/modern/class/__tests__/ReactES6Class-test.js index a6ec313d5c105..f634e1d1c58d4 100644 --- a/src/isomorphic/modern/class/__tests__/ReactES6Class-test.js +++ b/src/isomorphic/modern/class/__tests__/ReactES6Class-test.js @@ -11,6 +11,7 @@ 'use strict'; +var PropTypes; var React; var ReactDOM; @@ -25,6 +26,7 @@ describe('ReactES6Class', () => { var renderedName = null; beforeEach(() => { + PropTypes = require('prop-types'); React = require('react'); ReactDOM = require('react-dom'); container = document.createElement('div'); @@ -123,8 +125,8 @@ describe('ReactES6Class', () => { } } Foo.contextTypes = { - tag: React.PropTypes.string, - className: React.PropTypes.string, + tag: PropTypes.string, + className: PropTypes.string, }; class Outer extends React.Component { @@ -136,8 +138,8 @@ describe('ReactES6Class', () => { } } Outer.childContextTypes = { - tag: React.PropTypes.string, - className: React.PropTypes.string, + tag: PropTypes.string, + className: PropTypes.string, }; test(, 'SPAN', 'foo'); }); @@ -419,7 +421,7 @@ describe('ReactES6Class', () => { return
    ; } } - Bar.contextTypes = {bar: React.PropTypes.string}; + Bar.contextTypes = {bar: PropTypes.string}; class Foo extends React.Component { getChildContext() { return {bar: 'bar-through-context'}; @@ -428,7 +430,7 @@ describe('ReactES6Class', () => { return ; } } - Foo.childContextTypes = {bar: React.PropTypes.string}; + Foo.childContextTypes = {bar: PropTypes.string}; test(, 'DIV', 'bar-through-context'); }); diff --git a/src/isomorphic/modern/class/__tests__/ReactTypeScriptClass-test.ts b/src/isomorphic/modern/class/__tests__/ReactTypeScriptClass-test.ts index 921474d3affbc..33085c89d9213 100644 --- a/src/isomorphic/modern/class/__tests__/ReactTypeScriptClass-test.ts +++ b/src/isomorphic/modern/class/__tests__/ReactTypeScriptClass-test.ts @@ -1,3 +1,4 @@ +/// /// /// @@ -12,6 +13,7 @@ import React = require('react'); import ReactDOM = require('react-dom'); +import PropTypes = require('prop-types'); // Before Each @@ -85,8 +87,8 @@ class StateBasedOnProps extends React.Component { // it renders based on context in the constructor class StateBasedOnContext extends React.Component { static contextTypes = { - tag: React.PropTypes.string, - className: React.PropTypes.string + tag: PropTypes.string, + className: PropTypes.string }; state = { tag: this.context.tag, @@ -100,8 +102,8 @@ class StateBasedOnContext extends React.Component { class ProvideChildContextTypes extends React.Component { static childContextTypes = { - tag: React.PropTypes.string, - className: React.PropTypes.string + tag: PropTypes.string, + className: PropTypes.string }; getChildContext() { return { tag: 'span', className: 'foo' }; @@ -278,13 +280,13 @@ class MisspelledComponent2 extends React.Component { // it supports this.context passed via getChildContext class ReadContext extends React.Component { - static contextTypes = { bar: React.PropTypes.string }; + static contextTypes = { bar: PropTypes.string }; render() { return React.createElement('div', { className: this.context.bar }); } } class ProvideContext extends React.Component { - static childContextTypes = { bar: React.PropTypes.string }; + static childContextTypes = { bar: PropTypes.string }; getChildContext() { return { bar: 'bar-through-context' }; } diff --git a/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js b/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js index 5074097dfa47f..ff1ff2e7c8e6d 100644 --- a/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js +++ b/src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js @@ -17,6 +17,7 @@ var React; var ReactDOM; var ReactTestUtils; +var PropTypes; describe('ReactJSXElementValidator', () => { function normalizeCodeLocInfo(str) { @@ -29,6 +30,7 @@ describe('ReactJSXElementValidator', () => { beforeEach(() => { jest.resetModules(); + PropTypes = require('prop-types'); React = require('react'); ReactDOM = require('react-dom'); ReactTestUtils = require('ReactTestUtils'); @@ -45,7 +47,7 @@ describe('ReactJSXElementValidator', () => { } }; RequiredPropComponent.displayName = 'RequiredPropComponent'; - RequiredPropComponent.propTypes = {prop: React.PropTypes.string.isRequired}; + RequiredPropComponent.propTypes = {prop: PropTypes.string.isRequired}; }); it('warns for keys for arrays of elements in children position', () => { @@ -188,7 +190,7 @@ describe('ReactJSXElementValidator', () => { } } MyComp.propTypes = { - color: React.PropTypes.string, + color: PropTypes.string, }; class ParentComp extends React.Component { render() { @@ -211,7 +213,7 @@ describe('ReactJSXElementValidator', () => { return null; } MyComp.propTypes = { - color: React.PropTypes.string, + color: PropTypes.string, }; function MiddleComp(props) { return ; diff --git a/src/renderers/__tests__/ReactComponentLifeCycle-test.js b/src/renderers/__tests__/ReactComponentLifeCycle-test.js index b9231571bb733..af575d153071c 100644 --- a/src/renderers/__tests__/ReactComponentLifeCycle-test.js +++ b/src/renderers/__tests__/ReactComponentLifeCycle-test.js @@ -14,6 +14,7 @@ var React; var ReactDOM; var ReactTestUtils; +var PropTypes; var clone = function(o) { return JSON.parse(JSON.stringify(o)); @@ -91,6 +92,7 @@ describe('ReactComponentLifeCycle', () => { React = require('react'); ReactDOM = require('react-dom'); ReactTestUtils = require('ReactTestUtils'); + PropTypes = require('prop-types'); }); it('should not reuse an instance when it has been unmounted', () => { @@ -605,14 +607,14 @@ describe('ReactComponentLifeCycle', () => { }; } Parent.childContextTypes = { - x: React.PropTypes.number, + x: PropTypes.number, }; function Child(props, context) { expect(context.x).toBe(2); return
    ; } Child.contextTypes = { - x: React.PropTypes.number, + x: PropTypes.number, }; const div = document.createElement('div'); diff --git a/src/renderers/__tests__/ReactComponentTreeHook-test.native.js b/src/renderers/__tests__/ReactComponentTreeHook-test.native.js index dd7be7d7014ce..ff458d64a4d6d 100644 --- a/src/renderers/__tests__/ReactComponentTreeHook-test.native.js +++ b/src/renderers/__tests__/ReactComponentTreeHook-test.native.js @@ -29,10 +29,12 @@ describeStack('ReactComponentTreeHook', () => { var View; var Image; var Text; + var PropTypes; beforeEach(() => { jest.resetModules(); + PropTypes = require('prop-types'); React = require('react'); ReactNative = require('ReactNative'); ReactInstanceMap = require('ReactInstanceMap'); @@ -50,7 +52,7 @@ describeStack('ReactComponentTreeHook', () => { }); Text = class extends React.Component { static childContextTypes = { - isInAParentText: React.PropTypes.bool, + isInAParentText: PropTypes.bool, }; getChildContext() { diff --git a/src/renderers/__tests__/ReactErrorBoundaries-test.js b/src/renderers/__tests__/ReactErrorBoundaries-test.js index d9a34dc5e6f84..49e9a1273dc28 100644 --- a/src/renderers/__tests__/ReactErrorBoundaries-test.js +++ b/src/renderers/__tests__/ReactErrorBoundaries-test.js @@ -13,6 +13,7 @@ var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); +var PropTypes; var React; var ReactDOM; @@ -37,6 +38,7 @@ describe('ReactErrorBoundaries', () => { var Normal; beforeEach(() => { + PropTypes = require('prop-types'); ReactDOM = require('react-dom'); React = require('react'); @@ -737,7 +739,7 @@ describe('ReactErrorBoundaries', () => { it('renders an error state if context provider throws in componentWillMount', () => { class BrokenComponentWillMountWithContext extends React.Component { - static childContextTypes = {foo: React.PropTypes.number}; + static childContextTypes = {foo: PropTypes.number}; getChildContext() { return {foo: 42}; } @@ -774,7 +776,7 @@ describe('ReactErrorBoundaries', () => { }; } BrokenComponentWillMountWithContext.childContextTypes = { - foo: React.PropTypes.number, + foo: PropTypes.number, }; var container = document.createElement('div'); diff --git a/src/renderers/__tests__/ReactStatelessComponent-test.js b/src/renderers/__tests__/ReactStatelessComponent-test.js index 3f11bf438e15e..0792eded59464 100644 --- a/src/renderers/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/__tests__/ReactStatelessComponent-test.js @@ -11,6 +11,7 @@ 'use strict'; +var PropTypes; var React; var ReactDOM; var ReactTestUtils; @@ -28,6 +29,7 @@ describe('ReactStatelessComponent', () => { beforeEach(() => { jest.resetModuleRegistry(); + PropTypes = require('prop-types'); React = require('react'); ReactDOM = require('react-dom'); ReactTestUtils = require('ReactTestUtils'); @@ -68,7 +70,7 @@ describe('ReactStatelessComponent', () => { it('should pass context thru stateless component', () => { class Child extends React.Component { static contextTypes = { - test: React.PropTypes.string.isRequired, + test: PropTypes.string.isRequired, }; render() { @@ -82,7 +84,7 @@ describe('ReactStatelessComponent', () => { class GrandParent extends React.Component { static childContextTypes = { - test: React.PropTypes.string.isRequired, + test: PropTypes.string.isRequired, }; getChildContext() { @@ -111,7 +113,7 @@ describe('ReactStatelessComponent', () => { } StatelessComponentWithChildContext.childContextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; var container = document.createElement('div'); @@ -355,7 +357,7 @@ describe('ReactStatelessComponent', () => { return
    {props.test}
    ; } Child.defaultProps = {test: 2}; - Child.propTypes = {test: React.PropTypes.string}; + Child.propTypes = {test: PropTypes.string}; spyOn(console, 'error'); ReactTestUtils.renderIntoDocument(); @@ -372,7 +374,7 @@ describe('ReactStatelessComponent', () => { it('should receive context', () => { class Parent extends React.Component { static childContextTypes = { - lang: React.PropTypes.string, + lang: PropTypes.string, }; getChildContext() { @@ -387,7 +389,7 @@ describe('ReactStatelessComponent', () => { function Child(props, context) { return
    {context.lang}
    ; } - Child.contextTypes = {lang: React.PropTypes.string}; + Child.contextTypes = {lang: PropTypes.string}; var el = document.createElement('div'); ReactDOM.render(, el); diff --git a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js index a2280be28f1f2..026fa910355a5 100644 --- a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js +++ b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js @@ -15,6 +15,7 @@ var React = require('react'); var ReactDOM = require('react-dom'); var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); var ReactTestUtils = require('ReactTestUtils'); +var PropTypes = require('prop-types'); describe('ReactDOMFiber', () => { var container; @@ -683,7 +684,7 @@ describe('ReactDOMFiber', () => { class Component extends React.Component { static contextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; render() { @@ -693,7 +694,7 @@ describe('ReactDOMFiber', () => { class Parent extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; getChildContext() { @@ -717,8 +718,8 @@ describe('ReactDOMFiber', () => { class Component extends React.Component { static contextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; render() { @@ -728,8 +729,8 @@ describe('ReactDOMFiber', () => { class Parent extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; state = { @@ -761,8 +762,8 @@ describe('ReactDOMFiber', () => { class Component extends React.Component { static contextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; render() { @@ -772,8 +773,8 @@ describe('ReactDOMFiber', () => { class Parent extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; getChildContext() { diff --git a/src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js b/src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js index af29b8d5ac882..0381ec8fb82aa 100644 --- a/src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js +++ b/src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js @@ -12,6 +12,7 @@ 'use strict'; let ExecutionEnvironment; +let PropTypes; let React; let ReactDOM; let ReactDOMServer; @@ -206,6 +207,7 @@ function expectMarkupMismatch(serverElement, clientElement) { // To get around this, we must reload React modules in between server and client render. function resetModules() { jest.resetModuleRegistry(); + PropTypes = require('prop-types'); React = require('React'); ReactDOM = require('ReactDOM'); ReactDOMServer = require('ReactDOMServer'); @@ -1585,7 +1587,7 @@ describe('ReactDOMServerIntegration', () => { return this.props.children; } } - Parent.childContextTypes = {text: React.PropTypes.string}; + Parent.childContextTypes = {text: PropTypes.string}; PurpleContext = props => {props.children}; RedContext = props => {props.children}; @@ -1597,7 +1599,7 @@ describe('ReactDOMServerIntegration', () => { return
    {this.context.text}
    ; } } - ClassChildWithContext.contextTypes = {text: React.PropTypes.string}; + ClassChildWithContext.contextTypes = {text: PropTypes.string}; const e = await render( , @@ -1609,7 +1611,7 @@ describe('ReactDOMServerIntegration', () => { function StatelessChildWithContext(props, context) { return
    {context.text}
    ; } - StatelessChildWithContext.contextTypes = {text: React.PropTypes.string}; + StatelessChildWithContext.contextTypes = {text: PropTypes.string}; const e = await render( , @@ -1650,7 +1652,7 @@ describe('ReactDOMServerIntegration', () => { return
    {this.context.text}
    ; } } - ClassChildWithWrongContext.contextTypes = {foo: React.PropTypes.string}; + ClassChildWithWrongContext.contextTypes = {foo: PropTypes.string}; const e = await render( , @@ -1664,7 +1666,7 @@ describe('ReactDOMServerIntegration', () => { return
    {context.text}
    ; } StatelessChildWithWrongContext.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; const e = await render( @@ -1677,7 +1679,7 @@ describe('ReactDOMServerIntegration', () => { function Grandchild(props, context) { return
    {context.text}
    ; } - Grandchild.contextTypes = {text: React.PropTypes.string}; + Grandchild.contextTypes = {text: PropTypes.string}; const Child = props => ; @@ -1689,7 +1691,7 @@ describe('ReactDOMServerIntegration', () => { const Grandchild = (props, context) => { return
    {context.text}
    ; }; - Grandchild.contextTypes = {text: React.PropTypes.string}; + Grandchild.contextTypes = {text: PropTypes.string}; const e = await render( , @@ -1706,7 +1708,7 @@ describe('ReactDOMServerIntegration', () => { return ; } } - Parent.childContextTypes = {text1: React.PropTypes.string}; + Parent.childContextTypes = {text1: PropTypes.string}; class Child extends React.Component { getChildContext() { @@ -1716,7 +1718,7 @@ describe('ReactDOMServerIntegration', () => { return ; } } - Child.childContextTypes = {text2: React.PropTypes.string}; + Child.childContextTypes = {text2: PropTypes.string}; const Grandchild = (props, context) => { return ( @@ -1727,8 +1729,8 @@ describe('ReactDOMServerIntegration', () => { ); }; Grandchild.contextTypes = { - text1: React.PropTypes.string, - text2: React.PropTypes.string, + text1: PropTypes.string, + text2: PropTypes.string, }; const e = await render(); @@ -1750,12 +1752,12 @@ describe('ReactDOMServerIntegration', () => { return ; } } - WillMountContext.childContextTypes = {text: React.PropTypes.string}; + WillMountContext.childContextTypes = {text: PropTypes.string}; const Child = (props, context) => { return
    {context.text}
    ; }; - Child.contextTypes = {text: React.PropTypes.string}; + Child.contextTypes = {text: PropTypes.string}; const e = await render(); expect(e.textContent).toBe('foo'); @@ -1788,7 +1790,7 @@ describe('ReactDOMServerIntegration', () => { return {value1: 'foo', value2: 'bar'}; } } - Component.childContextTypes = {value1: React.PropTypes.string}; + Component.childContextTypes = {value1: PropTypes.string}; return render(); }, ); diff --git a/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js b/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js index 30e617480b1fa..a0a30dfe8d726 100644 --- a/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js +++ b/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js @@ -12,6 +12,7 @@ 'use strict'; var React = require('react'); +var PropTypes = require('prop-types'); var ReactDOM = require('react-dom'); var ReactTestUtils = require('ReactTestUtils'); var renderSubtreeIntoContainer = require('renderSubtreeIntoContainer'); @@ -22,7 +23,7 @@ describe('renderSubtreeIntoContainer', () => { class Component extends React.Component { static contextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; render() { @@ -32,7 +33,7 @@ describe('renderSubtreeIntoContainer', () => { class Parent extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; getChildContext() { @@ -63,7 +64,7 @@ describe('renderSubtreeIntoContainer', () => { class Component extends React.Component { static contextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; render() { @@ -76,7 +77,7 @@ describe('renderSubtreeIntoContainer', () => { // eslint-disable-next-line no-unused-vars class Parent extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, + foo: PropTypes.string.isRequired, }; getChildContext() { @@ -104,8 +105,8 @@ describe('renderSubtreeIntoContainer', () => { class Component extends React.Component { static contextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; render() { @@ -115,8 +116,8 @@ describe('renderSubtreeIntoContainer', () => { class Parent extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; state = { @@ -156,8 +157,8 @@ describe('renderSubtreeIntoContainer', () => { class Component extends React.Component { static contextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; render() { @@ -167,8 +168,8 @@ describe('renderSubtreeIntoContainer', () => { class Parent extends React.Component { static childContextTypes = { - foo: React.PropTypes.string.isRequired, - getFoo: React.PropTypes.func.isRequired, + foo: PropTypes.string.isRequired, + getFoo: PropTypes.func.isRequired, }; getChildContext() { @@ -229,7 +230,7 @@ describe('renderSubtreeIntoContainer', () => { return {value: this.props.value}; } static childContextTypes = { - value: React.PropTypes.string.isRequired, + value: PropTypes.string.isRequired, }; } @@ -244,7 +245,7 @@ describe('renderSubtreeIntoContainer', () => { class Child extends React.Component { static contextTypes = { - value: React.PropTypes.string.isRequired, + value: PropTypes.string.isRequired, }; render() { return
    {this.context.value}
    ; @@ -272,7 +273,7 @@ describe('renderSubtreeIntoContainer', () => { renderSubtreeIntoContainer(this, , portal1); } static childContextTypes = { - value: React.PropTypes.string.isRequired, + value: PropTypes.string.isRequired, }; } @@ -287,7 +288,7 @@ describe('renderSubtreeIntoContainer', () => { class Child extends React.Component { static contextTypes = { - value: React.PropTypes.string.isRequired, + value: PropTypes.string.isRequired, }; render() { return
    {this.context.value}
    ; diff --git a/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js index e0cdedf22f5c7..0f8b44bc81e4d 100644 --- a/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js +++ b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js @@ -11,7 +11,7 @@ 'use strict'; -var React = require('react'); +var PropTypes = require('prop-types'); var ReactPropTypesSecret = require('ReactPropTypesSecret'); var warning = require('fbjs/lib/warning'); @@ -57,7 +57,7 @@ var propTypes = { 'set either `onChange` or `readOnly`.', ); }, - onChange: React.PropTypes.func, + onChange: PropTypes.func, }; var loggedTypeFailures = {}; diff --git a/src/renderers/native/__tests__/ReactNativeEvents-test.js b/src/renderers/native/__tests__/ReactNativeEvents-test.js index 56206149a75e0..9efa5f05e097b 100644 --- a/src/renderers/native/__tests__/ReactNativeEvents-test.js +++ b/src/renderers/native/__tests__/ReactNativeEvents-test.js @@ -11,6 +11,7 @@ 'use strict'; +var PropTypes; var RCTEventEmitter; var React; var ReactNative; @@ -21,6 +22,7 @@ var createReactNativeComponentClass; beforeEach(() => { jest.resetModules(); + PropTypes = require('prop-types'); RCTEventEmitter = require('RCTEventEmitter'); React = require('react'); ReactNative = require('ReactNative'); @@ -97,7 +99,7 @@ it('handles events on text nodes', () => { }); class ContextHack extends React.Component { - static childContextTypes = {isInAParentText: React.PropTypes.bool}; + static childContextTypes = {isInAParentText: PropTypes.bool}; getChildContext() { return {isInAParentText: true}; } diff --git a/src/renderers/shared/fiber/ReactFiberContext.js b/src/renderers/shared/fiber/ReactFiberContext.js index e60fdd850eb16..b2104d19e9039 100644 --- a/src/renderers/shared/fiber/ReactFiberContext.js +++ b/src/renderers/shared/fiber/ReactFiberContext.js @@ -15,7 +15,7 @@ import type {Fiber} from 'ReactFiber'; import type {StackCursor} from 'ReactFiberStack'; -var React = require('react'); +var checkPropTypes = require('checkPropTypes'); var emptyObject = require('fbjs/lib/emptyObject'); var getComponentName = require('getComponentName'); var invariant = require('fbjs/lib/invariant'); @@ -105,8 +105,7 @@ exports.getMaskedContext = function( if (__DEV__) { const name = getComponentName(workInProgress) || 'Unknown'; ReactDebugCurrentFrame.current = workInProgress; - // $FlowFixMe - We know this export exists now, need to wait for Flow update - React.checkPropTypes( + checkPropTypes( contextTypes, context, 'context', @@ -219,8 +218,7 @@ function processChildContext( // TODO: remove this hack when we delete unstable_renderSubtree in Fiber. const workInProgress = isReconciling ? fiber : null; ReactDebugCurrentFrame.current = workInProgress; - // $FlowFixMe - We know this export exists now, need to wait for Flow update - React.checkPropTypes( + checkPropTypes( childContextTypes, childContext, 'child context', diff --git a/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js b/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js index f0da503be5e12..b66151f38e2aa 100644 --- a/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js +++ b/src/renderers/shared/fiber/__tests__/ReactIncremental-test.js @@ -14,12 +14,14 @@ var React; var ReactNoop; var ReactFeatureFlags; +var PropTypes; describe('ReactIncremental', () => { beforeEach(() => { jest.resetModules(); React = require('react'); ReactNoop = require('ReactNoop'); + PropTypes = require('prop-types'); ReactFeatureFlags = require('ReactFeatureFlags'); ReactFeatureFlags.disableNewFiberFeatures = false; @@ -1592,7 +1594,7 @@ describe('ReactIncremental', () => { class Intl extends React.Component { static childContextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; getChildContext() { return { @@ -1607,7 +1609,7 @@ describe('ReactIncremental', () => { class Router extends React.Component { static childContextTypes = { - route: React.PropTypes.string, + route: PropTypes.string, }; getChildContext() { return { @@ -1622,7 +1624,7 @@ describe('ReactIncremental', () => { class ShowLocale extends React.Component { static contextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; render() { ops.push('ShowLocale ' + JSON.stringify(this.context)); @@ -1632,7 +1634,7 @@ describe('ReactIncremental', () => { class ShowRoute extends React.Component { static contextTypes = { - route: React.PropTypes.string, + route: PropTypes.string, }; render() { ops.push('ShowRoute ' + JSON.stringify(this.context)); @@ -1645,8 +1647,8 @@ describe('ReactIncremental', () => { return `${context.route} in ${context.locale}`; } ShowBoth.contextTypes = { - locale: React.PropTypes.string, - route: React.PropTypes.string, + locale: PropTypes.string, + route: PropTypes.string, }; class ShowNeither extends React.Component { @@ -1745,10 +1747,10 @@ describe('ReactIncremental', () => { var ops = []; class Recurse extends React.Component { static contextTypes = { - n: React.PropTypes.number, + n: PropTypes.number, }; static childContextTypes = { - n: React.PropTypes.number, + n: PropTypes.number, }; getChildContext() { return {n: (this.context.n || 3) - 1}; @@ -1777,7 +1779,7 @@ describe('ReactIncremental', () => { class Intl extends React.Component { static childContextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; getChildContext() { return { @@ -1792,7 +1794,7 @@ describe('ReactIncremental', () => { class ShowLocale extends React.Component { static contextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; render() { ops.push('ShowLocale ' + JSON.stringify(this.context)); @@ -1835,7 +1837,7 @@ describe('ReactIncremental', () => { class Intl extends React.Component { static childContextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; getChildContext() { const childContext = { @@ -1852,7 +1854,7 @@ describe('ReactIncremental', () => { class ShowLocaleClass extends React.Component { static contextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; render() { ops.push('ShowLocaleClass:read ' + JSON.stringify(this.context)); @@ -1865,7 +1867,7 @@ describe('ReactIncremental', () => { return context.locale; } ShowLocaleFn.contextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; class Stateful extends React.Component { @@ -1925,7 +1927,7 @@ describe('ReactIncremental', () => { class Intl extends React.Component { static childContextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; getChildContext() { const childContext = { @@ -1942,7 +1944,7 @@ describe('ReactIncremental', () => { class ShowLocaleClass extends React.Component { static contextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; render() { ops.push('ShowLocaleClass:read ' + JSON.stringify(this.context)); @@ -1955,7 +1957,7 @@ describe('ReactIncremental', () => { return context.locale; } ShowLocaleFn.contextTypes = { - locale: React.PropTypes.string, + locale: PropTypes.string, }; function IndirectionFn(props, context) { diff --git a/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js b/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js index 4b4b415cc7173..b4c9098e8f4cf 100644 --- a/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js +++ b/src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js @@ -11,6 +11,7 @@ 'use strict'; +var PropTypes; var React; var ReactNoop; var ReactFeatureFlags; @@ -18,6 +19,7 @@ var ReactFeatureFlags; describe('ReactIncrementalErrorHandling', () => { beforeEach(() => { jest.resetModules(); + PropTypes = require('prop-types'); React = require('react'); ReactNoop = require('ReactNoop'); ReactFeatureFlags = require('ReactFeatureFlags'); @@ -679,8 +681,8 @@ describe('ReactIncrementalErrorHandling', () => { it('unwinds the context stack correctly on error', () => { class Provider extends React.Component { - static childContextTypes = {message: React.PropTypes.string}; - static contextTypes = {message: React.PropTypes.string}; + static childContextTypes = {message: PropTypes.string}; + static contextTypes = {message: PropTypes.string}; getChildContext() { return { message: (this.context.message || '') + this.props.message, @@ -696,7 +698,7 @@ describe('ReactIncrementalErrorHandling', () => { } Connector.contextTypes = { - message: React.PropTypes.string, + message: PropTypes.string, }; function BadRender() { diff --git a/src/renderers/shared/fiber/__tests__/ReactIncrementalPerf-test.js b/src/renderers/shared/fiber/__tests__/ReactIncrementalPerf-test.js index b4a47480039fd..56fa122245c1d 100644 --- a/src/renderers/shared/fiber/__tests__/ReactIncrementalPerf-test.js +++ b/src/renderers/shared/fiber/__tests__/ReactIncrementalPerf-test.js @@ -17,6 +17,7 @@ describe('ReactDebugFiberPerf', () => { let ReactFeatureFlags; let ReactNoop; let ReactPortal; + let PropTypes; let root; let activeMeasure; @@ -119,6 +120,7 @@ describe('ReactDebugFiberPerf', () => { ReactNoop = require('ReactNoop'); ReactPortal = require('ReactPortal'); ReactFeatureFlags.disableNewFiberFeatures = false; + PropTypes = require('prop-types'); }); afterEach(() => { @@ -245,7 +247,7 @@ describe('ReactDebugFiberPerf', () => { it('captures all lifecycles', () => { class AllLifecycles extends React.Component { static childContextTypes = { - foo: React.PropTypes.any, + foo: PropTypes.any, }; shouldComponentUpdate() { return true; diff --git a/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js b/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js index 6649dffaf64b5..2ad0d4b40316b 100644 --- a/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js @@ -27,6 +27,7 @@ if (__DEV__) { var warningAboutMissingGetChildContext = {}; } +var checkPropTypes = require('checkPropTypes'); var emptyObject = require('fbjs/lib/emptyObject'); var invariant = require('fbjs/lib/invariant'); var shallowEqual = require('fbjs/lib/shallowEqual'); @@ -729,7 +730,7 @@ var ReactCompositeComponent = { _checkContextTypes: function(typeSpecs, values, location: string) { if (__DEV__) { ReactDebugCurrentFrame.current = this._debugID; - React.checkPropTypes( + checkPropTypes( typeSpecs, values, location, diff --git a/src/test/__tests__/ReactTestUtils-test.js b/src/test/__tests__/ReactTestUtils-test.js index 68c489cfb8f3d..cd1b2a5dc8a5c 100644 --- a/src/test/__tests__/ReactTestUtils-test.js +++ b/src/test/__tests__/ReactTestUtils-test.js @@ -11,6 +11,7 @@ 'use strict'; +var PropTypes; var React; var ReactDOM; var ReactDOMServer; @@ -18,6 +19,7 @@ var ReactTestUtils; describe('ReactTestUtils', () => { beforeEach(() => { + PropTypes = require('prop-types'); React = require('react'); ReactDOM = require('react-dom'); ReactDOMServer = require('react-dom/server'); @@ -195,7 +197,7 @@ describe('ReactTestUtils', () => { it('can shallowly render components with contextTypes', () => { class SimpleComponent extends React.Component { static contextTypes = { - name: React.PropTypes.string, + name: PropTypes.string, }; render() { @@ -258,7 +260,7 @@ describe('ReactTestUtils', () => { it('can pass context when shallowly rendering', () => { class SimpleComponent extends React.Component { static contextTypes = { - name: React.PropTypes.string, + name: PropTypes.string, }; render() { @@ -278,7 +280,7 @@ describe('ReactTestUtils', () => { class SimpleComponent extends React.Component { static contextTypes = { - name: React.PropTypes.string.isRequired, + name: PropTypes.string.isRequired, }; render() { diff --git a/yarn.lock b/yarn.lock index 681679cb60642..bd8f7924ce013 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1438,11 +1438,12 @@ create-hmac@^1.1.0, create-hmac@^1.1.2: create-hash "^1.1.0" inherits "^2.0.1" -create-react-class@^15.5.0: - version "15.5.0" - resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.0.tgz#7508ffcad56a0804fb244d6ff70b07648abfe5fb" +create-react-class@^15.5.2: + version "15.5.2" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.2.tgz#6a8758348df660b88326a0e764d569f274aad681" dependencies: fbjs "^0.8.9" + object-assign "^4.1.1" cross-spawn-async@^2.2.2: version "2.2.5" @@ -3929,6 +3930,12 @@ promise@^7.1.1: dependencies: asap "~2.0.3" +prop-types@^15.5.6: + version "15.5.6" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.6.tgz#797a915b1714b645ebb7c5d6cc690346205bd2aa" + dependencies: + fbjs "^0.8.9" + prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"