Skip to content

Commit 665beff

Browse files
OskarEichlermeta-codesync[bot]
authored andcommitted
Fix native component event property checks (#58195)
Summary: Legacy native component event merging invokes `hasOwnProperty` directly on native/default event maps. An own event named `hasOwnProperty` shadows that method and crashes component initialization. Use a bound intrinsic own-property check for both source and destination maps, and add an exact regression. Hosted Flow caught two stale-server misses in the first patches: method unbinding/exact-object inference, then the deprecated `mixed` annotation. The final head uses the repository-standard suppression around the captured intrinsic and an explicit `unknown` indexer for the mutable test map. Fixes #58194. ## Changelog: [GENERAL] [FIXED] - Handle native component event names that shadow Object prototype properties. Pull Request resolved: #58195 Test Plan: - Focused `getNativeComponentAttributes` Jest suite: 2 tests passed on the original regression/fix run. - Final-head targeted ESLint, Prettier check, and `git diff --check` passed. - Hosted full Flow/lint passed on the final amended head. No UI change; screenshots are not applicable. Reviewed By: cipolleschi Differential Revision: D120117546 Pulled By: vzaidman fbshipit-source-id: f4e1cbf6c68bd33ff98ca8df4864b828ac31179b
1 parent 86ba0c6 commit 665beff

2 files changed

Lines changed: 25 additions & 3 deletions

File tree

packages/react-native/Libraries/ReactNative/__tests__/getNativeComponentAttributes-test.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010

1111
'use strict';
1212

13+
let mockDefaultEventTypes: {[string]: unknown} = {};
14+
1315
jest.mock('../UIManager', () => ({
1416
__esModule: true,
1517
default: {
1618
getConstants: () => ({ViewManagerNames: []}),
17-
getDefaultEventTypes: () => ({}),
19+
getDefaultEventTypes: () => mockDefaultEventTypes,
1820
getViewManagerConfig: name =>
1921
name === 'TestView'
2022
? {
@@ -33,6 +35,10 @@ const getNativeComponentAttributes =
3335
require('../getNativeComponentAttributes').default;
3436

3537
describe('getNativeComponentAttributes', () => {
38+
beforeEach(() => {
39+
mockDefaultEventTypes = {};
40+
});
41+
3642
it('processes object font variation settings from native view configs', () => {
3743
const viewConfig = getNativeComponentAttributes('TestView');
3844

@@ -46,4 +52,13 @@ describe('getNativeComponentAttributes', () => {
4652
}),
4753
).toBe("'opsz' 17.25, 'wght' 552.5");
4854
});
55+
56+
it('merges event types that shadow Object prototype properties', () => {
57+
const hasOwnPropertyEvent = {registrationName: 'onHasOwnProperty'};
58+
mockDefaultEventTypes = {hasOwnProperty: hasOwnPropertyEvent};
59+
60+
const viewConfig = getNativeComponentAttributes('TestView');
61+
62+
expect(viewConfig.hasOwnProperty).toBe(hasOwnPropertyEvent);
63+
});
4964
});

packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ function attachDefaultEventTypes(
138138
}
139139
}
140140

141+
// $FlowFixMe[method-unbinding]
142+
const hasOwnProperty = Object.prototype.hasOwnProperty;
143+
141144
// TODO: Figure out how to avoid all this runtime initialization cost.
142145
function merge(
143146
destination: ?ViewManagerConfig,
@@ -151,12 +154,16 @@ function merge(
151154
}
152155

153156
for (const key in source) {
154-
if (!source.hasOwnProperty(key)) {
157+
/* $FlowFixMe[invalid-this-arg] Error exposed after fixing this typing
158+
* unsoundness in flow */
159+
if (!hasOwnProperty.call(source, key)) {
155160
continue;
156161
}
157162

158163
let sourceValue = source[key];
159-
if (destination.hasOwnProperty(key)) {
164+
/* $FlowFixMe[invalid-this-arg] Error exposed after fixing this typing
165+
* unsoundness in flow */
166+
if (hasOwnProperty.call(destination, key)) {
160167
const destinationValue = destination[key];
161168
if (
162169
typeof sourceValue === 'object' &&

0 commit comments

Comments
 (0)