Skip to content

Commit 621ced7

Browse files
OskarEichlermeta-codesync[bot]
authored andcommitted
Make native event type cache prototype-safe (#58203)
Summary: The EventTarget declarative-prop cache is an ordinary object, so event names such as `constructor` resolve inherited Object properties as cached entries and silently skip their registered handler. Use a typed `Map` for exact event-name keys and add a custom native direct-event regression. Fixes #58202. ## Changelog: [GENERAL] [FIXED] - Resolve native EventTarget names that overlap Object prototype properties. Pull Request resolved: #58203 Test Plan: - Exact baseline regression expected `onConstructor` and received `undefined`; fixed test passes 1/1. - Focused Jest suite passed. - Fresh `yarn flow-check`: 0 errors. - Targeted ESLint, Prettier, and `git diff --check` passed. No UI change; screenshots are not applicable. Reviewed By: cortinico Differential Revision: D118266208 Pulled By: javache fbshipit-source-id: 5ab561865383cd363e9c3f6845ed597783874119
1 parent a344b4b commit 621ced7

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

‎packages/react-native/src/private/renderer/events/ReactNativeEventTypeMapping.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type EventPropNames = {
3030
};
3131

3232
// Cache of already-resolved event types.
33-
const eventTypeToProps: {[string]: EventPropNames} = {};
33+
const eventTypeToProps = new Map<string, EventPropNames>();
3434

3535
/**
3636
* Converts a topLevelType (e.g., "topPointerUp") to a DOM event type
@@ -90,13 +90,13 @@ export function getEventTypePropName(
9090
eventType: string,
9191
isCapture: boolean,
9292
): string | null {
93-
const cached = eventTypeToProps[eventType];
93+
const cached = eventTypeToProps.get(eventType);
9494
if (cached !== undefined) {
9595
return isCapture ? cached.captured : cached.bubbled;
9696
}
9797
const entry = findEventPropNames(eventType);
9898
if (entry != null) {
99-
eventTypeToProps[eventType] = entry;
99+
eventTypeToProps.set(eventType, entry);
100100
return isCapture ? entry.captured : entry.bubbled;
101101
}
102102
return null;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
* @format
9+
*/
10+
11+
import {customDirectEventTypes} from '../../../../../Libraries/Renderer/shims/ReactNativeViewConfigRegistry';
12+
import {getEventTypePropName} from '../ReactNativeEventTypeMapping';
13+
14+
describe('ReactNativeEventTypeMapping', () => {
15+
afterEach(() => {
16+
delete customDirectEventTypes.topConstructor;
17+
});
18+
19+
it('resolves event types that shadow Object prototype properties', () => {
20+
customDirectEventTypes.topConstructor = {
21+
registrationName: 'onConstructor',
22+
};
23+
24+
expect(getEventTypePropName('constructor', false)).toBe('onConstructor');
25+
expect(getEventTypePropName('constructor', true)).toBeNull();
26+
});
27+
});

0 commit comments

Comments
 (0)