@samitouri / QOS-React-2 / commits / 6ecfa90eb0

[React Native] Fix for view config registrations (#16821)

Ricky committed Sep 18, 2019 at 15:31 UTC 6ecfa90eb0d9bc369d0e6930bc02d59dfba770d1
3 files changed +51 -2
packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js
+4 -1
@@ -101,10 +101,13 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> {
101 : '',
102 );
103 }
104 - viewConfigCallbacks.set(name, null);
104 viewConfig = callback();
105 processEventTypes(viewConfig);
106 viewConfigs.set(name, viewConfig);
107 +
108 + // Clear the callback after the config is set so that
109 + // we don't mask any errors during registration.
110 + viewConfigCallbacks.set(name, null);
111 } else {
112 viewConfig = viewConfigs.get(name);
113 }
packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js
+43
@@ -75,6 +75,49 @@ beforeEach(() => {
75 .ReactNativeViewConfigRegistry.register;
76 });
77
78 +it('fails to register the same event name with different types', () => {
79 + const InvalidEvents = createReactNativeComponentClass('InvalidEvents', () => {
80 + if (!__DEV__) {
81 + // Simulate a registration error in prod.
82 + throw new Error('Event cannot be both direct and bubbling: topChange');
83 + }
84 +
85 + // This view config has the same bubbling and direct event name
86 + // which will fail to register in developement.
87 + return {
88 + uiViewClassName: 'InvalidEvents',
89 + validAttributes: {
90 + onChange: true,
91 + },
92 + bubblingEventTypes: {
93 + topChange: {
94 + phasedRegistrationNames: {
95 + bubbled: 'onChange',
96 + captured: 'onChangeCapture',
97 + },
98 + },
99 + },
100 + directEventTypes: {
101 + topChange: {
102 + registrationName: 'onChange',
103 + },
104 + },
105 + };
106 + });
107 +
108 + // The first time this renders,
109 + // we attempt to register the view config and fail.
110 + expect(() => ReactNative.render(<InvalidEvents />, 1)).toThrow(
111 + 'Event cannot be both direct and bubbling: topChange',
112 + );
113 +
114 + // Continue to re-register the config and
115 + // fail so that we don't mask the above failure.
116 + expect(() => ReactNative.render(<InvalidEvents />, 1)).toThrow(
117 + 'Event cannot be both direct and bubbling: topChange',
118 + );
119 +});
120 +
121 it('fails if unknown/unsupported event types are dispatched', () => {
122 expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
123 const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js
+4 -1
@@ -98,10 +98,13 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> {
98 : '',
99 );
100 }
101 - viewConfigCallbacks.set(name, null);
101 viewConfig = callback();
102 processEventTypes(viewConfig);
103 viewConfigs.set(name, viewConfig);
104 +
105 + // Clear the callback after the config is set so that
106 + // we don't mask any errors during registration.
107 + viewConfigCallbacks.set(name, null);
108 } else {
109 viewConfig = viewConfigs.get(name);
110 }