From 7ea7a3bd016ad00e35280b71b09072d14935fde9 Mon Sep 17 00:00:00 2001 From: acdlite Date: Tue, 9 Apr 2024 21:18:26 +0000 Subject: [PATCH] Warn if outdated JSX transform is detected (#28781) We want to warn if we detect that an app is using an outdated JSX transform. We can't just warn if `createElement` is called because we still support `createElement` when it's called manually. We only want to warn if `createElement` is output by the compiler. The heuristic is to check for a `__self` prop, which is an optional, internal prop that older transforms used to pass to `createElement` for better debugging in development mode. If `__self` is present, we `console.warn` once with advice to upgrade to the modern JSX transform. Subsequent elements will not warn. There's a special case we have to account for: when a static "key" prop is defined _after_ a spread, the modern JSX transform outputs `createElement` instead of `jsx`. (This is because with `jsx`, a spread key always takes precedence over a static key, regardless of the order, whereas `createElement` respects the order.) To avoid a false positive warning, we skip the warning whenever a `key` prop is present. DiffTrain build for [ed3c65caf042f75fe2fdc2a5e568a9624c6175fb](https://github.com/facebook/react/commit/ed3c65caf042f75fe2fdc2a5e568a9624c6175fb) --- compiled/facebook-www/REVISION | 2 +- compiled/facebook-www/React-dev.classic.js | 24 ++++++++++++++++++- compiled/facebook-www/React-dev.modern.js | 24 ++++++++++++++++++- .../facebook-www/ReactServer-dev.modern.js | 24 ++++++++++++++++++- .../__test_utils__/ReactAllWarnings.js | 1 + 5 files changed, 71 insertions(+), 4 deletions(-) diff --git a/compiled/facebook-www/REVISION b/compiled/facebook-www/REVISION index 542f0b4ea6..052e04d269 100644 --- a/compiled/facebook-www/REVISION +++ b/compiled/facebook-www/REVISION @@ -1 +1 @@ -3f9e237a2feb74f1fca23b76d9d2e9e1713e2ba1 +ed3c65caf042f75fe2fdc2a5e568a9624c6175fb diff --git a/compiled/facebook-www/React-dev.classic.js b/compiled/facebook-www/React-dev.classic.js index 476d37142c..0a528e65d4 100644 --- a/compiled/facebook-www/React-dev.classic.js +++ b/compiled/facebook-www/React-dev.classic.js @@ -24,7 +24,7 @@ if (__DEV__) { ) { __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); } - var ReactVersion = "19.0.0-www-classic-8d3386cf"; + var ReactVersion = "19.0.0-www-classic-e2f5fe42"; // ATTENTION // When adding new symbols to this file, @@ -1292,6 +1292,7 @@ if (__DEV__) { var specialPropRefWarningShown; var didWarnAboutStringRefs; var didWarnAboutElementRef; + var didWarnAboutOldJSXRuntime; { didWarnAboutStringRefs = {}; @@ -1894,6 +1895,27 @@ if (__DEV__) { var ref = null; if (config != null) { + { + if ( + !didWarnAboutOldJSXRuntime && + "__self" in config && // Do not assume this is the result of an oudated JSX transform if key + // is present, because the modern JSX transform sometimes outputs + // createElement to preserve precedence between a static key and a + // spread key. To avoid false positive warnings, we never warn if + // there's a key. + !("key" in config) + ) { + didWarnAboutOldJSXRuntime = true; + + warn( + "Your app (or one of its dependencies) is using an outdated JSX " + + "transform. Update to the modern JSX transform for " + + "faster performance: " + // TODO: Create a short link for this + "https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html" + ); + } + } + if (hasValidRef(config)) { if (!enableRefAsProp) { ref = config.ref; diff --git a/compiled/facebook-www/React-dev.modern.js b/compiled/facebook-www/React-dev.modern.js index 3e9abaaec8..d19ef6b0a0 100644 --- a/compiled/facebook-www/React-dev.modern.js +++ b/compiled/facebook-www/React-dev.modern.js @@ -24,7 +24,7 @@ if (__DEV__) { ) { __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); } - var ReactVersion = "19.0.0-www-modern-337e1422"; + var ReactVersion = "19.0.0-www-modern-cd353aaf"; // ATTENTION // When adding new symbols to this file, @@ -1294,6 +1294,7 @@ if (__DEV__) { var specialPropRefWarningShown; var didWarnAboutStringRefs; var didWarnAboutElementRef; + var didWarnAboutOldJSXRuntime; { didWarnAboutStringRefs = {}; @@ -1896,6 +1897,27 @@ if (__DEV__) { var ref = null; if (config != null) { + { + if ( + !didWarnAboutOldJSXRuntime && + "__self" in config && // Do not assume this is the result of an oudated JSX transform if key + // is present, because the modern JSX transform sometimes outputs + // createElement to preserve precedence between a static key and a + // spread key. To avoid false positive warnings, we never warn if + // there's a key. + !("key" in config) + ) { + didWarnAboutOldJSXRuntime = true; + + warn( + "Your app (or one of its dependencies) is using an outdated JSX " + + "transform. Update to the modern JSX transform for " + + "faster performance: " + // TODO: Create a short link for this + "https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html" + ); + } + } + if (hasValidRef(config)) { if (!enableRefAsProp) { ref = config.ref; diff --git a/compiled/facebook-www/ReactServer-dev.modern.js b/compiled/facebook-www/ReactServer-dev.modern.js index 7dcf3801e5..2bde6a19a3 100644 --- a/compiled/facebook-www/ReactServer-dev.modern.js +++ b/compiled/facebook-www/ReactServer-dev.modern.js @@ -1018,6 +1018,7 @@ if (__DEV__) { var specialPropRefWarningShown; var didWarnAboutStringRefs; var didWarnAboutElementRef; + var didWarnAboutOldJSXRuntime; { didWarnAboutStringRefs = {}; @@ -1620,6 +1621,27 @@ if (__DEV__) { var ref = null; if (config != null) { + { + if ( + !didWarnAboutOldJSXRuntime && + "__self" in config && // Do not assume this is the result of an oudated JSX transform if key + // is present, because the modern JSX transform sometimes outputs + // createElement to preserve precedence between a static key and a + // spread key. To avoid false positive warnings, we never warn if + // there's a key. + !("key" in config) + ) { + didWarnAboutOldJSXRuntime = true; + + warn( + "Your app (or one of its dependencies) is using an outdated JSX " + + "transform. Update to the modern JSX transform for " + + "faster performance: " + // TODO: Create a short link for this + "https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html" + ); + } + } + if (hasValidRef(config)) { if (!enableRefAsProp) { ref = config.ref; @@ -3083,7 +3105,7 @@ if (__DEV__) { function noop() {} - var ReactVersion = "19.0.0-www-modern-a3494f1d"; + var ReactVersion = "19.0.0-www-modern-6d726a4f"; // Patch fetch var Children = { diff --git a/compiled/facebook-www/__test_utils__/ReactAllWarnings.js b/compiled/facebook-www/__test_utils__/ReactAllWarnings.js index acf0b8123e..cebb933df7 100644 --- a/compiled/facebook-www/__test_utils__/ReactAllWarnings.js +++ b/compiled/facebook-www/__test_utils__/ReactAllWarnings.js @@ -345,6 +345,7 @@ export default [ "You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set `onChange`.", "You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.", "You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ", + "Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html", "`%s` uses `getDerivedStateFromProps` but its initial state is %s. This is not recommended. Instead, define the initial state by assigning an object to `this.state` in the constructor of `%s`. This ensures that `getDerivedStateFromProps` arguments have a consistent shape.", "`Infinity` is an invalid value for the `%s` css style property.", "`NaN` is an invalid value for the `%s` css style property.",