Skip to content

Commit 12627f9

Browse files
authored
Perform hasOwnProperty check in Relay Flight (#20220)
We simulate JSON.stringify in this loop so we should do a has own check. Otherwise we'll include things like constructor properties. This will actually make things throw less even when it should.
1 parent 163199d commit 12627f9

File tree

4 files changed

+61
-12
lines changed

4 files changed

+61
-12
lines changed

packages/react-transport-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ export function processErrorChunk(
7171
];
7272
}
7373

74+
const hasOwnProperty = Object.prototype.hasOwnProperty;
75+
7476
function convertModelToJSON(
7577
request: Request,
7678
parent: {+[key: string]: ReactModel} | $ReadOnlyArray<ReactModel>,
@@ -88,12 +90,14 @@ function convertModelToJSON(
8890
} else {
8991
const jsonObj: {[key: string]: JSONValue} = {};
9092
for (const nextKey in json) {
91-
jsonObj[nextKey] = convertModelToJSON(
92-
request,
93-
json,
94-
nextKey,
95-
json[nextKey],
96-
);
93+
if (hasOwnProperty.call(json, nextKey)) {
94+
jsonObj[nextKey] = convertModelToJSON(
95+
request,
96+
json,
97+
nextKey,
98+
json[nextKey],
99+
);
100+
}
97101
}
98102
return jsonObj;
99103
}

packages/react-transport-dom-relay/src/__tests__/ReactFlightDOMRelay-test.internal.js

+19
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,23 @@ describe('ReactFlightDOMRelay', () => {
214214
const model = readThrough(transport);
215215
expect(model).toEqual(14);
216216
});
217+
218+
it('should warn in DEV if a class instance polyfill is passed to a host component', () => {
219+
function Bar() {}
220+
221+
function Foo() {}
222+
Foo.prototype = Object.create(Bar.prototype);
223+
// This is enumerable which some polyfills do.
224+
Foo.prototype.constructor = Foo;
225+
Foo.prototype.method = function() {};
226+
227+
expect(() => {
228+
const transport = [];
229+
ReactDOMFlightRelayServer.render(<input value={new Foo()} />, transport);
230+
readThrough(transport);
231+
}).toErrorDev(
232+
'Only plain objects can be passed to client components from server components. ',
233+
{withoutStack: true},
234+
);
235+
});
217236
});

packages/react-transport-native-relay/src/ReactFlightNativeRelayServerHostConfig.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ export function processErrorChunk(
7171
];
7272
}
7373

74+
const hasOwnProperty = Object.prototype.hasOwnProperty;
75+
7476
function convertModelToJSON(
7577
request: Request,
7678
parent: {+[key: string]: ReactModel} | $ReadOnlyArray<ReactModel>,
@@ -88,12 +90,14 @@ function convertModelToJSON(
8890
} else {
8991
const jsonObj: {[key: string]: JSONValue} = {};
9092
for (const nextKey in json) {
91-
jsonObj[nextKey] = convertModelToJSON(
92-
request,
93-
json,
94-
nextKey,
95-
json[nextKey],
96-
);
93+
if (hasOwnProperty.call(json, nextKey)) {
94+
jsonObj[nextKey] = convertModelToJSON(
95+
request,
96+
json,
97+
nextKey,
98+
json[nextKey],
99+
);
100+
}
97101
}
98102
return jsonObj;
99103
}

packages/react-transport-native-relay/src/__tests__/ReactFlightNativeRelay-test.internal.js

+22
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,26 @@ describe('ReactFlightNativeRelay', () => {
105105
nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(),
106106
).toMatchSnapshot();
107107
});
108+
109+
it('should warn in DEV if a class instance polyfill is passed to a host component', () => {
110+
function Bar() {}
111+
112+
function Foo() {}
113+
Foo.prototype = Object.create(Bar.prototype);
114+
// This is enumerable which some polyfills do.
115+
Foo.prototype.constructor = Foo;
116+
Foo.prototype.method = function() {};
117+
118+
expect(() => {
119+
const transport = [];
120+
ReactNativeFlightRelayServer.render(
121+
<input value={new Foo()} />,
122+
transport,
123+
);
124+
readThrough(transport);
125+
}).toErrorDev(
126+
'Only plain objects can be passed to client components from server components. ',
127+
{withoutStack: true},
128+
);
129+
});
108130
});

0 commit comments

Comments
 (0)