Skip to content

Commit ec5b61a

Browse files
committed
Make enableRefAsProp www dynamic (#28423)
Going to start rolling this out DiffTrain build for [aaf85f3](aaf85f3)
1 parent 52c966b commit ec5b61a

35 files changed

+1454
-520
lines changed

compiled/facebook-www/JSXDEVRuntime-dev.classic.js

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ if (__DEV__) {
109109

110110
var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing,
111111
enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing,
112-
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext;
113-
// On WWW, false is used for a new modern build.
112+
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext,
113+
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, false is used for a new modern build.
114114

115115
function getWrappedName(outerType, innerType, wrapperName) {
116116
var displayName = outerType.displayName;
@@ -813,9 +813,11 @@ if (__DEV__) {
813813
var specialPropKeyWarningShown;
814814
var specialPropRefWarningShown;
815815
var didWarnAboutStringRefs;
816+
var didWarnAboutElementRef;
816817

817818
{
818819
didWarnAboutStringRefs = {};
820+
didWarnAboutElementRef = {};
819821
}
820822

821823
function hasValidRef(config) {
@@ -901,7 +903,7 @@ if (__DEV__) {
901903
}
902904

903905
function defineRefPropWarningGetter(props, displayName) {
904-
{
906+
if (!enableRefAsProp) {
905907
{
906908
var warnAboutAccessingRef = function () {
907909
if (!specialPropRefWarningShown) {
@@ -925,6 +927,26 @@ if (__DEV__) {
925927
}
926928
}
927929
}
930+
931+
function elementRefGetterWithDeprecationWarning() {
932+
{
933+
var componentName = getComponentNameFromType(this.type);
934+
935+
if (!didWarnAboutElementRef[componentName]) {
936+
didWarnAboutElementRef[componentName] = true;
937+
938+
error(
939+
"Accessing element.ref is no longer supported. ref is now a " +
940+
"regular prop. It will be removed from the JSX Element " +
941+
"type in a future release."
942+
);
943+
} // An undefined `element.ref` is coerced to `null` for
944+
// backwards compatibility.
945+
946+
var refProp = this.props.ref;
947+
return refProp !== undefined ? refProp : null;
948+
}
949+
}
928950
/**
929951
* Factory method to create a new React element. This no longer adheres to
930952
* the class pattern, so do not use new to call it. Also, instanceof check
@@ -949,13 +971,64 @@ if (__DEV__) {
949971
function ReactElement(type, key, _ref, self, source, owner, props) {
950972
var ref;
951973

952-
{
974+
if (enableRefAsProp) {
975+
// When enableRefAsProp is on, ignore whatever was passed as the ref
976+
// argument and treat `props.ref` as the source of truth. The only thing we
977+
// use this for is `element.ref`, which will log a deprecation warning on
978+
// access. In the next release, we can remove `element.ref` as well as the
979+
// `ref` argument.
980+
var refProp = props.ref; // An undefined `element.ref` is coerced to `null` for
981+
// backwards compatibility.
982+
983+
ref = refProp !== undefined ? refProp : null;
984+
} else {
953985
ref = _ref;
954986
}
955987

956988
var element;
957989

958-
{
990+
if (enableRefAsProp) {
991+
// In dev, make `ref` a non-enumerable property with a warning. It's non-
992+
// enumerable so that test matchers and serializers don't access it and
993+
// trigger the warning.
994+
//
995+
// `ref` will be removed from the element completely in a future release.
996+
element = {
997+
// This tag allows us to uniquely identify this as a React Element
998+
$$typeof: REACT_ELEMENT_TYPE,
999+
// Built-in properties that belong on the element
1000+
type: type,
1001+
key: key,
1002+
props: props,
1003+
// Record the component responsible for creating this element.
1004+
_owner: owner
1005+
};
1006+
1007+
if (ref !== null) {
1008+
Object.defineProperty(element, "ref", {
1009+
enumerable: false,
1010+
get: elementRefGetterWithDeprecationWarning
1011+
});
1012+
} else {
1013+
// Don't warn on access if a ref is not given. This reduces false
1014+
// positives in cases where a test serializer uses
1015+
// getOwnPropertyDescriptors to compare objects, like Jest does, which is
1016+
// a problem because it bypasses non-enumerability.
1017+
//
1018+
// So unfortunately this will trigger a false positive warning in Jest
1019+
// when the diff is printed:
1020+
//
1021+
// expect(<div ref={ref} />).toEqual(<span ref={ref} />);
1022+
//
1023+
// A bit sketchy, but this is what we've done for the `props.key` and
1024+
// `props.ref` accessors for years, which implies it will be good enough
1025+
// for `element.ref`, too. Let's see if anyone complains.
1026+
Object.defineProperty(element, "ref", {
1027+
enumerable: false,
1028+
value: null
1029+
});
1030+
}
1031+
} else {
9591032
// In prod, `ref` is a regular property. It will be removed in a
9601033
// future release.
9611034
element = {
@@ -1155,7 +1228,7 @@ if (__DEV__) {
11551228
}
11561229

11571230
if (hasValidRef(config)) {
1158-
{
1231+
if (!enableRefAsProp) {
11591232
ref = config.ref;
11601233
}
11611234

@@ -1166,7 +1239,7 @@ if (__DEV__) {
11661239
if (
11671240
hasOwnProperty.call(config, propName) && // Skip over reserved prop names
11681241
propName !== "key" &&
1169-
propName !== "ref"
1242+
(enableRefAsProp || propName !== "ref")
11701243
) {
11711244
props[propName] = config[propName];
11721245
}
@@ -1182,7 +1255,7 @@ if (__DEV__) {
11821255
}
11831256
}
11841257

1185-
if (key || ref) {
1258+
if (key || (!enableRefAsProp && ref)) {
11861259
var displayName =
11871260
typeof type === "function"
11881261
? type.displayName || type.name || "Unknown"
@@ -1192,7 +1265,7 @@ if (__DEV__) {
11921265
defineKeyPropWarningGetter(props, displayName);
11931266
}
11941267

1195-
if (ref) {
1268+
if (!enableRefAsProp && ref) {
11961269
defineRefPropWarningGetter(props, displayName);
11971270
}
11981271
}
@@ -1425,7 +1498,7 @@ if (__DEV__) {
14251498
}
14261499
}
14271500

1428-
if (fragment.ref !== null) {
1501+
if (!enableRefAsProp && fragment.ref !== null) {
14291502
setCurrentlyValidatingElement(fragment);
14301503

14311504
error("Invalid attribute `ref` supplied to `React.Fragment`.");

compiled/facebook-www/JSXDEVRuntime-dev.modern.js

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ if (__DEV__) {
109109

110110
var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing,
111111
enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing,
112-
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext;
113-
// On WWW, true is used for a new modern build.
112+
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext,
113+
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp; // On WWW, true is used for a new modern build.
114114

115115
function getWrappedName(outerType, innerType, wrapperName) {
116116
var displayName = outerType.displayName;
@@ -813,9 +813,11 @@ if (__DEV__) {
813813
var specialPropKeyWarningShown;
814814
var specialPropRefWarningShown;
815815
var didWarnAboutStringRefs;
816+
var didWarnAboutElementRef;
816817

817818
{
818819
didWarnAboutStringRefs = {};
820+
didWarnAboutElementRef = {};
819821
}
820822

821823
function hasValidRef(config) {
@@ -901,7 +903,7 @@ if (__DEV__) {
901903
}
902904

903905
function defineRefPropWarningGetter(props, displayName) {
904-
{
906+
if (!enableRefAsProp) {
905907
{
906908
var warnAboutAccessingRef = function () {
907909
if (!specialPropRefWarningShown) {
@@ -925,6 +927,26 @@ if (__DEV__) {
925927
}
926928
}
927929
}
930+
931+
function elementRefGetterWithDeprecationWarning() {
932+
{
933+
var componentName = getComponentNameFromType(this.type);
934+
935+
if (!didWarnAboutElementRef[componentName]) {
936+
didWarnAboutElementRef[componentName] = true;
937+
938+
error(
939+
"Accessing element.ref is no longer supported. ref is now a " +
940+
"regular prop. It will be removed from the JSX Element " +
941+
"type in a future release."
942+
);
943+
} // An undefined `element.ref` is coerced to `null` for
944+
// backwards compatibility.
945+
946+
var refProp = this.props.ref;
947+
return refProp !== undefined ? refProp : null;
948+
}
949+
}
928950
/**
929951
* Factory method to create a new React element. This no longer adheres to
930952
* the class pattern, so do not use new to call it. Also, instanceof check
@@ -949,13 +971,64 @@ if (__DEV__) {
949971
function ReactElement(type, key, _ref, self, source, owner, props) {
950972
var ref;
951973

952-
{
974+
if (enableRefAsProp) {
975+
// When enableRefAsProp is on, ignore whatever was passed as the ref
976+
// argument and treat `props.ref` as the source of truth. The only thing we
977+
// use this for is `element.ref`, which will log a deprecation warning on
978+
// access. In the next release, we can remove `element.ref` as well as the
979+
// `ref` argument.
980+
var refProp = props.ref; // An undefined `element.ref` is coerced to `null` for
981+
// backwards compatibility.
982+
983+
ref = refProp !== undefined ? refProp : null;
984+
} else {
953985
ref = _ref;
954986
}
955987

956988
var element;
957989

958-
{
990+
if (enableRefAsProp) {
991+
// In dev, make `ref` a non-enumerable property with a warning. It's non-
992+
// enumerable so that test matchers and serializers don't access it and
993+
// trigger the warning.
994+
//
995+
// `ref` will be removed from the element completely in a future release.
996+
element = {
997+
// This tag allows us to uniquely identify this as a React Element
998+
$$typeof: REACT_ELEMENT_TYPE,
999+
// Built-in properties that belong on the element
1000+
type: type,
1001+
key: key,
1002+
props: props,
1003+
// Record the component responsible for creating this element.
1004+
_owner: owner
1005+
};
1006+
1007+
if (ref !== null) {
1008+
Object.defineProperty(element, "ref", {
1009+
enumerable: false,
1010+
get: elementRefGetterWithDeprecationWarning
1011+
});
1012+
} else {
1013+
// Don't warn on access if a ref is not given. This reduces false
1014+
// positives in cases where a test serializer uses
1015+
// getOwnPropertyDescriptors to compare objects, like Jest does, which is
1016+
// a problem because it bypasses non-enumerability.
1017+
//
1018+
// So unfortunately this will trigger a false positive warning in Jest
1019+
// when the diff is printed:
1020+
//
1021+
// expect(<div ref={ref} />).toEqual(<span ref={ref} />);
1022+
//
1023+
// A bit sketchy, but this is what we've done for the `props.key` and
1024+
// `props.ref` accessors for years, which implies it will be good enough
1025+
// for `element.ref`, too. Let's see if anyone complains.
1026+
Object.defineProperty(element, "ref", {
1027+
enumerable: false,
1028+
value: null
1029+
});
1030+
}
1031+
} else {
9591032
// In prod, `ref` is a regular property. It will be removed in a
9601033
// future release.
9611034
element = {
@@ -1155,7 +1228,7 @@ if (__DEV__) {
11551228
}
11561229

11571230
if (hasValidRef(config)) {
1158-
{
1231+
if (!enableRefAsProp) {
11591232
ref = config.ref;
11601233
}
11611234

@@ -1166,7 +1239,7 @@ if (__DEV__) {
11661239
if (
11671240
hasOwnProperty.call(config, propName) && // Skip over reserved prop names
11681241
propName !== "key" &&
1169-
propName !== "ref"
1242+
(enableRefAsProp || propName !== "ref")
11701243
) {
11711244
props[propName] = config[propName];
11721245
}
@@ -1182,7 +1255,7 @@ if (__DEV__) {
11821255
}
11831256
}
11841257

1185-
if (key || ref) {
1258+
if (key || (!enableRefAsProp && ref)) {
11861259
var displayName =
11871260
typeof type === "function"
11881261
? type.displayName || type.name || "Unknown"
@@ -1192,7 +1265,7 @@ if (__DEV__) {
11921265
defineKeyPropWarningGetter(props, displayName);
11931266
}
11941267

1195-
if (ref) {
1268+
if (!enableRefAsProp && ref) {
11961269
defineRefPropWarningGetter(props, displayName);
11971270
}
11981271
}
@@ -1425,7 +1498,7 @@ if (__DEV__) {
14251498
}
14261499
}
14271500

1428-
if (fragment.ref !== null) {
1501+
if (!enableRefAsProp && fragment.ref !== null) {
14291502
setCurrentlyValidatingElement(fragment);
14301503

14311504
error("Invalid attribute `ref` supplied to `React.Fragment`.");

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e4b816ba1a1ea7c1874cf3f82dd841830b71341a
1+
aaf85f3af8c30252edaab5c24975cd086937b2a4

0 commit comments

Comments
 (0)