Skip to content

Commit bfd8da8

Browse files
authored
Make class prop resolution faster (#28766)
`delete` causes an object (in V8, and maybe other engines) to deopt to a dictionary instead of a class. Instead of `assign` + `delete`, manually iterate over all the properties, like the JSX runtime does. To avoid copying the object twice I moved the `ref` prop removal to come before handling default props. If we already cloned the props to remove `ref`, then we can skip cloning again to handle default props.
1 parent cbb6f2b commit bfd8da8

2 files changed

Lines changed: 44 additions & 25 deletions

File tree

‎packages/react-reconciler/src/ReactFiberClassComponent.js‎

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,32 +1251,39 @@ export function resolveClassComponentProps(
12511251
): Object{
12521252
letnewProps=baseProps;
12531253

1254-
// Resolve default props. Taken from old JSX runtime, where this used to live.
1254+
if(enableRefAsProp){
1255+
// Remove ref from the props object, if it exists.
1256+
if('ref'inbaseProps){
1257+
newProps=({}: any);
1258+
for(constpropNameinbaseProps){
1259+
if(propName!=='ref'){
1260+
newProps[propName]=baseProps[propName];
1261+
}
1262+
}
1263+
}
1264+
}
1265+
1266+
// Resolve default props.
12551267
constdefaultProps=Component.defaultProps;
12561268
if(
12571269
defaultProps&&
12581270
// If disableDefaultPropsExceptForClasses is true, we always resolve
12591271
// default props here in the reconciler, rather than in the JSX runtime.
12601272
(disableDefaultPropsExceptForClasses||!alreadyResolvedDefaultProps)
12611273
){
1262-
newProps=assign({},newProps,baseProps);
1274+
// We may have already copied the props object above to remove ref. If so,
1275+
// we can modify that. Otherwise, copy the props object with Object.assign.
1276+
if(newProps===baseProps){
1277+
newProps=assign({},newProps,baseProps);
1278+
}
1279+
// Taken from old JSX runtime, where this used to live.
12631280
for(constpropNameindefaultProps){
12641281
if(newProps[propName]===undefined){
12651282
newProps[propName]=defaultProps[propName];
12661283
}
12671284
}
12681285
}
12691286

1270-
if(enableRefAsProp){
1271-
// Remove ref from the props object, if it exists.
1272-
if('ref'innewProps){
1273-
if(newProps===baseProps){
1274-
newProps=assign({},newProps);
1275-
}
1276-
deletenewProps.ref;
1277-
}
1278-
}
1279-
12801287
returnnewProps;
12811288
}
12821289

‎packages/react-server/src/ReactFizzServer.js‎

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,24 +1397,36 @@ export function resolveClassComponentProps(
13971397
): Object{
13981398
letnewProps=baseProps;
13991399

1400-
// Resolve default props. Taken from old JSX runtime, where this used to live.
1401-
constdefaultProps=Component.defaultProps;
1402-
if(defaultProps&&disableDefaultPropsExceptForClasses){
1403-
newProps=assign({},newProps,baseProps);
1404-
for(constpropNameindefaultProps){
1405-
if(newProps[propName]===undefined){
1406-
newProps[propName]=defaultProps[propName];
1400+
if(enableRefAsProp){
1401+
// Remove ref from the props object, if it exists.
1402+
if('ref' inbaseProps){
1403+
newProps=({}: any);
1404+
for(constpropNameinbaseProps){
1405+
if(propName!== 'ref'){
1406+
newProps[propName]=baseProps[propName];
1407+
}
14071408
}
14081409
}
14091410
}
14101411

1411-
if(enableRefAsProp){
1412-
// Remove ref from the props object, if it exists.
1413-
if('ref' innewProps){
1414-
if(newProps===baseProps){
1415-
newProps=assign({},newProps);
1412+
// Resolve default props.
1413+
constdefaultProps=Component.defaultProps;
1414+
if(
1415+
defaultProps&&
1416+
// If disableDefaultPropsExceptForClasses is true, we always resolve
1417+
// default props here, rather than in the JSX runtime.
1418+
disableDefaultPropsExceptForClasses
1419+
){
1420+
// We may have already copied the props object above to remove ref. If so,
1421+
// we can modify that. Otherwise, copy the props object with Object.assign.
1422+
if(newProps===baseProps){
1423+
newProps=assign({},newProps,baseProps);
1424+
}
1425+
// Taken from old JSX runtime, where this used to live.
1426+
for(constpropNameindefaultProps){
1427+
if(newProps[propName]===undefined){
1428+
newProps[propName]=defaultProps[propName];
14161429
}
1417-
deletenewProps.ref;
14181430
}
14191431
}
14201432

0 commit comments

Comments
 (0)