From 07d1b47353c73eb7bdded80ac13d7ca082935d9d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 19 Jun 2018 15:42:51 +0100 Subject: [PATCH 1/2] Remove fbjs dependency --- checkPropTypes.js | 40 +++++++++++++++++++++++---- factoryWithThrowingShims.js | 7 ++--- factoryWithTypeCheckers.js | 55 ++++++++++++++++++++++--------------- package.json | 1 - yarn.lock | 12 -------- 5 files changed, 71 insertions(+), 44 deletions(-) diff --git a/checkPropTypes.js b/checkPropTypes.js index 0802c36..7c06d4e 100644 --- a/checkPropTypes.js +++ b/checkPropTypes.js @@ -7,11 +7,24 @@ 'use strict'; +var printWarning = function() {}; + if (process.env.NODE_ENV !== 'production') { - var invariant = require('fbjs/lib/invariant'); - var warning = require('fbjs/lib/warning'); var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); var loggedTypeFailures = {}; + + printWarning = function(text) { + var message = 'Warning: ' + text; + if (typeof console !== 'undefined') { + console.error(message); + } + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; } /** @@ -36,12 +49,27 @@ function checkPropTypes(typeSpecs, values, location, componentName, getStack) { 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 ' + 'the `prop-types` package, but received `%s`.', componentName || 'React class', location, typeSpecName, typeof typeSpecs[typeSpecName]); + if (typeof typeSpecs[typeSpecName] !== 'function') { + throw new Error( + (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[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 && !(error instanceof Error)) { + printWarning( + (componentName || 'React class') + ': type specification of ' + + location + ' `' + typeSpecName + '` is invalid; the type checker ' + + 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' + + 'You may have forgotten to pass an argument to the type checker ' + + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + + 'shape all require an argument).' + ) + + } if (error instanceof Error && !(error.message in loggedTypeFailures)) { // Only monitor this failure once because there tends to be a lot of the // same error. @@ -49,7 +77,9 @@ function checkPropTypes(typeSpecs, values, location, componentName, getStack) { var stack = getStack ? getStack() : ''; - warning(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : ''); + printWarning( + 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '') + ); } } } diff --git a/factoryWithThrowingShims.js b/factoryWithThrowingShims.js index 2b3c924..2ddf2d9 100644 --- a/factoryWithThrowingShims.js +++ b/factoryWithThrowingShims.js @@ -7,18 +7,17 @@ 'use strict'; -var emptyFunction = require('fbjs/lib/emptyFunction'); -var invariant = require('fbjs/lib/invariant'); var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); +function emptyFunction() {} + module.exports = function() { function shim(props, propName, componentName, location, propFullName, secret) { if (secret === ReactPropTypesSecret) { // It is still safe when called from React. return; } - invariant( - false, + throw new Error( 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use PropTypes.checkPropTypes() to call them. ' + 'Read more at http://fb.me/use-check-prop-types' diff --git a/factoryWithTypeCheckers.js b/factoryWithTypeCheckers.js index 7c962b1..c4362a5 100644 --- a/factoryWithTypeCheckers.js +++ b/factoryWithTypeCheckers.js @@ -7,14 +7,32 @@ 'use strict'; -var emptyFunction = require('fbjs/lib/emptyFunction'); -var invariant = require('fbjs/lib/invariant'); -var warning = require('fbjs/lib/warning'); var assign = require('object-assign'); var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret'); var checkPropTypes = require('./checkPropTypes'); +var printWarning = function() {}; + +if (process.env.NODE_ENV !== 'production') { + printWarning = function(text) { + var message = 'Warning: ' + text; + if (typeof console !== 'undefined') { + console.error(message); + } + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; +} + +function emptyFunctionThatReturnsNull() { + return null; +} + module.exports = function(isValidElement, throwOnDirectAccess) { /* global Symbol */ var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; @@ -157,8 +175,7 @@ module.exports = function(isValidElement, throwOnDirectAccess) { if (secret !== ReactPropTypesSecret) { if (throwOnDirectAccess) { // New behavior only for users of `prop-types` package - invariant( - false, + throw new Error( 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use `PropTypes.checkPropTypes()` to call them. ' + 'Read more at http://fb.me/use-check-prop-types' @@ -171,15 +188,12 @@ module.exports = function(isValidElement, throwOnDirectAccess) { // Avoid spamming the console because they are often not actionable except for lib authors manualPropTypeWarningCount < 3 ) { - warning( - false, + printWarning( 'You are manually calling a React.PropTypes validation ' + - 'function for the `%s` prop on `%s`. This is deprecated ' + + 'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' + 'and will throw in the standalone `prop-types` package. ' + '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 + 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.' ); manualPropTypeCallCache[cacheKey] = true; manualPropTypeWarningCount++; @@ -223,7 +237,7 @@ module.exports = function(isValidElement, throwOnDirectAccess) { } function createAnyTypeChecker() { - return createChainableTypeChecker(emptyFunction.thatReturnsNull); + return createChainableTypeChecker(emptyFunctionThatReturnsNull); } function createArrayOfTypeChecker(typeChecker) { @@ -273,8 +287,8 @@ module.exports = function(isValidElement, throwOnDirectAccess) { function createEnumTypeChecker(expectedValues) { if (!Array.isArray(expectedValues)) { - process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.') : void 0; - return emptyFunction.thatReturnsNull; + process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOf, expected an instance of array.') : void 0; + return emptyFunctionThatReturnsNull; } function validate(props, propName, componentName, location, propFullName) { @@ -316,21 +330,18 @@ module.exports = function(isValidElement, throwOnDirectAccess) { function createUnionTypeChecker(arrayOfTypeCheckers) { if (!Array.isArray(arrayOfTypeCheckers)) { - process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; - return emptyFunction.thatReturnsNull; + process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; + return emptyFunctionThatReturnsNull; } for (var i = 0; i < arrayOfTypeCheckers.length; i++) { var checker = arrayOfTypeCheckers[i]; if (typeof checker !== 'function') { - warning( - false, + printWarning( 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' + - 'received %s at index %s.', - getPostfixForTypeWarning(checker), - i + 'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.' ); - return emptyFunction.thatReturnsNull; + return emptyFunctionThatReturnsNull; } } diff --git a/package.json b/package.json index 2b14362..50c1465 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ }, "homepage": "https://facebook.github.io/react/", "dependencies": { - "fbjs": "^0.8.16", "loose-envify": "^1.3.1", "object-assign": "^4.1.1" }, diff --git a/yarn.lock b/yarn.lock index 31446b1..fefa4e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1049,18 +1049,6 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fbjs@^0.8.16: - version "0.8.16" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" - dependencies: - core-js "^1.0.0" - isomorphic-fetch "^2.1.1" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^0.7.9" - fbjs@^0.8.9: version "0.8.12" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04" From d6c9c5ce04ea59da9016242865bfe8a8f3dbc9e0 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 19 Jun 2018 15:46:13 +0100 Subject: [PATCH 2/2] Preserve "Invariant Violation" name --- checkPropTypes.js | 4 +++- factoryWithThrowingShims.js | 4 +++- factoryWithTypeCheckers.js | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/checkPropTypes.js b/checkPropTypes.js index 7c06d4e..05403dc 100644 --- a/checkPropTypes.js +++ b/checkPropTypes.js @@ -50,10 +50,12 @@ function checkPropTypes(typeSpecs, values, location, componentName, getStack) { // This is intentionally an invariant that gets caught. It's the same // behavior as without this statement except with a better message. if (typeof typeSpecs[typeSpecName] !== 'function') { - throw new Error( + var err = Error( (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' ); + err.name = 'Invariant Violation'; + throw err; } error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); } catch (ex) { diff --git a/factoryWithThrowingShims.js b/factoryWithThrowingShims.js index 2ddf2d9..79b60f2 100644 --- a/factoryWithThrowingShims.js +++ b/factoryWithThrowingShims.js @@ -17,11 +17,13 @@ module.exports = function() { // It is still safe when called from React. return; } - throw new Error( + var err = new Error( 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use PropTypes.checkPropTypes() to call them. ' + 'Read more at http://fb.me/use-check-prop-types' ); + err.name = 'Invariant Violation'; + throw err; }; shim.isRequired = shim; function getShim() { diff --git a/factoryWithTypeCheckers.js b/factoryWithTypeCheckers.js index c4362a5..c41e3bb 100644 --- a/factoryWithTypeCheckers.js +++ b/factoryWithTypeCheckers.js @@ -175,11 +175,13 @@ module.exports = function(isValidElement, throwOnDirectAccess) { if (secret !== ReactPropTypesSecret) { if (throwOnDirectAccess) { // New behavior only for users of `prop-types` package - throw new Error( + var err = new Error( 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use `PropTypes.checkPropTypes()` to call them. ' + 'Read more at http://fb.me/use-check-prop-types' ); + err.name = 'Invariant Violation'; + throw err; } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') { // Old behavior for people using React.PropTypes var cacheKey = componentName + ':' + propName;