diff --git a/packages/shared/__tests__/ReactErrorProd-test.internal.js b/packages/shared/__tests__/ReactErrorProd-test.internal.js index 62d6da32c5c2d..27679bc529920 100644 --- a/packages/shared/__tests__/ReactErrorProd-test.internal.js +++ b/packages/shared/__tests__/ReactErrorProd-test.internal.js @@ -8,7 +8,7 @@ */ 'use strict'; -let ReactErrorProd; +let formatProdErrorMessage; describe('ReactErrorProd', () => { let globalErrorMock; @@ -25,7 +25,7 @@ describe('ReactErrorProd', () => { expect(typeof global.Error).toBe('function'); } jest.resetModules(); - ReactErrorProd = require('shared/ReactErrorProd').default; + formatProdErrorMessage = require('shared/formatProdErrorMessage').default; }); afterEach(() => { @@ -35,27 +35,21 @@ describe('ReactErrorProd', () => { }); it('should throw with the correct number of `%s`s in the URL', () => { - expect(function() { - throw ReactErrorProd(Error(124), 'foo', 'bar'); - }).toThrowError( + expect(formatProdErrorMessage(124, 'foo', 'bar')).toEqual( 'Minified React error #124; visit ' + 'https://reactjs.org/docs/error-decoder.html?invariant=124&args[]=foo&args[]=bar' + ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.', ); - expect(function() { - throw ReactErrorProd(Error(20)); - }).toThrowError( + expect(formatProdErrorMessage(20)).toEqual( 'Minified React error #20; visit ' + 'https://reactjs.org/docs/error-decoder.html?invariant=20' + ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.', ); - expect(function() { - throw ReactErrorProd(Error(77), '
', '&?bar'); - }).toThrowError( + expect(formatProdErrorMessage(77, '
', '&?bar')).toEqual( 'Minified React error #77; visit ' + 'https://reactjs.org/docs/error-decoder.html?invariant=77&args[]=%3Cdiv%3E&args[]=%26%3Fbar' + ' for the full message or use the non-minified dev environment' + diff --git a/packages/shared/ReactErrorProd.js b/packages/shared/formatProdErrorMessage.js similarity index 68% rename from packages/shared/ReactErrorProd.js rename to packages/shared/formatProdErrorMessage.js index b909e2180809e..e315ed83155c3 100644 --- a/packages/shared/ReactErrorProd.js +++ b/packages/shared/formatProdErrorMessage.js @@ -7,20 +7,19 @@ */ // Do not require this module directly! Use normal `invariant` calls with -// template literal strings. The messages will be converted to ReactError during -// build, and in production they will be minified. +// template literal strings. The messages will be replaced with error codes +// during build. -function ReactErrorProd(error) { - const code = error.message; +function formatProdErrorMessage(code) { let url = 'https://reactjs.org/docs/error-decoder.html?invariant=' + code; for (let i = 1; i < arguments.length; i++) { url += '&args[]=' + encodeURIComponent(arguments[i]); } - error.message = + return ( `Minified React error #${code}; visit ${url} for the full message or ` + 'use the non-minified dev environment for full errors and additional ' + - 'helpful warnings. '; - return error; + 'helpful warnings.' + ); } -export default ReactErrorProd; +export default formatProdErrorMessage; diff --git a/scripts/error-codes/__tests__/__snapshots__/transform-error-messages.js.snap b/scripts/error-codes/__tests__/__snapshots__/transform-error-messages.js.snap index 4d7d944f8238e..f93b31a659dd2 100644 --- a/scripts/error-codes/__tests__/__snapshots__/transform-error-messages.js.snap +++ b/scripts/error-codes/__tests__/__snapshots__/transform-error-messages.js.snap @@ -4,59 +4,49 @@ exports[`error transform should correctly transform invariants that are not in t "import invariant from 'shared/invariant'; /*FIXME (minify-errors-in-prod): Unminified error message in production build!*/ -(function () { - if (!condition) { - throw Error(\\"This is not a real error message.\\"); - } -})();" +if (!condition) { + throw Error(\\"This is not a real error message.\\"); +}" `; exports[`error transform should handle escaped characters 1`] = ` "import invariant from 'shared/invariant'; /*FIXME (minify-errors-in-prod): Unminified error message in production build!*/ -(function () { - if (!condition) { - throw Error(\\"What's up?\\"); - } -})();" +if (!condition) { + throw Error(\\"What's up?\\"); +}" `; exports[`error transform should replace simple invariant calls 1`] = ` -"import _ReactErrorProd from \\"shared/ReactErrorProd\\"; +"import _formatProdErrorMessage from \\"shared/formatProdErrorMessage\\"; import invariant from 'shared/invariant'; if (!condition) { - if (__DEV__) { - throw Error(\\"Do not override existing functions.\\"); - } else { - throw _ReactErrorProd(Error(16)); + { + throw Error(__DEV__ ? \\"Do not override existing functions.\\" : _formatProdErrorMessage(16)); } }" `; exports[`error transform should support invariant calls with a concatenated template string and args 1`] = ` -"import _ReactErrorProd from \\"shared/ReactErrorProd\\"; +"import _formatProdErrorMessage from \\"shared/formatProdErrorMessage\\"; import invariant from 'shared/invariant'; if (!condition) { - if (__DEV__) { - throw Error(\\"Expected a component class, got \\" + Foo + \\".\\" + Bar); - } else { - throw _ReactErrorProd(Error(18), Foo, Bar); + { + throw Error(__DEV__ ? \\"Expected a component class, got \\" + Foo + \\".\\" + Bar : _formatProdErrorMessage(18, Foo, Bar)); } }" `; exports[`error transform should support invariant calls with args 1`] = ` -"import _ReactErrorProd from \\"shared/ReactErrorProd\\"; +"import _formatProdErrorMessage from \\"shared/formatProdErrorMessage\\"; import invariant from 'shared/invariant'; if (!condition) { - if (__DEV__) { - throw Error(\\"Expected \\" + foo + \\" target to be an array; got \\" + bar); - } else { - throw _ReactErrorProd(Error(7), foo, bar); + { + throw Error(__DEV__ ? \\"Expected \\" + foo + \\" target to be an array; got \\" + bar : _formatProdErrorMessage(7, foo, bar)); } }" `; diff --git a/scripts/error-codes/transform-error-messages.js b/scripts/error-codes/transform-error-messages.js index f97f82e6b98a9..6ebb68731f860 100644 --- a/scripts/error-codes/transform-error-messages.js +++ b/scripts/error-codes/transform-error-messages.js @@ -29,11 +29,11 @@ module.exports = function(babel) { // into this: // // if (!condition) { - // if (__DEV__) { - // throw Error(`A ${adj} message that contains ${noun}`); - // } else { - // throw ReactErrorProd(Error(ERR_CODE), adj, noun); - // } + // throw Error( + // __DEV__ + // ? `A ${adj} message that contains ${noun}` + // : formatProdErrorMessage(ERR_CODE, adj, noun) + // ); // } // // where ERR_CODE is an error code: a unique identifier (a number @@ -47,11 +47,10 @@ module.exports = function(babel) { .map(raw => t.templateElement({raw, cooked: String.raw({raw})})); // Outputs: - // throw Error(`A ${adj} message that contains ${noun}`); - const devThrow = t.throwStatement( - t.callExpression(t.identifier('Error'), [ - t.templateLiteral(errorMsgQuasis, errorMsgExpressions), - ]) + // `A ${adj} message that contains ${noun}`; + const devMessage = t.templateLiteral( + errorMsgQuasis, + errorMsgExpressions ); const parentStatementPath = path.parentPath; @@ -72,7 +71,11 @@ module.exports = function(babel) { parentStatementPath.replaceWith( t.ifStatement( t.unaryExpression('!', condition), - t.blockStatement([devThrow]) + t.blockStatement([ + t.throwStatement( + t.callExpression(t.identifier('Error'), [devMessage]) + ), + ]) ) ); return; @@ -94,15 +97,19 @@ module.exports = function(babel) { // Outputs: // /* FIXME (minify-errors-in-prod): Unminified error message in production build! */ // if (!condition) { - // throw ReactError(Error(`A ${adj} message that contains ${noun}`)); + // throw Error(`A ${adj} message that contains ${noun}`); // } - path.replaceWith( + parentStatementPath.replaceWith( t.ifStatement( t.unaryExpression('!', condition), - t.blockStatement([devThrow]) + t.blockStatement([ + t.throwStatement( + t.callExpression(t.identifier('Error'), [devMessage]) + ), + ]) ) ); - path.addComment( + parentStatementPath.addComment( 'leading', 'FIXME (minify-errors-in-prod): Unminified error message in production build!' ); @@ -111,40 +118,42 @@ module.exports = function(babel) { prodErrorId = parseInt(prodErrorId, 10); // Import ReactErrorProd - const reactErrorProdIdentfier = helperModuleImports.addDefault( + const formatProdErrorMessageIdentifier = helperModuleImports.addDefault( path, - 'shared/ReactErrorProd', - {nameHint: 'ReactErrorProd'} + 'shared/formatProdErrorMessage', + {nameHint: 'formatProdErrorMessage'} ); // Outputs: - // throw ReactErrorProd(Error(ERR_CODE), adj, noun); - const prodThrow = t.throwStatement( - t.callExpression(reactErrorProdIdentfier, [ - t.callExpression(t.identifier('Error'), [ - t.numericLiteral(prodErrorId), - ]), - ...errorMsgExpressions, - ]) + // formatProdErrorMessage(ERR_CODE, adj, noun); + const prodMessage = t.callExpression( + formatProdErrorMessageIdentifier, + [t.numericLiteral(prodErrorId), ...errorMsgExpressions] ); // Outputs: - // if (!condition) { - // if (__DEV__) { - // throw ReactError(Error(`A ${adj} message that contains ${noun}`)); - // } else { - // throw ReactErrorProd(Error(ERR_CODE), adj, noun); - // } - // } + // if (!condition) { + // throw Error( + // __DEV__ + // ? `A ${adj} message that contains ${noun}` + // : formatProdErrorMessage(ERR_CODE, adj, noun) + // ); + // } parentStatementPath.replaceWith( t.ifStatement( t.unaryExpression('!', condition), t.blockStatement([ - t.ifStatement( - DEV_EXPRESSION, - t.blockStatement([devThrow]), - t.blockStatement([prodThrow]) - ), + t.blockStatement([ + t.throwStatement( + t.callExpression(t.identifier('Error'), [ + t.conditionalExpression( + DEV_EXPRESSION, + devMessage, + prodMessage + ), + ]) + ), + ]), ]) ) );