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 [ed3c65caf0](https://github.com/facebook/react/commit/ed3c65caf042f75fe2fdc2a5e568a9624c6175fb)
This commit is contained in:
acdlite
2024-04-09 21:18:26 +00:00
parent 442049b3dc
commit 7ea7a3bd01
5 changed files with 71 additions and 4 deletions
+1 -1
View File
@@ -1 +1 @@
3f9e237a2feb74f1fca23b76d9d2e9e1713e2ba1
ed3c65caf042f75fe2fdc2a5e568a9624c6175fb
+23 -1
View File
@@ -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;
+23 -1
View File
@@ -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;
@@ -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 = {
@@ -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.",