Skip to content

Commit c25dcdb

Browse files
committed
Pass ref as normal prop (#28348)
Depends on: - #28317 - #28320 --- Changes the behavior of the JSX runtime to pass through `ref` as a normal prop, rather than plucking it from the props object and storing on the element. This is a breaking change since it changes the type of the receiving component. However, most code is unaffected since it's unlikely that a component would have attempted to access a `ref` prop, since it was not possible to get a reference to one. `forwardRef` _will_ still pluck `ref` from the props object, though, since it's extremely common for users to spread the props object onto the inner component and pass `ref` as a differently named prop. This is for maximum compatibility with existing code — the real impact of this change is that `forwardRef` is no longer required. Currently, refs are resolved during child reconciliation and stored on the fiber. As a result of this change, we can move ref resolution to happen only much later, and only for components that actually use them. Then we can remove the `ref` field from the Fiber type. I have not yet done that in this step, though. DiffTrain build for commit fa2f82a.
1 parent 5a8f5c8 commit c25dcdb

File tree

11 files changed

+232
-138
lines changed

11 files changed

+232
-138
lines changed

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-dev.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<bdf0df21b100941fad1618d2f0f4ea03>>
10+
* @generated SignedSource<<1d3d484449a45d9d48c574d191f78a9b>>
1111
*/
1212

1313
"use strict";
@@ -5040,7 +5040,12 @@ if (__DEV__) {
50405040
}
50415041

50425042
function coerceRef(returnFiber, current, element) {
5043-
var mixedRef = element.ref;
5043+
var mixedRef;
5044+
5045+
{
5046+
// Old behavior.
5047+
mixedRef = element.ref;
5048+
}
50445049

50455050
if (
50465051
mixedRef !== null &&
@@ -12692,7 +12697,12 @@ if (__DEV__) {
1269212697
// hasn't yet mounted. This happens after the first render suspends.
1269312698
// We'll need to figure out if this is fine or can cause issues.
1269412699
var render = Component.render;
12695-
var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent
12700+
var ref = workInProgress.ref;
12701+
var propsWithoutRef;
12702+
12703+
{
12704+
propsWithoutRef = nextProps;
12705+
} // The rest is a fork of updateFunctionComponent
1269612706

1269712707
var nextChildren;
1269812708
prepareToReadContext(workInProgress, renderLanes);
@@ -12704,7 +12714,7 @@ if (__DEV__) {
1270412714
current,
1270512715
workInProgress,
1270612716
render,
12707-
nextProps,
12717+
propsWithoutRef,
1270812718
ref,
1270912719
renderLanes
1271012720
);
@@ -25686,7 +25696,7 @@ if (__DEV__) {
2568625696
return root;
2568725697
}
2568825698

25689-
var ReactVersion = "18.3.0-canary-7b196be09-20240220";
25699+
var ReactVersion = "18.3.0-canary-fa2f82add-20240220";
2569025700

2569125701
// Might add PROFILE later.
2569225702

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-prod.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9176,7 +9176,7 @@ var devToolsConfig$jscomp$inline_1014 = {
91769176
throw Error("TestRenderer does not support findFiberByHostInstance()");
91779177
},
91789178
bundleType: 0,
9179-
version: "18.3.0-canary-7b196be09-20240220",
9179+
version: "18.3.0-canary-fa2f82add-20240220",
91809180
rendererPackageName: "react-test-renderer"
91819181
};
91829182
var internals$jscomp$inline_1195 = {
@@ -9207,7 +9207,7 @@ var internals$jscomp$inline_1195 = {
92079207
scheduleRoot: null,
92089208
setRefreshHandler: null,
92099209
getCurrentFiber: null,
9210-
reconcilerVersion: "18.3.0-canary-7b196be09-20240220"
9210+
reconcilerVersion: "18.3.0-canary-fa2f82add-20240220"
92119211
};
92129212
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
92139213
var hook$jscomp$inline_1196 = __REACT_DEVTOOLS_GLOBAL_HOOK__;

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react-test-renderer/cjs/ReactTestRenderer-profiling.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9604,7 +9604,7 @@ var devToolsConfig$jscomp$inline_1056 = {
96049604
throw Error("TestRenderer does not support findFiberByHostInstance()");
96059605
},
96069606
bundleType: 0,
9607-
version: "18.3.0-canary-7b196be09-20240220",
9607+
version: "18.3.0-canary-fa2f82add-20240220",
96089608
rendererPackageName: "react-test-renderer"
96099609
};
96109610
var internals$jscomp$inline_1236 = {
@@ -9635,7 +9635,7 @@ var internals$jscomp$inline_1236 = {
96359635
scheduleRoot: null,
96369636
setRefreshHandler: null,
96379637
getCurrentFiber: null,
9638-
reconcilerVersion: "18.3.0-canary-7b196be09-20240220"
9638+
reconcilerVersion: "18.3.0-canary-fa2f82add-20240220"
96399639
};
96409640
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
96419641
var hook$jscomp$inline_1237 = __REACT_DEVTOOLS_GLOBAL_HOOK__;

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXDEVRuntime-dev.js

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<9d1803d74418a7ac44bc89ae8cd0f170>>
10+
* @generated SignedSource<<20a889fc4c8eaee85875c7091bc5ea65>>
1111
*/
1212

1313
"use strict";
@@ -643,25 +643,27 @@ if (__DEV__) {
643643

644644
function defineRefPropWarningGetter(props, displayName) {
645645
{
646-
var warnAboutAccessingRef = function () {
647-
if (!specialPropRefWarningShown) {
648-
specialPropRefWarningShown = true;
646+
{
647+
var warnAboutAccessingRef = function () {
648+
if (!specialPropRefWarningShown) {
649+
specialPropRefWarningShown = true;
649650

650-
error(
651-
"%s: `ref` is not a prop. Trying to access it will result " +
652-
"in `undefined` being returned. If you need to access the same " +
653-
"value within the child component, you should pass it as a different " +
654-
"prop. (https://reactjs.org/link/special-props)",
655-
displayName
656-
);
657-
}
658-
};
651+
error(
652+
"%s: `ref` is not a prop. Trying to access it will result " +
653+
"in `undefined` being returned. If you need to access the same " +
654+
"value within the child component, you should pass it as a different " +
655+
"prop. (https://reactjs.org/link/special-props)",
656+
displayName
657+
);
658+
}
659+
};
659660

660-
warnAboutAccessingRef.isReactWarning = true;
661-
Object.defineProperty(props, "ref", {
662-
get: warnAboutAccessingRef,
663-
configurable: true
664-
});
661+
warnAboutAccessingRef.isReactWarning = true;
662+
Object.defineProperty(props, "ref", {
663+
get: warnAboutAccessingRef,
664+
configurable: true
665+
});
666+
}
665667
}
666668
}
667669
/**
@@ -685,18 +687,30 @@ if (__DEV__) {
685687
* @internal
686688
*/
687689

688-
function ReactElement(type, key, ref, self, source, owner, props) {
689-
var element = {
690-
// This tag allows us to uniquely identify this as a React Element
691-
$$typeof: REACT_ELEMENT_TYPE,
692-
// Built-in properties that belong on the element
693-
type: type,
694-
key: key,
695-
ref: ref,
696-
props: props,
697-
// Record the component responsible for creating this element.
698-
_owner: owner
699-
};
690+
function ReactElement(type, key, _ref, self, source, owner, props) {
691+
var ref;
692+
693+
{
694+
ref = _ref;
695+
}
696+
697+
var element;
698+
699+
{
700+
// In prod, `ref` is a regular property. It will be removed in a
701+
// future release.
702+
element = {
703+
// This tag allows us to uniquely identify this as a React Element
704+
$$typeof: REACT_ELEMENT_TYPE,
705+
// Built-in properties that belong on the element
706+
type: type,
707+
key: key,
708+
ref: ref,
709+
props: props,
710+
// Record the component responsible for creating this element.
711+
_owner: owner
712+
};
713+
}
700714

701715
{
702716
// The validation flag is currently mutative. We put it on
@@ -882,14 +896,17 @@ if (__DEV__) {
882896
}
883897

884898
if (hasValidRef(config)) {
885-
ref = config.ref;
899+
{
900+
ref = config.ref;
901+
}
902+
886903
warnIfStringRefCannotBeAutoConverted(config, self);
887904
} // Remaining properties are added to a new props object
888905

889906
for (propName in config) {
890907
if (
891908
hasOwnProperty.call(config, propName) && // Skip over reserved prop names
892-
propName !== "key" && // TODO: `ref` will no longer be reserved in the next major
909+
propName !== "key" &&
893910
propName !== "ref"
894911
) {
895912
props[propName] = config[propName];
@@ -1130,6 +1147,7 @@ if (__DEV__) {
11301147
*/
11311148

11321149
function validateFragmentProps(fragment) {
1150+
// TODO: Move this to render phase instead of at element creation.
11331151
{
11341152
var keys = Object.keys(fragment.props);
11351153

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXRuntime-dev.js

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<8af9696c59d9d4cfa4cc835b5a54e94e>>
10+
* @generated SignedSource<<74f1366b0384318710be72f745716987>>
1111
*/
1212

1313
"use strict";
@@ -643,25 +643,27 @@ if (__DEV__) {
643643

644644
function defineRefPropWarningGetter(props, displayName) {
645645
{
646-
var warnAboutAccessingRef = function () {
647-
if (!specialPropRefWarningShown) {
648-
specialPropRefWarningShown = true;
646+
{
647+
var warnAboutAccessingRef = function () {
648+
if (!specialPropRefWarningShown) {
649+
specialPropRefWarningShown = true;
649650

650-
error(
651-
"%s: `ref` is not a prop. Trying to access it will result " +
652-
"in `undefined` being returned. If you need to access the same " +
653-
"value within the child component, you should pass it as a different " +
654-
"prop. (https://reactjs.org/link/special-props)",
655-
displayName
656-
);
657-
}
658-
};
651+
error(
652+
"%s: `ref` is not a prop. Trying to access it will result " +
653+
"in `undefined` being returned. If you need to access the same " +
654+
"value within the child component, you should pass it as a different " +
655+
"prop. (https://reactjs.org/link/special-props)",
656+
displayName
657+
);
658+
}
659+
};
659660

660-
warnAboutAccessingRef.isReactWarning = true;
661-
Object.defineProperty(props, "ref", {
662-
get: warnAboutAccessingRef,
663-
configurable: true
664-
});
661+
warnAboutAccessingRef.isReactWarning = true;
662+
Object.defineProperty(props, "ref", {
663+
get: warnAboutAccessingRef,
664+
configurable: true
665+
});
666+
}
665667
}
666668
}
667669
/**
@@ -685,18 +687,30 @@ if (__DEV__) {
685687
* @internal
686688
*/
687689

688-
function ReactElement(type, key, ref, self, source, owner, props) {
689-
var element = {
690-
// This tag allows us to uniquely identify this as a React Element
691-
$$typeof: REACT_ELEMENT_TYPE,
692-
// Built-in properties that belong on the element
693-
type: type,
694-
key: key,
695-
ref: ref,
696-
props: props,
697-
// Record the component responsible for creating this element.
698-
_owner: owner
699-
};
690+
function ReactElement(type, key, _ref, self, source, owner, props) {
691+
var ref;
692+
693+
{
694+
ref = _ref;
695+
}
696+
697+
var element;
698+
699+
{
700+
// In prod, `ref` is a regular property. It will be removed in a
701+
// future release.
702+
element = {
703+
// This tag allows us to uniquely identify this as a React Element
704+
$$typeof: REACT_ELEMENT_TYPE,
705+
// Built-in properties that belong on the element
706+
type: type,
707+
key: key,
708+
ref: ref,
709+
props: props,
710+
// Record the component responsible for creating this element.
711+
_owner: owner
712+
};
713+
}
700714

701715
{
702716
// The validation flag is currently mutative. We put it on
@@ -918,14 +932,17 @@ if (__DEV__) {
918932
}
919933

920934
if (hasValidRef(config)) {
921-
ref = config.ref;
935+
{
936+
ref = config.ref;
937+
}
938+
922939
warnIfStringRefCannotBeAutoConverted(config, self);
923940
} // Remaining properties are added to a new props object
924941

925942
for (propName in config) {
926943
if (
927944
hasOwnProperty.call(config, propName) && // Skip over reserved prop names
928-
propName !== "key" && // TODO: `ref` will no longer be reserved in the next major
945+
propName !== "key" &&
929946
propName !== "ref"
930947
) {
931948
props[propName] = config[propName];
@@ -1166,6 +1183,7 @@ if (__DEV__) {
11661183
*/
11671184

11681185
function validateFragmentProps(fragment) {
1186+
// TODO: Move this to render phase instead of at element creation.
11691187
{
11701188
var keys = Object.keys(fragment.props);
11711189

0 commit comments

Comments
 (0)