From ec5b61a29b52506e01a6dbb9a70b63960c2246b5 Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Thu, 22 Feb 2024 20:40:32 +0000 Subject: [PATCH] Make enableRefAsProp www dynamic (#28423) Going to start rolling this out DiffTrain build for [aaf85f3af8c30252edaab5c24975cd086937b2a4](https://github.com/facebook/react/commit/aaf85f3af8c30252edaab5c24975cd086937b2a4) --- .../facebook-www/JSXDEVRuntime-dev.classic.js | 93 ++++++++- .../facebook-www/JSXDEVRuntime-dev.modern.js | 93 ++++++++- compiled/facebook-www/REVISION | 2 +- compiled/facebook-www/React-dev.classic.js | 116 +++++++++--- compiled/facebook-www/React-dev.modern.js | 116 +++++++++--- compiled/facebook-www/React-prod.classic.js | 33 ++-- compiled/facebook-www/React-prod.modern.js | 33 ++-- .../facebook-www/React-profiling.classic.js | 33 ++-- .../facebook-www/React-profiling.modern.js | 33 ++-- compiled/facebook-www/ReactART-dev.classic.js | 56 +++++- compiled/facebook-www/ReactART-dev.modern.js | 56 +++++- .../facebook-www/ReactART-prod.classic.js | 37 +++- compiled/facebook-www/ReactART-prod.modern.js | 37 +++- compiled/facebook-www/ReactDOM-dev.classic.js | 56 +++++- compiled/facebook-www/ReactDOM-dev.modern.js | 56 +++++- .../facebook-www/ReactDOM-prod.classic.js | 43 +++-- compiled/facebook-www/ReactDOM-prod.modern.js | 43 +++-- .../ReactDOM-profiling.classic.js | 43 +++-- .../facebook-www/ReactDOM-profiling.modern.js | 43 +++-- .../ReactDOMServer-dev.classic.js | 30 ++- .../facebook-www/ReactDOMServer-dev.modern.js | 30 ++- .../ReactDOMServer-prod.classic.js | 178 ++++++++++-------- .../ReactDOMServer-prod.modern.js | 162 ++++++++-------- .../ReactDOMServerStreaming-dev.modern.js | 28 ++- .../ReactDOMServerStreaming-prod.modern.js | 120 ++++++------ .../ReactDOMTesting-dev.classic.js | 56 +++++- .../ReactDOMTesting-dev.modern.js | 56 +++++- .../ReactDOMTesting-prod.classic.js | 43 +++-- .../ReactDOMTesting-prod.modern.js | 43 +++-- .../ReactFlightDOMClient-dev.modern.js | 25 ++- .../ReactFlightDOMServer-dev.modern.js | 12 +- .../ReactFlightDOMServer-prod.modern.js | 14 +- .../facebook-www/ReactServer-dev.modern.js | 116 +++++++++--- .../facebook-www/ReactServer-prod.modern.js | 37 ++-- .../ReactTestRenderer-dev.modern.js | 2 +- 35 files changed, 1454 insertions(+), 520 deletions(-) diff --git a/compiled/facebook-www/JSXDEVRuntime-dev.classic.js b/compiled/facebook-www/JSXDEVRuntime-dev.classic.js index deb98b9e19130..7be7a0eea0df9 100644 --- a/compiled/facebook-www/JSXDEVRuntime-dev.classic.js +++ b/compiled/facebook-www/JSXDEVRuntime-dev.classic.js @@ -109,8 +109,8 @@ if (__DEV__) { var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, - enableRenderableContext = dynamicFeatureFlags.enableRenderableContext; - // On WWW, false is used for a new modern build. + enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, false is used for a new modern build. function getWrappedName(outerType, innerType, wrapperName) { var displayName = outerType.displayName; @@ -813,9 +813,11 @@ if (__DEV__) { var specialPropKeyWarningShown; var specialPropRefWarningShown; var didWarnAboutStringRefs; + var didWarnAboutElementRef; { didWarnAboutStringRefs = {}; + didWarnAboutElementRef = {}; } function hasValidRef(config) { @@ -901,7 +903,7 @@ if (__DEV__) { } function defineRefPropWarningGetter(props, displayName) { - { + if (!enableRefAsProp) { { var warnAboutAccessingRef = function () { if (!specialPropRefWarningShown) { @@ -925,6 +927,26 @@ if (__DEV__) { } } } + + function elementRefGetterWithDeprecationWarning() { + { + var componentName = getComponentNameFromType(this.type); + + if (!didWarnAboutElementRef[componentName]) { + didWarnAboutElementRef[componentName] = true; + + error( + "Accessing element.ref is no longer supported. ref is now a " + + "regular prop. It will be removed from the JSX Element " + + "type in a future release." + ); + } // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + var refProp = this.props.ref; + return refProp !== undefined ? refProp : null; + } + } /** * Factory method to create a new React element. This no longer adheres to * the class pattern, so do not use new to call it. Also, instanceof check @@ -949,13 +971,64 @@ if (__DEV__) { function ReactElement(type, key, _ref, self, source, owner, props) { var ref; - { + if (enableRefAsProp) { + // When enableRefAsProp is on, ignore whatever was passed as the ref + // argument and treat `props.ref` as the source of truth. The only thing we + // use this for is `element.ref`, which will log a deprecation warning on + // access. In the next release, we can remove `element.ref` as well as the + // `ref` argument. + var refProp = props.ref; // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + ref = refProp !== undefined ? refProp : null; + } else { ref = _ref; } var element; - { + if (enableRefAsProp) { + // In dev, make `ref` a non-enumerable property with a warning. It's non- + // enumerable so that test matchers and serializers don't access it and + // trigger the warning. + // + // `ref` will be removed from the element completely in a future release. + element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; + + if (ref !== null) { + Object.defineProperty(element, "ref", { + enumerable: false, + get: elementRefGetterWithDeprecationWarning + }); + } else { + // Don't warn on access if a ref is not given. This reduces false + // positives in cases where a test serializer uses + // getOwnPropertyDescriptors to compare objects, like Jest does, which is + // a problem because it bypasses non-enumerability. + // + // So unfortunately this will trigger a false positive warning in Jest + // when the diff is printed: + // + // expect(
).toEqual(); + // + // A bit sketchy, but this is what we've done for the `props.key` and + // `props.ref` accessors for years, which implies it will be good enough + // for `element.ref`, too. Let's see if anyone complains. + Object.defineProperty(element, "ref", { + enumerable: false, + value: null + }); + } + } else { // In prod, `ref` is a regular property. It will be removed in a // future release. element = { @@ -1155,7 +1228,7 @@ if (__DEV__) { } if (hasValidRef(config)) { - { + if (!enableRefAsProp) { ref = config.ref; } @@ -1166,7 +1239,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" + (enableRefAsProp || propName !== "ref") ) { props[propName] = config[propName]; } @@ -1182,7 +1255,7 @@ if (__DEV__) { } } - if (key || ref) { + if (key || (!enableRefAsProp && ref)) { var displayName = typeof type === "function" ? type.displayName || type.name || "Unknown" @@ -1192,7 +1265,7 @@ if (__DEV__) { defineKeyPropWarningGetter(props, displayName); } - if (ref) { + if (!enableRefAsProp && ref) { defineRefPropWarningGetter(props, displayName); } } @@ -1425,7 +1498,7 @@ if (__DEV__) { } } - if (fragment.ref !== null) { + if (!enableRefAsProp && fragment.ref !== null) { setCurrentlyValidatingElement(fragment); error("Invalid attribute `ref` supplied to `React.Fragment`."); diff --git a/compiled/facebook-www/JSXDEVRuntime-dev.modern.js b/compiled/facebook-www/JSXDEVRuntime-dev.modern.js index f432bf9f90373..e840f3f6a5d28 100644 --- a/compiled/facebook-www/JSXDEVRuntime-dev.modern.js +++ b/compiled/facebook-www/JSXDEVRuntime-dev.modern.js @@ -109,8 +109,8 @@ if (__DEV__) { var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, - enableRenderableContext = dynamicFeatureFlags.enableRenderableContext; - // On WWW, true is used for a new modern build. + enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, true is used for a new modern build. function getWrappedName(outerType, innerType, wrapperName) { var displayName = outerType.displayName; @@ -813,9 +813,11 @@ if (__DEV__) { var specialPropKeyWarningShown; var specialPropRefWarningShown; var didWarnAboutStringRefs; + var didWarnAboutElementRef; { didWarnAboutStringRefs = {}; + didWarnAboutElementRef = {}; } function hasValidRef(config) { @@ -901,7 +903,7 @@ if (__DEV__) { } function defineRefPropWarningGetter(props, displayName) { - { + if (!enableRefAsProp) { { var warnAboutAccessingRef = function () { if (!specialPropRefWarningShown) { @@ -925,6 +927,26 @@ if (__DEV__) { } } } + + function elementRefGetterWithDeprecationWarning() { + { + var componentName = getComponentNameFromType(this.type); + + if (!didWarnAboutElementRef[componentName]) { + didWarnAboutElementRef[componentName] = true; + + error( + "Accessing element.ref is no longer supported. ref is now a " + + "regular prop. It will be removed from the JSX Element " + + "type in a future release." + ); + } // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + var refProp = this.props.ref; + return refProp !== undefined ? refProp : null; + } + } /** * Factory method to create a new React element. This no longer adheres to * the class pattern, so do not use new to call it. Also, instanceof check @@ -949,13 +971,64 @@ if (__DEV__) { function ReactElement(type, key, _ref, self, source, owner, props) { var ref; - { + if (enableRefAsProp) { + // When enableRefAsProp is on, ignore whatever was passed as the ref + // argument and treat `props.ref` as the source of truth. The only thing we + // use this for is `element.ref`, which will log a deprecation warning on + // access. In the next release, we can remove `element.ref` as well as the + // `ref` argument. + var refProp = props.ref; // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + ref = refProp !== undefined ? refProp : null; + } else { ref = _ref; } var element; - { + if (enableRefAsProp) { + // In dev, make `ref` a non-enumerable property with a warning. It's non- + // enumerable so that test matchers and serializers don't access it and + // trigger the warning. + // + // `ref` will be removed from the element completely in a future release. + element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; + + if (ref !== null) { + Object.defineProperty(element, "ref", { + enumerable: false, + get: elementRefGetterWithDeprecationWarning + }); + } else { + // Don't warn on access if a ref is not given. This reduces false + // positives in cases where a test serializer uses + // getOwnPropertyDescriptors to compare objects, like Jest does, which is + // a problem because it bypasses non-enumerability. + // + // So unfortunately this will trigger a false positive warning in Jest + // when the diff is printed: + // + // expect(
).toEqual(); + // + // A bit sketchy, but this is what we've done for the `props.key` and + // `props.ref` accessors for years, which implies it will be good enough + // for `element.ref`, too. Let's see if anyone complains. + Object.defineProperty(element, "ref", { + enumerable: false, + value: null + }); + } + } else { // In prod, `ref` is a regular property. It will be removed in a // future release. element = { @@ -1155,7 +1228,7 @@ if (__DEV__) { } if (hasValidRef(config)) { - { + if (!enableRefAsProp) { ref = config.ref; } @@ -1166,7 +1239,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" + (enableRefAsProp || propName !== "ref") ) { props[propName] = config[propName]; } @@ -1182,7 +1255,7 @@ if (__DEV__) { } } - if (key || ref) { + if (key || (!enableRefAsProp && ref)) { var displayName = typeof type === "function" ? type.displayName || type.name || "Unknown" @@ -1192,7 +1265,7 @@ if (__DEV__) { defineKeyPropWarningGetter(props, displayName); } - if (ref) { + if (!enableRefAsProp && ref) { defineRefPropWarningGetter(props, displayName); } } @@ -1425,7 +1498,7 @@ if (__DEV__) { } } - if (fragment.ref !== null) { + if (!enableRefAsProp && fragment.ref !== null) { setCurrentlyValidatingElement(fragment); error("Invalid attribute `ref` supplied to `React.Fragment`."); diff --git a/compiled/facebook-www/REVISION b/compiled/facebook-www/REVISION index 045f850882863..7a563e551204c 100644 --- a/compiled/facebook-www/REVISION +++ b/compiled/facebook-www/REVISION @@ -1 +1 @@ -e4b816ba1a1ea7c1874cf3f82dd841830b71341a +aaf85f3af8c30252edaab5c24975cd086937b2a4 diff --git a/compiled/facebook-www/React-dev.classic.js b/compiled/facebook-www/React-dev.classic.js index f8bd6b8831938..9c8cfb6295ee4 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 = "18.3.0-www-classic-3f51e0fb"; + var ReactVersion = "18.3.0-www-classic-b8eb15b2"; // ATTENTION // When adding new symbols to this file, @@ -475,11 +475,8 @@ if (__DEV__) { var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, - enableRenderableContext = dynamicFeatureFlags.enableRenderableContext; - // On WWW, false is used for a new modern build. - // because JSX is an extremely hot path. - - var enableRefAsProp = false; // Flow magic to verify the exports of this file match the original version. + enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, false is used for a new modern build. function getWrappedName(outerType, innerType, wrapperName) { var displayName = outerType.displayName; @@ -1185,9 +1182,11 @@ if (__DEV__) { var specialPropKeyWarningShown; var specialPropRefWarningShown; var didWarnAboutStringRefs; + var didWarnAboutElementRef; { didWarnAboutStringRefs = {}; + didWarnAboutElementRef = {}; } function hasValidRef(config) { @@ -1273,7 +1272,7 @@ if (__DEV__) { } function defineRefPropWarningGetter(props, displayName) { - { + if (!enableRefAsProp) { { var warnAboutAccessingRef = function () { if (!specialPropRefWarningShown) { @@ -1297,6 +1296,26 @@ if (__DEV__) { } } } + + function elementRefGetterWithDeprecationWarning() { + { + var componentName = getComponentNameFromType(this.type); + + if (!didWarnAboutElementRef[componentName]) { + didWarnAboutElementRef[componentName] = true; + + error( + "Accessing element.ref is no longer supported. ref is now a " + + "regular prop. It will be removed from the JSX Element " + + "type in a future release." + ); + } // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + var refProp = this.props.ref; + return refProp !== undefined ? refProp : null; + } + } /** * Factory method to create a new React element. This no longer adheres to * the class pattern, so do not use new to call it. Also, instanceof check @@ -1321,13 +1340,64 @@ if (__DEV__) { function ReactElement(type, key, _ref, self, source, owner, props) { var ref; - { + if (enableRefAsProp) { + // When enableRefAsProp is on, ignore whatever was passed as the ref + // argument and treat `props.ref` as the source of truth. The only thing we + // use this for is `element.ref`, which will log a deprecation warning on + // access. In the next release, we can remove `element.ref` as well as the + // `ref` argument. + var refProp = props.ref; // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + ref = refProp !== undefined ? refProp : null; + } else { ref = _ref; } var element; - { + if (enableRefAsProp) { + // In dev, make `ref` a non-enumerable property with a warning. It's non- + // enumerable so that test matchers and serializers don't access it and + // trigger the warning. + // + // `ref` will be removed from the element completely in a future release. + element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; + + if (ref !== null) { + Object.defineProperty(element, "ref", { + enumerable: false, + get: elementRefGetterWithDeprecationWarning + }); + } else { + // Don't warn on access if a ref is not given. This reduces false + // positives in cases where a test serializer uses + // getOwnPropertyDescriptors to compare objects, like Jest does, which is + // a problem because it bypasses non-enumerability. + // + // So unfortunately this will trigger a false positive warning in Jest + // when the diff is printed: + // + // expect(
).toEqual(); + // + // A bit sketchy, but this is what we've done for the `props.key` and + // `props.ref` accessors for years, which implies it will be good enough + // for `element.ref`, too. Let's see if anyone complains. + Object.defineProperty(element, "ref", { + enumerable: false, + value: null + }); + } + } else { // In prod, `ref` is a regular property. It will be removed in a // future release. element = { @@ -1563,7 +1633,7 @@ if (__DEV__) { } if (hasValidRef(config)) { - { + if (!enableRefAsProp) { ref = config.ref; } @@ -1574,7 +1644,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" + (enableRefAsProp || propName !== "ref") ) { props[propName] = config[propName]; } @@ -1590,7 +1660,7 @@ if (__DEV__) { } } - if (key || ref) { + if (key || (!enableRefAsProp && ref)) { var displayName = typeof type === "function" ? type.displayName || type.name || "Unknown" @@ -1600,7 +1670,7 @@ if (__DEV__) { defineKeyPropWarningGetter(props, displayName); } - if (ref) { + if (!enableRefAsProp && ref) { defineRefPropWarningGetter(props, displayName); } } @@ -1701,7 +1771,7 @@ if (__DEV__) { if (config != null) { if (hasValidRef(config)) { - { + if (!enableRefAsProp) { ref = config.ref; } @@ -1722,7 +1792,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" && // Even though we don't use these anymore in the runtime, we don't want + (enableRefAsProp || propName !== "ref") && // Even though we don't use these anymore in the runtime, we don't want // them to appear as props, so in createElement we filter them out. // We don't have to do this in the jsx() runtime because the jsx() // transform never passed these as props; it used separate arguments. @@ -1766,7 +1836,7 @@ if (__DEV__) { } { - if (key || ref) { + if (key || (!enableRefAsProp && ref)) { var displayName = typeof type === "function" ? type.displayName || type.name || "Unknown" @@ -1776,7 +1846,7 @@ if (__DEV__) { defineKeyPropWarningGetter(props, displayName); } - if (ref) { + if (!enableRefAsProp && ref) { defineRefPropWarningGetter(props, displayName); } } @@ -1847,7 +1917,7 @@ if (__DEV__) { oldElement.type, newKey, // When enableRefAsProp is on, this argument is ignored. This check only // exists to avoid the `ref` access warning. - oldElement.ref, + enableRefAsProp ? null : oldElement.ref, undefined, undefined, oldElement._owner, @@ -1873,13 +1943,13 @@ if (__DEV__) { var props = assign({}, element.props); // Reserved names are extracted var key = element.key; - var ref = element.ref; // Owner will be preserved, unless ref is overridden + var ref = enableRefAsProp ? null : element.ref; // Owner will be preserved, unless ref is overridden var owner = element._owner; if (config != null) { if (hasValidRef(config)) { - { + if (!enableRefAsProp) { // Silently steal the ref from the parent. ref = config.ref; } @@ -1905,7 +1975,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" && // ...and maybe these, too, though we currently rely on them for + (enableRefAsProp || propName !== "ref") && // ...and maybe these, too, though we currently rely on them for // warnings and debug information in dev. Need to decide if we're OK // with dropping them. In the jsx() runtime it's not an issue because // the data gets passed as separate arguments instead of props, but @@ -1915,7 +1985,7 @@ if (__DEV__) { propName !== "__source" && // Undefined `ref` is ignored by cloneElement. We treat it the same as // if the property were missing. This is mostly for // backwards compatibility. - !enableRefAsProp + !(enableRefAsProp && propName === "ref" && config.ref === undefined) ) { if (config[propName] === undefined && defaultProps !== undefined) { // Resolve default props @@ -2177,7 +2247,7 @@ if (__DEV__) { } } - if (fragment.ref !== null) { + if (!enableRefAsProp && fragment.ref !== null) { setCurrentlyValidatingElement(fragment); error("Invalid attribute `ref` supplied to `React.Fragment`."); diff --git a/compiled/facebook-www/React-dev.modern.js b/compiled/facebook-www/React-dev.modern.js index a28d3952d97f4..70e47f5190e19 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 = "18.3.0-www-modern-5e309987"; + var ReactVersion = "18.3.0-www-modern-5ca55b0c"; // ATTENTION // When adding new symbols to this file, @@ -475,11 +475,8 @@ if (__DEV__) { var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, - enableRenderableContext = dynamicFeatureFlags.enableRenderableContext; - // On WWW, true is used for a new modern build. - // because JSX is an extremely hot path. - - var enableRefAsProp = false; // Flow magic to verify the exports of this file match the original version. + enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, true is used for a new modern build. function getWrappedName(outerType, innerType, wrapperName) { var displayName = outerType.displayName; @@ -1185,9 +1182,11 @@ if (__DEV__) { var specialPropKeyWarningShown; var specialPropRefWarningShown; var didWarnAboutStringRefs; + var didWarnAboutElementRef; { didWarnAboutStringRefs = {}; + didWarnAboutElementRef = {}; } function hasValidRef(config) { @@ -1273,7 +1272,7 @@ if (__DEV__) { } function defineRefPropWarningGetter(props, displayName) { - { + if (!enableRefAsProp) { { var warnAboutAccessingRef = function () { if (!specialPropRefWarningShown) { @@ -1297,6 +1296,26 @@ if (__DEV__) { } } } + + function elementRefGetterWithDeprecationWarning() { + { + var componentName = getComponentNameFromType(this.type); + + if (!didWarnAboutElementRef[componentName]) { + didWarnAboutElementRef[componentName] = true; + + error( + "Accessing element.ref is no longer supported. ref is now a " + + "regular prop. It will be removed from the JSX Element " + + "type in a future release." + ); + } // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + var refProp = this.props.ref; + return refProp !== undefined ? refProp : null; + } + } /** * Factory method to create a new React element. This no longer adheres to * the class pattern, so do not use new to call it. Also, instanceof check @@ -1321,13 +1340,64 @@ if (__DEV__) { function ReactElement(type, key, _ref, self, source, owner, props) { var ref; - { + if (enableRefAsProp) { + // When enableRefAsProp is on, ignore whatever was passed as the ref + // argument and treat `props.ref` as the source of truth. The only thing we + // use this for is `element.ref`, which will log a deprecation warning on + // access. In the next release, we can remove `element.ref` as well as the + // `ref` argument. + var refProp = props.ref; // An undefined `element.ref` is coerced to `null` for + // backwards compatibility. + + ref = refProp !== undefined ? refProp : null; + } else { ref = _ref; } var element; - { + if (enableRefAsProp) { + // In dev, make `ref` a non-enumerable property with a warning. It's non- + // enumerable so that test matchers and serializers don't access it and + // trigger the warning. + // + // `ref` will be removed from the element completely in a future release. + element = { + // This tag allows us to uniquely identify this as a React Element + $$typeof: REACT_ELEMENT_TYPE, + // Built-in properties that belong on the element + type: type, + key: key, + props: props, + // Record the component responsible for creating this element. + _owner: owner + }; + + if (ref !== null) { + Object.defineProperty(element, "ref", { + enumerable: false, + get: elementRefGetterWithDeprecationWarning + }); + } else { + // Don't warn on access if a ref is not given. This reduces false + // positives in cases where a test serializer uses + // getOwnPropertyDescriptors to compare objects, like Jest does, which is + // a problem because it bypasses non-enumerability. + // + // So unfortunately this will trigger a false positive warning in Jest + // when the diff is printed: + // + // expect(
).toEqual(); + // + // A bit sketchy, but this is what we've done for the `props.key` and + // `props.ref` accessors for years, which implies it will be good enough + // for `element.ref`, too. Let's see if anyone complains. + Object.defineProperty(element, "ref", { + enumerable: false, + value: null + }); + } + } else { // In prod, `ref` is a regular property. It will be removed in a // future release. element = { @@ -1563,7 +1633,7 @@ if (__DEV__) { } if (hasValidRef(config)) { - { + if (!enableRefAsProp) { ref = config.ref; } @@ -1574,7 +1644,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" + (enableRefAsProp || propName !== "ref") ) { props[propName] = config[propName]; } @@ -1590,7 +1660,7 @@ if (__DEV__) { } } - if (key || ref) { + if (key || (!enableRefAsProp && ref)) { var displayName = typeof type === "function" ? type.displayName || type.name || "Unknown" @@ -1600,7 +1670,7 @@ if (__DEV__) { defineKeyPropWarningGetter(props, displayName); } - if (ref) { + if (!enableRefAsProp && ref) { defineRefPropWarningGetter(props, displayName); } } @@ -1701,7 +1771,7 @@ if (__DEV__) { if (config != null) { if (hasValidRef(config)) { - { + if (!enableRefAsProp) { ref = config.ref; } @@ -1722,7 +1792,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" && // Even though we don't use these anymore in the runtime, we don't want + (enableRefAsProp || propName !== "ref") && // Even though we don't use these anymore in the runtime, we don't want // them to appear as props, so in createElement we filter them out. // We don't have to do this in the jsx() runtime because the jsx() // transform never passed these as props; it used separate arguments. @@ -1766,7 +1836,7 @@ if (__DEV__) { } { - if (key || ref) { + if (key || (!enableRefAsProp && ref)) { var displayName = typeof type === "function" ? type.displayName || type.name || "Unknown" @@ -1776,7 +1846,7 @@ if (__DEV__) { defineKeyPropWarningGetter(props, displayName); } - if (ref) { + if (!enableRefAsProp && ref) { defineRefPropWarningGetter(props, displayName); } } @@ -1803,7 +1873,7 @@ if (__DEV__) { oldElement.type, newKey, // When enableRefAsProp is on, this argument is ignored. This check only // exists to avoid the `ref` access warning. - oldElement.ref, + enableRefAsProp ? null : oldElement.ref, undefined, undefined, oldElement._owner, @@ -1829,13 +1899,13 @@ if (__DEV__) { var props = assign({}, element.props); // Reserved names are extracted var key = element.key; - var ref = element.ref; // Owner will be preserved, unless ref is overridden + var ref = enableRefAsProp ? null : element.ref; // Owner will be preserved, unless ref is overridden var owner = element._owner; if (config != null) { if (hasValidRef(config)) { - { + if (!enableRefAsProp) { // Silently steal the ref from the parent. ref = config.ref; } @@ -1861,7 +1931,7 @@ if (__DEV__) { if ( hasOwnProperty.call(config, propName) && // Skip over reserved prop names propName !== "key" && - propName !== "ref" && // ...and maybe these, too, though we currently rely on them for + (enableRefAsProp || propName !== "ref") && // ...and maybe these, too, though we currently rely on them for // warnings and debug information in dev. Need to decide if we're OK // with dropping them. In the jsx() runtime it's not an issue because // the data gets passed as separate arguments instead of props, but @@ -1871,7 +1941,7 @@ if (__DEV__) { propName !== "__source" && // Undefined `ref` is ignored by cloneElement. We treat it the same as // if the property were missing. This is mostly for // backwards compatibility. - !enableRefAsProp + !(enableRefAsProp && propName === "ref" && config.ref === undefined) ) { if (config[propName] === undefined && defaultProps !== undefined) { // Resolve default props @@ -2133,7 +2203,7 @@ if (__DEV__) { } } - if (fragment.ref !== null) { + if (!enableRefAsProp && fragment.ref !== null) { setCurrentlyValidatingElement(fragment); error("Invalid attribute `ref` supplied to `React.Fragment`."); diff --git a/compiled/facebook-www/React-prod.classic.js b/compiled/facebook-www/React-prod.classic.js index 9703f5f5f1462..a07c7c447296b 100644 --- a/compiled/facebook-www/React-prod.classic.js +++ b/compiled/facebook-www/React-prod.classic.js @@ -85,6 +85,7 @@ var isArrayImpl = Array.isArray, dynamicFeatureFlags = require("ReactFeatureFlags"), enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, ReactCurrentDispatcher = { current: null }, ReactCurrentCache = { current: null }, ReactCurrentBatchConfig = { transition: null }, @@ -97,6 +98,8 @@ var isArrayImpl = Array.isArray, hasOwnProperty = Object.prototype.hasOwnProperty, ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function ReactElement(type, key, _ref, self, source, owner, props) { + enableRefAsProp && + ((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null)); return { $$typeof: REACT_ELEMENT_TYPE, type: type, @@ -113,11 +116,11 @@ function jsxProd(type, config, maybeKey) { ref = null; void 0 !== maybeKey && (key = "" + maybeKey); void 0 !== config.key && (key = "" + config.key); - void 0 !== config.ref && (ref = config.ref); + void 0 === config.ref || enableRefAsProp || (ref = config.ref); for (propName in config) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && (props[propName] = config[propName]); if (type && type.defaultProps) for (propName in ((config = type.defaultProps), config)) @@ -138,12 +141,14 @@ function createElement(type, config, children) { key = null, ref = null; if (null != config) - for (propName in (void 0 !== config.ref && (ref = config.ref), + for (propName in (void 0 === config.ref || + enableRefAsProp || + (ref = config.ref), void 0 !== config.key && (key = "" + config.key), config)) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && "__self" !== propName && "__source" !== propName && (props[propName] = config[propName]); @@ -172,7 +177,7 @@ function cloneAndReplaceKey(oldElement, newKey) { return ReactElement( oldElement.type, newKey, - oldElement.ref, + enableRefAsProp ? null : oldElement.ref, void 0, void 0, oldElement._owner, @@ -434,20 +439,22 @@ exports.cloneElement = function (element, config, children) { ); var props = assign({}, element.props), key = element.key, - ref = element.ref, + ref = enableRefAsProp ? null : element.ref, owner = element._owner; if (null != config) { void 0 !== config.ref && - ((ref = config.ref), (owner = ReactCurrentOwner.current)); + (enableRefAsProp || (ref = config.ref), + (owner = ReactCurrentOwner.current)); void 0 !== config.key && (key = "" + config.key); if (element.type && element.type.defaultProps) var defaultProps = element.type.defaultProps; for (propName in config) - hasOwnProperty.call(config, propName) && - "key" !== propName && - "ref" !== propName && - "__self" !== propName && - "__source" !== propName && + !hasOwnProperty.call(config, propName) || + "key" === propName || + (!enableRefAsProp && "ref" === propName) || + "__self" === propName || + "__source" === propName || + (enableRefAsProp && "ref" === propName && void 0 === config.ref) || (props[propName] = void 0 === config[propName] && void 0 !== defaultProps ? defaultProps[propName] @@ -628,4 +635,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-classic-8284b06d"; +exports.version = "18.3.0-www-classic-523eda18"; diff --git a/compiled/facebook-www/React-prod.modern.js b/compiled/facebook-www/React-prod.modern.js index 69ade073dbb7d..ae4f620bb39ad 100644 --- a/compiled/facebook-www/React-prod.modern.js +++ b/compiled/facebook-www/React-prod.modern.js @@ -84,6 +84,7 @@ var isArrayImpl = Array.isArray, dynamicFeatureFlags = require("ReactFeatureFlags"), enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, ReactCurrentDispatcher = { current: null }, ReactCurrentCache = { current: null }, ReactCurrentBatchConfig = { transition: null }, @@ -96,6 +97,8 @@ var isArrayImpl = Array.isArray, hasOwnProperty = Object.prototype.hasOwnProperty, ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function ReactElement(type, key, _ref, self, source, owner, props) { + enableRefAsProp && + ((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null)); return { $$typeof: REACT_ELEMENT_TYPE, type: type, @@ -112,11 +115,11 @@ function jsxProd(type, config, maybeKey) { ref = null; void 0 !== maybeKey && (key = "" + maybeKey); void 0 !== config.key && (key = "" + config.key); - void 0 !== config.ref && (ref = config.ref); + void 0 === config.ref || enableRefAsProp || (ref = config.ref); for (propName in config) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && (props[propName] = config[propName]); if (type && type.defaultProps) for (propName in ((config = type.defaultProps), config)) @@ -135,7 +138,7 @@ function cloneAndReplaceKey(oldElement, newKey) { return ReactElement( oldElement.type, newKey, - oldElement.ref, + enableRefAsProp ? null : oldElement.ref, void 0, void 0, oldElement._owner, @@ -397,20 +400,22 @@ exports.cloneElement = function (element, config, children) { ); var props = assign({}, element.props), key = element.key, - ref = element.ref, + ref = enableRefAsProp ? null : element.ref, owner = element._owner; if (null != config) { void 0 !== config.ref && - ((ref = config.ref), (owner = ReactCurrentOwner.current)); + (enableRefAsProp || (ref = config.ref), + (owner = ReactCurrentOwner.current)); void 0 !== config.key && (key = "" + config.key); if (element.type && element.type.defaultProps) var defaultProps = element.type.defaultProps; for (propName in config) - hasOwnProperty.call(config, propName) && - "key" !== propName && - "ref" !== propName && - "__self" !== propName && - "__source" !== propName && + !hasOwnProperty.call(config, propName) || + "key" === propName || + (!enableRefAsProp && "ref" === propName) || + "__self" === propName || + "__source" === propName || + (enableRefAsProp && "ref" === propName && void 0 === config.ref) || (props[propName] = void 0 === config[propName] && void 0 !== defaultProps ? defaultProps[propName] @@ -453,12 +458,14 @@ exports.createElement = function (type, config, children) { key = null, ref = null; if (null != config) - for (propName in (void 0 !== config.ref && (ref = config.ref), + for (propName in (void 0 === config.ref || + enableRefAsProp || + (ref = config.ref), void 0 !== config.key && (key = "" + config.key), config)) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && "__self" !== propName && "__source" !== propName && (props[propName] = config[propName]); @@ -620,4 +627,4 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-modern-eb7ac9a1"; +exports.version = "18.3.0-www-modern-16a3d0dd"; diff --git a/compiled/facebook-www/React-profiling.classic.js b/compiled/facebook-www/React-profiling.classic.js index e96c7ad0d8690..6b93899284094 100644 --- a/compiled/facebook-www/React-profiling.classic.js +++ b/compiled/facebook-www/React-profiling.classic.js @@ -89,6 +89,7 @@ var isArrayImpl = Array.isArray, dynamicFeatureFlags = require("ReactFeatureFlags"), enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, ReactCurrentDispatcher = { current: null }, ReactCurrentCache = { current: null }, ReactCurrentBatchConfig = { transition: null }, @@ -101,6 +102,8 @@ var isArrayImpl = Array.isArray, hasOwnProperty = Object.prototype.hasOwnProperty, ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function ReactElement(type, key, _ref, self, source, owner, props) { + enableRefAsProp && + ((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null)); return { $$typeof: REACT_ELEMENT_TYPE, type: type, @@ -117,11 +120,11 @@ function jsxProd(type, config, maybeKey) { ref = null; void 0 !== maybeKey && (key = "" + maybeKey); void 0 !== config.key && (key = "" + config.key); - void 0 !== config.ref && (ref = config.ref); + void 0 === config.ref || enableRefAsProp || (ref = config.ref); for (propName in config) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && (props[propName] = config[propName]); if (type && type.defaultProps) for (propName in ((config = type.defaultProps), config)) @@ -142,12 +145,14 @@ function createElement(type, config, children) { key = null, ref = null; if (null != config) - for (propName in (void 0 !== config.ref && (ref = config.ref), + for (propName in (void 0 === config.ref || + enableRefAsProp || + (ref = config.ref), void 0 !== config.key && (key = "" + config.key), config)) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && "__self" !== propName && "__source" !== propName && (props[propName] = config[propName]); @@ -176,7 +181,7 @@ function cloneAndReplaceKey(oldElement, newKey) { return ReactElement( oldElement.type, newKey, - oldElement.ref, + enableRefAsProp ? null : oldElement.ref, void 0, void 0, oldElement._owner, @@ -438,20 +443,22 @@ exports.cloneElement = function (element, config, children) { ); var props = assign({}, element.props), key = element.key, - ref = element.ref, + ref = enableRefAsProp ? null : element.ref, owner = element._owner; if (null != config) { void 0 !== config.ref && - ((ref = config.ref), (owner = ReactCurrentOwner.current)); + (enableRefAsProp || (ref = config.ref), + (owner = ReactCurrentOwner.current)); void 0 !== config.key && (key = "" + config.key); if (element.type && element.type.defaultProps) var defaultProps = element.type.defaultProps; for (propName in config) - hasOwnProperty.call(config, propName) && - "key" !== propName && - "ref" !== propName && - "__self" !== propName && - "__source" !== propName && + !hasOwnProperty.call(config, propName) || + "key" === propName || + (!enableRefAsProp && "ref" === propName) || + "__self" === propName || + "__source" === propName || + (enableRefAsProp && "ref" === propName && void 0 === config.ref) || (props[propName] = void 0 === config[propName] && void 0 !== defaultProps ? defaultProps[propName] @@ -632,7 +639,7 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-classic-9d08c2e5"; +exports.version = "18.3.0-www-classic-d95f23f2"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/compiled/facebook-www/React-profiling.modern.js b/compiled/facebook-www/React-profiling.modern.js index 74c53d64da221..82685169134d7 100644 --- a/compiled/facebook-www/React-profiling.modern.js +++ b/compiled/facebook-www/React-profiling.modern.js @@ -88,6 +88,7 @@ var isArrayImpl = Array.isArray, dynamicFeatureFlags = require("ReactFeatureFlags"), enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, ReactCurrentDispatcher = { current: null }, ReactCurrentCache = { current: null }, ReactCurrentBatchConfig = { transition: null }, @@ -100,6 +101,8 @@ var isArrayImpl = Array.isArray, hasOwnProperty = Object.prototype.hasOwnProperty, ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function ReactElement(type, key, _ref, self, source, owner, props) { + enableRefAsProp && + ((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null)); return { $$typeof: REACT_ELEMENT_TYPE, type: type, @@ -116,11 +119,11 @@ function jsxProd(type, config, maybeKey) { ref = null; void 0 !== maybeKey && (key = "" + maybeKey); void 0 !== config.key && (key = "" + config.key); - void 0 !== config.ref && (ref = config.ref); + void 0 === config.ref || enableRefAsProp || (ref = config.ref); for (propName in config) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && (props[propName] = config[propName]); if (type && type.defaultProps) for (propName in ((config = type.defaultProps), config)) @@ -139,7 +142,7 @@ function cloneAndReplaceKey(oldElement, newKey) { return ReactElement( oldElement.type, newKey, - oldElement.ref, + enableRefAsProp ? null : oldElement.ref, void 0, void 0, oldElement._owner, @@ -401,20 +404,22 @@ exports.cloneElement = function (element, config, children) { ); var props = assign({}, element.props), key = element.key, - ref = element.ref, + ref = enableRefAsProp ? null : element.ref, owner = element._owner; if (null != config) { void 0 !== config.ref && - ((ref = config.ref), (owner = ReactCurrentOwner.current)); + (enableRefAsProp || (ref = config.ref), + (owner = ReactCurrentOwner.current)); void 0 !== config.key && (key = "" + config.key); if (element.type && element.type.defaultProps) var defaultProps = element.type.defaultProps; for (propName in config) - hasOwnProperty.call(config, propName) && - "key" !== propName && - "ref" !== propName && - "__self" !== propName && - "__source" !== propName && + !hasOwnProperty.call(config, propName) || + "key" === propName || + (!enableRefAsProp && "ref" === propName) || + "__self" === propName || + "__source" === propName || + (enableRefAsProp && "ref" === propName && void 0 === config.ref) || (props[propName] = void 0 === config[propName] && void 0 !== defaultProps ? defaultProps[propName] @@ -457,12 +462,14 @@ exports.createElement = function (type, config, children) { key = null, ref = null; if (null != config) - for (propName in (void 0 !== config.ref && (ref = config.ref), + for (propName in (void 0 === config.ref || + enableRefAsProp || + (ref = config.ref), void 0 !== config.key && (key = "" + config.key), config)) hasOwnProperty.call(config, propName) && "key" !== propName && - "ref" !== propName && + (enableRefAsProp || "ref" !== propName) && "__self" !== propName && "__source" !== propName && (props[propName] = config[propName]); @@ -624,7 +631,7 @@ exports.useSyncExternalStore = function ( exports.useTransition = function () { return ReactCurrentDispatcher.current.useTransition(); }; -exports.version = "18.3.0-www-modern-df6fe9f7"; +exports.version = "18.3.0-www-modern-12626cf3"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/compiled/facebook-www/ReactART-dev.classic.js b/compiled/facebook-www/ReactART-dev.classic.js index af733f64a46e6..78eeaab49b6af 100644 --- a/compiled/facebook-www/ReactART-dev.classic.js +++ b/compiled/facebook-www/ReactART-dev.classic.js @@ -66,7 +66,7 @@ if (__DEV__) { return self; } - var ReactVersion = "18.3.0-www-classic-cbef9601"; + var ReactVersion = "18.3.0-www-classic-2f254d96"; var LegacyRoot = 0; var ConcurrentRoot = 1; @@ -188,7 +188,8 @@ if (__DEV__) { enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, - useModernStrictMode = dynamicFeatureFlags.useModernStrictMode; // On WWW, false is used for a new modern build. + useModernStrictMode = dynamicFeatureFlags.useModernStrictMode, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, false is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; @@ -6458,7 +6459,13 @@ if (__DEV__) { function coerceRef(returnFiber, current, workInProgress, element) { var mixedRef; - { + if (enableRefAsProp) { + // TODO: This is a temporary, intermediate step. When enableRefAsProp is on, + // we should resolve the `ref` prop during the begin phase of the component + // it's attached to (HostComponent, ClassComponent, etc). + var refProp = element.props.ref; + mixedRef = refProp !== undefined ? refProp : null; + } else { // Old behavior. mixedRef = element.ref; } @@ -6478,6 +6485,31 @@ if (__DEV__) { element, mixedRef ); + + if (enableRefAsProp) { + // When enableRefAsProp is on, we should always use the props as the + // source of truth for refs. Not a field on the fiber. + // + // In the case of string refs, this presents a problem, because string + // refs are not passed around internally as strings; they are converted to + // callback refs. The ref used by the reconciler is not the same as the + // one the user provided. + // + // But since this is a deprecated feature anyway, what we can do is clone + // the props object and replace it with the internal callback ref. Then we + // can continue to use the props object as the source of truth. + // + // This means the internal callback ref will leak into userspace. The + // receiving component will receive a callback ref even though the parent + // passed a string. Which is weird, but again, this is a deprecated + // feature, and we're only leaving it around behind a flag so that Meta + // can keep using string refs temporarily while they finish migrating + // their codebase. + var userProvidedProps = workInProgress.pendingProps; + var propsWithInternalCallbackRef = assign({}, userProvidedProps); + propsWithInternalCallbackRef.ref = coercedRef; + workInProgress.pendingProps = propsWithInternalCallbackRef; + } } else { coercedRef = mixedRef; } // TODO: If enableRefAsProp is on, we shouldn't use the `ref` field. We @@ -14678,7 +14710,21 @@ if (__DEV__) { var ref = workInProgress.ref; var propsWithoutRef; - { + if (enableRefAsProp && "ref" in nextProps) { + // `ref` is just a prop now, but `forwardRef` expects it to not appear in + // the props object. This used to happen in the JSX runtime, but now we do + // it here. + propsWithoutRef = {}; + + for (var key in nextProps) { + // Since `ref` should only appear in props via the JSX transform, we can + // assume that this is a plain object. So we don't need a + // hasOwnProperty check. + if (key !== "ref") { + propsWithoutRef[key] = nextProps[key]; + } + } + } else { propsWithoutRef = nextProps; } // The rest is a fork of updateFunctionComponent @@ -16005,7 +16051,7 @@ if (__DEV__) { } } - if (workInProgress.ref !== null) { + if (!enableRefAsProp && workInProgress.ref !== null) { var info = ""; var componentName = getComponentNameFromType(Component) || "Unknown"; var ownerName = getCurrentFiberOwnerNameInDevOrNull(); diff --git a/compiled/facebook-www/ReactART-dev.modern.js b/compiled/facebook-www/ReactART-dev.modern.js index 58f45a7b13cc4..93e27daf402a3 100644 --- a/compiled/facebook-www/ReactART-dev.modern.js +++ b/compiled/facebook-www/ReactART-dev.modern.js @@ -66,7 +66,7 @@ if (__DEV__) { return self; } - var ReactVersion = "18.3.0-www-modern-e9e265be"; + var ReactVersion = "18.3.0-www-modern-388a31ab"; var LegacyRoot = 0; var ConcurrentRoot = 1; @@ -188,7 +188,8 @@ if (__DEV__) { enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, - useModernStrictMode = dynamicFeatureFlags.useModernStrictMode; // On WWW, true is used for a new modern build. + useModernStrictMode = dynamicFeatureFlags.useModernStrictMode, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, true is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; @@ -6223,7 +6224,13 @@ if (__DEV__) { function coerceRef(returnFiber, current, workInProgress, element) { var mixedRef; - { + if (enableRefAsProp) { + // TODO: This is a temporary, intermediate step. When enableRefAsProp is on, + // we should resolve the `ref` prop during the begin phase of the component + // it's attached to (HostComponent, ClassComponent, etc). + var refProp = element.props.ref; + mixedRef = refProp !== undefined ? refProp : null; + } else { // Old behavior. mixedRef = element.ref; } @@ -6243,6 +6250,31 @@ if (__DEV__) { element, mixedRef ); + + if (enableRefAsProp) { + // When enableRefAsProp is on, we should always use the props as the + // source of truth for refs. Not a field on the fiber. + // + // In the case of string refs, this presents a problem, because string + // refs are not passed around internally as strings; they are converted to + // callback refs. The ref used by the reconciler is not the same as the + // one the user provided. + // + // But since this is a deprecated feature anyway, what we can do is clone + // the props object and replace it with the internal callback ref. Then we + // can continue to use the props object as the source of truth. + // + // This means the internal callback ref will leak into userspace. The + // receiving component will receive a callback ref even though the parent + // passed a string. Which is weird, but again, this is a deprecated + // feature, and we're only leaving it around behind a flag so that Meta + // can keep using string refs temporarily while they finish migrating + // their codebase. + var userProvidedProps = workInProgress.pendingProps; + var propsWithInternalCallbackRef = assign({}, userProvidedProps); + propsWithInternalCallbackRef.ref = coercedRef; + workInProgress.pendingProps = propsWithInternalCallbackRef; + } } else { coercedRef = mixedRef; } // TODO: If enableRefAsProp is on, we shouldn't use the `ref` field. We @@ -14402,7 +14434,21 @@ if (__DEV__) { var ref = workInProgress.ref; var propsWithoutRef; - { + if (enableRefAsProp && "ref" in nextProps) { + // `ref` is just a prop now, but `forwardRef` expects it to not appear in + // the props object. This used to happen in the JSX runtime, but now we do + // it here. + propsWithoutRef = {}; + + for (var key in nextProps) { + // Since `ref` should only appear in props via the JSX transform, we can + // assume that this is a plain object. So we don't need a + // hasOwnProperty check. + if (key !== "ref") { + propsWithoutRef[key] = nextProps[key]; + } + } + } else { propsWithoutRef = nextProps; } // The rest is a fork of updateFunctionComponent @@ -15699,7 +15745,7 @@ if (__DEV__) { } } - if (workInProgress.ref !== null) { + if (!enableRefAsProp && workInProgress.ref !== null) { var info = ""; var componentName = getComponentNameFromType(Component) || "Unknown"; var ownerName = getCurrentFiberOwnerNameInDevOrNull(); diff --git a/compiled/facebook-www/ReactART-prod.classic.js b/compiled/facebook-www/ReactART-prod.classic.js index aa6d947060a80..ca1787d1b8082 100644 --- a/compiled/facebook-www/ReactART-prod.classic.js +++ b/compiled/facebook-www/ReactART-prod.classic.js @@ -84,6 +84,7 @@ var ReactSharedInternals = enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -1864,13 +1865,24 @@ function convertStringRefToCallbackRef( return ref; } function coerceRef(returnFiber, current, workInProgress, element) { - var mixedRef = element.ref; - returnFiber = - null !== mixedRef && - "function" !== typeof mixedRef && - "object" !== typeof mixedRef - ? convertStringRefToCallbackRef(returnFiber, current, element, mixedRef) - : mixedRef; + if (enableRefAsProp) { + var mixedRef = element.props.ref; + mixedRef = void 0 !== mixedRef ? mixedRef : null; + } else mixedRef = element.ref; + null !== mixedRef && + "function" !== typeof mixedRef && + "object" !== typeof mixedRef + ? ((returnFiber = convertStringRefToCallbackRef( + returnFiber, + current, + element, + mixedRef + )), + enableRefAsProp && + ((current = assign({}, workInProgress.pendingProps)), + (current.ref = returnFiber), + (workInProgress.pendingProps = current))) + : (returnFiber = mixedRef); workInProgress.ref = returnFiber; } function throwOnInvalidObjectType(returnFiber, newChild) { @@ -4378,12 +4390,17 @@ function updateForwardRef( ) { Component = Component.render; var ref = workInProgress.ref; + if (enableRefAsProp && "ref" in nextProps) { + var propsWithoutRef = {}; + for (var key in nextProps) + "ref" !== key && (propsWithoutRef[key] = nextProps[key]); + } else propsWithoutRef = nextProps; prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, - nextProps, + propsWithoutRef, ref, renderLanes ); @@ -10577,7 +10594,7 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "18.3.0-www-classic-ca1292bb", + version: "18.3.0-www-classic-36516bcc", rendererPackageName: "react-art" }; var internals$jscomp$inline_1320 = { @@ -10608,7 +10625,7 @@ var internals$jscomp$inline_1320 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-classic-ca1292bb" + reconcilerVersion: "18.3.0-www-classic-36516bcc" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1321 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/compiled/facebook-www/ReactART-prod.modern.js b/compiled/facebook-www/ReactART-prod.modern.js index e56a8c2d01136..b11e58662f2de 100644 --- a/compiled/facebook-www/ReactART-prod.modern.js +++ b/compiled/facebook-www/ReactART-prod.modern.js @@ -84,6 +84,7 @@ var ReactSharedInternals = enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -1660,13 +1661,24 @@ function convertStringRefToCallbackRef( return ref; } function coerceRef(returnFiber, current, workInProgress, element) { - var mixedRef = element.ref; - returnFiber = - null !== mixedRef && - "function" !== typeof mixedRef && - "object" !== typeof mixedRef - ? convertStringRefToCallbackRef(returnFiber, current, element, mixedRef) - : mixedRef; + if (enableRefAsProp) { + var mixedRef = element.props.ref; + mixedRef = void 0 !== mixedRef ? mixedRef : null; + } else mixedRef = element.ref; + null !== mixedRef && + "function" !== typeof mixedRef && + "object" !== typeof mixedRef + ? ((returnFiber = convertStringRefToCallbackRef( + returnFiber, + current, + element, + mixedRef + )), + enableRefAsProp && + ((current = assign({}, workInProgress.pendingProps)), + (current.ref = returnFiber), + (workInProgress.pendingProps = current))) + : (returnFiber = mixedRef); workInProgress.ref = returnFiber; } function throwOnInvalidObjectType(returnFiber, newChild) { @@ -4159,12 +4171,17 @@ function updateForwardRef( ) { Component = Component.render; var ref = workInProgress.ref; + if (enableRefAsProp && "ref" in nextProps) { + var propsWithoutRef = {}; + for (var key in nextProps) + "ref" !== key && (propsWithoutRef[key] = nextProps[key]); + } else propsWithoutRef = nextProps; prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, - nextProps, + propsWithoutRef, ref, renderLanes ); @@ -10232,7 +10249,7 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "18.3.0-www-modern-0a467636", + version: "18.3.0-www-modern-630a2790", rendererPackageName: "react-art" }; var internals$jscomp$inline_1300 = { @@ -10263,7 +10280,7 @@ var internals$jscomp$inline_1300 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-modern-0a467636" + reconcilerVersion: "18.3.0-www-modern-630a2790" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1301 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/compiled/facebook-www/ReactDOM-dev.classic.js b/compiled/facebook-www/ReactDOM-dev.classic.js index 525d438307bbc..d5c6059dd6d6b 100644 --- a/compiled/facebook-www/ReactDOM-dev.classic.js +++ b/compiled/facebook-www/ReactDOM-dev.classic.js @@ -153,7 +153,8 @@ if (__DEV__) { enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, - useModernStrictMode = dynamicFeatureFlags.useModernStrictMode; // On WWW, false is used for a new modern build. + useModernStrictMode = dynamicFeatureFlags.useModernStrictMode, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, false is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; @@ -11105,7 +11106,13 @@ if (__DEV__) { function coerceRef(returnFiber, current, workInProgress, element) { var mixedRef; - { + if (enableRefAsProp) { + // TODO: This is a temporary, intermediate step. When enableRefAsProp is on, + // we should resolve the `ref` prop during the begin phase of the component + // it's attached to (HostComponent, ClassComponent, etc). + var refProp = element.props.ref; + mixedRef = refProp !== undefined ? refProp : null; + } else { // Old behavior. mixedRef = element.ref; } @@ -11125,6 +11132,31 @@ if (__DEV__) { element, mixedRef ); + + if (enableRefAsProp) { + // When enableRefAsProp is on, we should always use the props as the + // source of truth for refs. Not a field on the fiber. + // + // In the case of string refs, this presents a problem, because string + // refs are not passed around internally as strings; they are converted to + // callback refs. The ref used by the reconciler is not the same as the + // one the user provided. + // + // But since this is a deprecated feature anyway, what we can do is clone + // the props object and replace it with the internal callback ref. Then we + // can continue to use the props object as the source of truth. + // + // This means the internal callback ref will leak into userspace. The + // receiving component will receive a callback ref even though the parent + // passed a string. Which is weird, but again, this is a deprecated + // feature, and we're only leaving it around behind a flag so that Meta + // can keep using string refs temporarily while they finish migrating + // their codebase. + var userProvidedProps = workInProgress.pendingProps; + var propsWithInternalCallbackRef = assign({}, userProvidedProps); + propsWithInternalCallbackRef.ref = coercedRef; + workInProgress.pendingProps = propsWithInternalCallbackRef; + } } else { coercedRef = mixedRef; } // TODO: If enableRefAsProp is on, we shouldn't use the `ref` field. We @@ -19551,7 +19583,21 @@ if (__DEV__) { var ref = workInProgress.ref; var propsWithoutRef; - { + if (enableRefAsProp && "ref" in nextProps) { + // `ref` is just a prop now, but `forwardRef` expects it to not appear in + // the props object. This used to happen in the JSX runtime, but now we do + // it here. + propsWithoutRef = {}; + + for (var key in nextProps) { + // Since `ref` should only appear in props via the JSX transform, we can + // assume that this is a plain object. So we don't need a + // hasOwnProperty check. + if (key !== "ref") { + propsWithoutRef[key] = nextProps[key]; + } + } + } else { propsWithoutRef = nextProps; } // The rest is a fork of updateFunctionComponent @@ -21056,7 +21102,7 @@ if (__DEV__) { } } - if (workInProgress.ref !== null) { + if (!enableRefAsProp && workInProgress.ref !== null) { var info = ""; var componentName = getComponentNameFromType(Component) || "Unknown"; var ownerName = getCurrentFiberOwnerNameInDevOrNull(); @@ -35894,7 +35940,7 @@ if (__DEV__) { return root; } - var ReactVersion = "18.3.0-www-classic-69ce38b6"; + var ReactVersion = "18.3.0-www-classic-ba863f98"; function createPortal$1( children, diff --git a/compiled/facebook-www/ReactDOM-dev.modern.js b/compiled/facebook-www/ReactDOM-dev.modern.js index a269ab1d2f839..e34f908086dd1 100644 --- a/compiled/facebook-www/ReactDOM-dev.modern.js +++ b/compiled/facebook-www/ReactDOM-dev.modern.js @@ -139,7 +139,8 @@ if (__DEV__) { enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, - useModernStrictMode = dynamicFeatureFlags.useModernStrictMode; // On WWW, true is used for a new modern build. + useModernStrictMode = dynamicFeatureFlags.useModernStrictMode, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, true is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; @@ -11056,7 +11057,13 @@ if (__DEV__) { function coerceRef(returnFiber, current, workInProgress, element) { var mixedRef; - { + if (enableRefAsProp) { + // TODO: This is a temporary, intermediate step. When enableRefAsProp is on, + // we should resolve the `ref` prop during the begin phase of the component + // it's attached to (HostComponent, ClassComponent, etc). + var refProp = element.props.ref; + mixedRef = refProp !== undefined ? refProp : null; + } else { // Old behavior. mixedRef = element.ref; } @@ -11076,6 +11083,31 @@ if (__DEV__) { element, mixedRef ); + + if (enableRefAsProp) { + // When enableRefAsProp is on, we should always use the props as the + // source of truth for refs. Not a field on the fiber. + // + // In the case of string refs, this presents a problem, because string + // refs are not passed around internally as strings; they are converted to + // callback refs. The ref used by the reconciler is not the same as the + // one the user provided. + // + // But since this is a deprecated feature anyway, what we can do is clone + // the props object and replace it with the internal callback ref. Then we + // can continue to use the props object as the source of truth. + // + // This means the internal callback ref will leak into userspace. The + // receiving component will receive a callback ref even though the parent + // passed a string. Which is weird, but again, this is a deprecated + // feature, and we're only leaving it around behind a flag so that Meta + // can keep using string refs temporarily while they finish migrating + // their codebase. + var userProvidedProps = workInProgress.pendingProps; + var propsWithInternalCallbackRef = assign({}, userProvidedProps); + propsWithInternalCallbackRef.ref = coercedRef; + workInProgress.pendingProps = propsWithInternalCallbackRef; + } } else { coercedRef = mixedRef; } // TODO: If enableRefAsProp is on, we shouldn't use the `ref` field. We @@ -19461,7 +19493,21 @@ if (__DEV__) { var ref = workInProgress.ref; var propsWithoutRef; - { + if (enableRefAsProp && "ref" in nextProps) { + // `ref` is just a prop now, but `forwardRef` expects it to not appear in + // the props object. This used to happen in the JSX runtime, but now we do + // it here. + propsWithoutRef = {}; + + for (var key in nextProps) { + // Since `ref` should only appear in props via the JSX transform, we can + // assume that this is a plain object. So we don't need a + // hasOwnProperty check. + if (key !== "ref") { + propsWithoutRef[key] = nextProps[key]; + } + } + } else { propsWithoutRef = nextProps; } // The rest is a fork of updateFunctionComponent @@ -20936,7 +20982,7 @@ if (__DEV__) { } } - if (workInProgress.ref !== null) { + if (!enableRefAsProp && workInProgress.ref !== null) { var info = ""; var componentName = getComponentNameFromType(Component) || "Unknown"; var ownerName = getCurrentFiberOwnerNameInDevOrNull(); @@ -35730,7 +35776,7 @@ if (__DEV__) { return root; } - var ReactVersion = "18.3.0-www-modern-2372e606"; + var ReactVersion = "18.3.0-www-modern-fbeafe0c"; function createPortal$1( children, diff --git a/compiled/facebook-www/ReactDOM-prod.classic.js b/compiled/facebook-www/ReactDOM-prod.classic.js index 6b37e6f50a19a..10cce320f6361 100644 --- a/compiled/facebook-www/ReactDOM-prod.classic.js +++ b/compiled/facebook-www/ReactDOM-prod.classic.js @@ -63,6 +63,7 @@ var ReactSharedInternals = enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, REACT_ELEMENT_TYPE = Symbol.for("react.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), @@ -2595,13 +2596,24 @@ function convertStringRefToCallbackRef( return ref; } function coerceRef(returnFiber, current, workInProgress, element) { - var mixedRef = element.ref; - returnFiber = - null !== mixedRef && - "function" !== typeof mixedRef && - "object" !== typeof mixedRef - ? convertStringRefToCallbackRef(returnFiber, current, element, mixedRef) - : mixedRef; + if (enableRefAsProp) { + var mixedRef = element.props.ref; + mixedRef = void 0 !== mixedRef ? mixedRef : null; + } else mixedRef = element.ref; + null !== mixedRef && + "function" !== typeof mixedRef && + "object" !== typeof mixedRef + ? ((returnFiber = convertStringRefToCallbackRef( + returnFiber, + current, + element, + mixedRef + )), + enableRefAsProp && + ((current = assign({}, workInProgress.pendingProps)), + (current.ref = returnFiber), + (workInProgress.pendingProps = current))) + : (returnFiber = mixedRef); workInProgress.ref = returnFiber; } function throwOnInvalidObjectType(returnFiber, newChild) { @@ -5286,22 +5298,27 @@ function updateForwardRef( ) { Component = Component.render; var ref = workInProgress.ref; + if (enableRefAsProp && "ref" in nextProps) { + var propsWithoutRef = {}; + for (var key in nextProps) + "ref" !== key && (propsWithoutRef[key] = nextProps[key]); + } else propsWithoutRef = nextProps; prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, - nextProps, + propsWithoutRef, ref, renderLanes ); - Component = checkDidRenderIdHook(); + key = checkDidRenderIdHook(); if (null !== current && !didReceiveUpdate) return ( bailoutHooks(current, workInProgress, renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - isHydrating && Component && pushMaterializedTreeId(workInProgress); + isHydrating && key && pushMaterializedTreeId(workInProgress); workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; @@ -17161,7 +17178,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1819 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "18.3.0-www-classic-380fe00f", + version: "18.3.0-www-classic-28d4f1a1", rendererPackageName: "react-dom" }; var internals$jscomp$inline_2179 = { @@ -17191,7 +17208,7 @@ var internals$jscomp$inline_2179 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-classic-380fe00f" + reconcilerVersion: "18.3.0-www-classic-28d4f1a1" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2180 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -17534,4 +17551,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactCurrentDispatcher$2.current.useHostTransitionStatus(); }; -exports.version = "18.3.0-www-classic-380fe00f"; +exports.version = "18.3.0-www-classic-28d4f1a1"; diff --git a/compiled/facebook-www/ReactDOM-prod.modern.js b/compiled/facebook-www/ReactDOM-prod.modern.js index f9c6cee632050..06d20507a1f9e 100644 --- a/compiled/facebook-www/ReactDOM-prod.modern.js +++ b/compiled/facebook-www/ReactDOM-prod.modern.js @@ -66,6 +66,7 @@ var assign = Object.assign, enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, @@ -2478,13 +2479,24 @@ function convertStringRefToCallbackRef( return ref; } function coerceRef(returnFiber, current, workInProgress, element) { - var mixedRef = element.ref; - returnFiber = - null !== mixedRef && - "function" !== typeof mixedRef && - "object" !== typeof mixedRef - ? convertStringRefToCallbackRef(returnFiber, current, element, mixedRef) - : mixedRef; + if (enableRefAsProp) { + var mixedRef = element.props.ref; + mixedRef = void 0 !== mixedRef ? mixedRef : null; + } else mixedRef = element.ref; + null !== mixedRef && + "function" !== typeof mixedRef && + "object" !== typeof mixedRef + ? ((returnFiber = convertStringRefToCallbackRef( + returnFiber, + current, + element, + mixedRef + )), + enableRefAsProp && + ((current = assign({}, workInProgress.pendingProps)), + (current.ref = returnFiber), + (workInProgress.pendingProps = current))) + : (returnFiber = mixedRef); workInProgress.ref = returnFiber; } function throwOnInvalidObjectType(returnFiber, newChild) { @@ -5154,22 +5166,27 @@ function updateForwardRef( ) { Component = Component.render; var ref = workInProgress.ref; + if (enableRefAsProp && "ref" in nextProps) { + var propsWithoutRef = {}; + for (var key in nextProps) + "ref" !== key && (propsWithoutRef[key] = nextProps[key]); + } else propsWithoutRef = nextProps; prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, - nextProps, + propsWithoutRef, ref, renderLanes ); - Component = checkDidRenderIdHook(); + key = checkDidRenderIdHook(); if (null !== current && !didReceiveUpdate) return ( bailoutHooks(current, workInProgress, renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - isHydrating && Component && pushMaterializedTreeId(workInProgress); + isHydrating && key && pushMaterializedTreeId(workInProgress); workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; @@ -16677,7 +16694,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1778 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "18.3.0-www-modern-e062351c", + version: "18.3.0-www-modern-469be386", rendererPackageName: "react-dom" }; var internals$jscomp$inline_2143 = { @@ -16708,7 +16725,7 @@ var internals$jscomp$inline_2143 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-modern-e062351c" + reconcilerVersion: "18.3.0-www-modern-469be386" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2144 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -16979,4 +16996,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactCurrentDispatcher$2.current.useHostTransitionStatus(); }; -exports.version = "18.3.0-www-modern-e062351c"; +exports.version = "18.3.0-www-modern-469be386"; diff --git a/compiled/facebook-www/ReactDOM-profiling.classic.js b/compiled/facebook-www/ReactDOM-profiling.classic.js index 1e70a259437d5..f9405321ff5cc 100644 --- a/compiled/facebook-www/ReactDOM-profiling.classic.js +++ b/compiled/facebook-www/ReactDOM-profiling.classic.js @@ -67,6 +67,7 @@ var ReactSharedInternals = enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, enableProfilerNestedUpdateScheduledHook = dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook, enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler, @@ -2735,13 +2736,24 @@ function convertStringRefToCallbackRef( return ref; } function coerceRef(returnFiber, current, workInProgress, element) { - var mixedRef = element.ref; - returnFiber = - null !== mixedRef && - "function" !== typeof mixedRef && - "object" !== typeof mixedRef - ? convertStringRefToCallbackRef(returnFiber, current, element, mixedRef) - : mixedRef; + if (enableRefAsProp) { + var mixedRef = element.props.ref; + mixedRef = void 0 !== mixedRef ? mixedRef : null; + } else mixedRef = element.ref; + null !== mixedRef && + "function" !== typeof mixedRef && + "object" !== typeof mixedRef + ? ((returnFiber = convertStringRefToCallbackRef( + returnFiber, + current, + element, + mixedRef + )), + enableRefAsProp && + ((current = assign({}, workInProgress.pendingProps)), + (current.ref = returnFiber), + (workInProgress.pendingProps = current))) + : (returnFiber = mixedRef); workInProgress.ref = returnFiber; } function throwOnInvalidObjectType(returnFiber, newChild) { @@ -5499,24 +5511,29 @@ function updateForwardRef( ) { Component = Component.render; var ref = workInProgress.ref; + if (enableRefAsProp && "ref" in nextProps) { + var propsWithoutRef = {}; + for (var key in nextProps) + "ref" !== key && (propsWithoutRef[key] = nextProps[key]); + } else propsWithoutRef = nextProps; prepareToReadContext(workInProgress, renderLanes); enableSchedulingProfiler && markComponentRenderStarted(workInProgress); nextProps = renderWithHooks( current, workInProgress, Component, - nextProps, + propsWithoutRef, ref, renderLanes ); - Component = checkDidRenderIdHook(); + key = checkDidRenderIdHook(); enableSchedulingProfiler && markComponentRenderStopped(); if (null !== current && !didReceiveUpdate) return ( bailoutHooks(current, workInProgress, renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - isHydrating && Component && pushMaterializedTreeId(workInProgress); + isHydrating && key && pushMaterializedTreeId(workInProgress); workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; @@ -17930,7 +17947,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1904 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "18.3.0-www-classic-e2f0d381", + version: "18.3.0-www-classic-86040999", rendererPackageName: "react-dom" }; (function (internals) { @@ -17974,7 +17991,7 @@ var devToolsConfig$jscomp$inline_1904 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-classic-e2f0d381" + reconcilerVersion: "18.3.0-www-classic-86040999" }); assign(Internals, { ReactBrowserEventEmitter: { @@ -18304,7 +18321,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactCurrentDispatcher$2.current.useHostTransitionStatus(); }; -exports.version = "18.3.0-www-classic-e2f0d381"; +exports.version = "18.3.0-www-classic-86040999"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/compiled/facebook-www/ReactDOM-profiling.modern.js b/compiled/facebook-www/ReactDOM-profiling.modern.js index 502850d232480..16abce0867ba1 100644 --- a/compiled/facebook-www/ReactDOM-profiling.modern.js +++ b/compiled/facebook-www/ReactDOM-profiling.modern.js @@ -70,6 +70,7 @@ var assign = Object.assign, enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, enableProfilerNestedUpdateScheduledHook = dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook, enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler, @@ -2618,13 +2619,24 @@ function convertStringRefToCallbackRef( return ref; } function coerceRef(returnFiber, current, workInProgress, element) { - var mixedRef = element.ref; - returnFiber = - null !== mixedRef && - "function" !== typeof mixedRef && - "object" !== typeof mixedRef - ? convertStringRefToCallbackRef(returnFiber, current, element, mixedRef) - : mixedRef; + if (enableRefAsProp) { + var mixedRef = element.props.ref; + mixedRef = void 0 !== mixedRef ? mixedRef : null; + } else mixedRef = element.ref; + null !== mixedRef && + "function" !== typeof mixedRef && + "object" !== typeof mixedRef + ? ((returnFiber = convertStringRefToCallbackRef( + returnFiber, + current, + element, + mixedRef + )), + enableRefAsProp && + ((current = assign({}, workInProgress.pendingProps)), + (current.ref = returnFiber), + (workInProgress.pendingProps = current))) + : (returnFiber = mixedRef); workInProgress.ref = returnFiber; } function throwOnInvalidObjectType(returnFiber, newChild) { @@ -5367,24 +5379,29 @@ function updateForwardRef( ) { Component = Component.render; var ref = workInProgress.ref; + if (enableRefAsProp && "ref" in nextProps) { + var propsWithoutRef = {}; + for (var key in nextProps) + "ref" !== key && (propsWithoutRef[key] = nextProps[key]); + } else propsWithoutRef = nextProps; prepareToReadContext(workInProgress, renderLanes); enableSchedulingProfiler && markComponentRenderStarted(workInProgress); nextProps = renderWithHooks( current, workInProgress, Component, - nextProps, + propsWithoutRef, ref, renderLanes ); - Component = checkDidRenderIdHook(); + key = checkDidRenderIdHook(); enableSchedulingProfiler && markComponentRenderStopped(); if (null !== current && !didReceiveUpdate) return ( bailoutHooks(current, workInProgress, renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - isHydrating && Component && pushMaterializedTreeId(workInProgress); + isHydrating && key && pushMaterializedTreeId(workInProgress); workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; @@ -17440,7 +17457,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1863 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "18.3.0-www-modern-e9e265be", + version: "18.3.0-www-modern-388a31ab", rendererPackageName: "react-dom" }; (function (internals) { @@ -17485,7 +17502,7 @@ var devToolsConfig$jscomp$inline_1863 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-modern-e9e265be" + reconcilerVersion: "18.3.0-www-modern-388a31ab" }); exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals; exports.createPortal = function (children, container) { @@ -17743,7 +17760,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactCurrentDispatcher$2.current.useHostTransitionStatus(); }; -exports.version = "18.3.0-www-modern-e9e265be"; +exports.version = "18.3.0-www-modern-388a31ab"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/compiled/facebook-www/ReactDOMServer-dev.classic.js b/compiled/facebook-www/ReactDOMServer-dev.classic.js index d7a042e5b6553..2ad7dbf9ae306 100644 --- a/compiled/facebook-www/ReactDOMServer-dev.classic.js +++ b/compiled/facebook-www/ReactDOMServer-dev.classic.js @@ -19,7 +19,7 @@ if (__DEV__) { var React = require("react"); var ReactDOM = require("react-dom"); - var ReactVersion = "18.3.0-www-classic-1805c8f4"; + var ReactVersion = "18.3.0-www-classic-53767808"; // This refers to a WWW module. var warningWWW = require("warning"); @@ -681,8 +681,8 @@ if (__DEV__) { var enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableUseDeferredValueInitialArg = dynamicFeatureFlags.enableUseDeferredValueInitialArg, - enableRenderableContext = dynamicFeatureFlags.enableRenderableContext; - // On WWW, false is used for a new modern build. + enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, false is used for a new modern build. var enableFloat = true; // $FlowFixMe[method-unbinding] @@ -12173,7 +12173,21 @@ if (__DEV__) { task.componentStack = createFunctionComponentStack(task, type.render); var propsWithoutRef; - { + if (enableRefAsProp && "ref" in props) { + // `ref` is just a prop now, but `forwardRef` expects it to not appear in + // the props object. This used to happen in the JSX runtime, but now we do + // it here. + propsWithoutRef = {}; + + for (var key in props) { + // Since `ref` should only appear in props via the JSX transform, we can + // assume that this is a plain object. So we don't need a + // hasOwnProperty check. + if (key !== "ref") { + propsWithoutRef[key] = props[key]; + } + } + } else { propsWithoutRef = props; } @@ -12687,7 +12701,13 @@ if (__DEV__) { var props = element.props; var ref; - { + if (enableRefAsProp) { + // TODO: This is a temporary, intermediate step. Once the feature + // flag is removed, we should get the ref off the props object right + // before using it. + var refProp = props.ref; + ref = refProp !== undefined ? refProp : null; + } else { ref = element.ref; } diff --git a/compiled/facebook-www/ReactDOMServer-dev.modern.js b/compiled/facebook-www/ReactDOMServer-dev.modern.js index 961961576ed2f..7c54444bfeb5f 100644 --- a/compiled/facebook-www/ReactDOMServer-dev.modern.js +++ b/compiled/facebook-www/ReactDOMServer-dev.modern.js @@ -19,7 +19,7 @@ if (__DEV__) { var React = require("react"); var ReactDOM = require("react-dom"); - var ReactVersion = "18.3.0-www-modern-a9f7c4dc"; + var ReactVersion = "18.3.0-www-modern-4b346c06"; // This refers to a WWW module. var warningWWW = require("warning"); @@ -681,8 +681,8 @@ if (__DEV__) { var enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableUseDeferredValueInitialArg = dynamicFeatureFlags.enableUseDeferredValueInitialArg, - enableRenderableContext = dynamicFeatureFlags.enableRenderableContext; - // On WWW, true is used for a new modern build. + enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, true is used for a new modern build. var enableFloat = true; // $FlowFixMe[method-unbinding] @@ -12083,7 +12083,21 @@ if (__DEV__) { task.componentStack = createFunctionComponentStack(task, type.render); var propsWithoutRef; - { + if (enableRefAsProp && "ref" in props) { + // `ref` is just a prop now, but `forwardRef` expects it to not appear in + // the props object. This used to happen in the JSX runtime, but now we do + // it here. + propsWithoutRef = {}; + + for (var key in props) { + // Since `ref` should only appear in props via the JSX transform, we can + // assume that this is a plain object. So we don't need a + // hasOwnProperty check. + if (key !== "ref") { + propsWithoutRef[key] = props[key]; + } + } + } else { propsWithoutRef = props; } @@ -12597,7 +12611,13 @@ if (__DEV__) { var props = element.props; var ref; - { + if (enableRefAsProp) { + // TODO: This is a temporary, intermediate step. Once the feature + // flag is removed, we should get the ref off the props object right + // before using it. + var refProp = props.ref; + ref = refProp !== undefined ? refProp : null; + } else { ref = element.ref; } diff --git a/compiled/facebook-www/ReactDOMServer-prod.classic.js b/compiled/facebook-www/ReactDOMServer-prod.classic.js index dbe62a22594a8..04604e92a7617 100644 --- a/compiled/facebook-www/ReactDOMServer-prod.classic.js +++ b/compiled/facebook-www/ReactDOMServer-prod.classic.js @@ -133,6 +133,7 @@ var assign = Object.assign, enableUseDeferredValueInitialArg = dynamicFeatureFlags.enableUseDeferredValueInitialArg, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, + enableRefAsProp = dynamicFeatureFlags.enableRefAsProp, hasOwnProperty = Object.prototype.hasOwnProperty, VALID_ATTRIBUTE_NAME_REGEX = RegExp( "^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$" @@ -2592,16 +2593,16 @@ function createRenderState(resumableState, generateStaticMarkup) { "\x3c/script>" ); bootstrapScriptContent = idPrefix + "P:"; - var JSCompiler_object_inline_segmentPrefix_1595 = idPrefix + "S:"; + var JSCompiler_object_inline_segmentPrefix_1596 = idPrefix + "S:"; idPrefix += "B:"; - var JSCompiler_object_inline_preconnects_1609 = new Set(), - JSCompiler_object_inline_fontPreloads_1610 = new Set(), - JSCompiler_object_inline_highImagePreloads_1611 = new Set(), - JSCompiler_object_inline_styles_1612 = new Map(), - JSCompiler_object_inline_bootstrapScripts_1613 = new Set(), - JSCompiler_object_inline_scripts_1614 = new Set(), - JSCompiler_object_inline_bulkPreloads_1615 = new Set(), - JSCompiler_object_inline_preloads_1616 = { + var JSCompiler_object_inline_preconnects_1610 = new Set(), + JSCompiler_object_inline_fontPreloads_1611 = new Set(), + JSCompiler_object_inline_highImagePreloads_1612 = new Set(), + JSCompiler_object_inline_styles_1613 = new Map(), + JSCompiler_object_inline_bootstrapScripts_1614 = new Set(), + JSCompiler_object_inline_scripts_1615 = new Set(), + JSCompiler_object_inline_bulkPreloads_1616 = new Set(), + JSCompiler_object_inline_preloads_1617 = { images: new Map(), stylesheets: new Map(), scripts: new Map(), @@ -2638,7 +2639,7 @@ function createRenderState(resumableState, generateStaticMarkup) { scriptConfig.moduleScriptResources[href] = null; scriptConfig = []; pushLinkImpl(scriptConfig, props); - JSCompiler_object_inline_bootstrapScripts_1613.add(scriptConfig); + JSCompiler_object_inline_bootstrapScripts_1614.add(scriptConfig); bootstrapChunks.push('