From 32e5c97d11e390e6a3d3ce6a2ab7443daed09747 Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Tue, 24 Sep 2019 17:46:21 -0700 Subject: [PATCH] [React Native] Improve errors for invalid ViewConfig getter functions (#16879) * [React Native] Improve logging for missing view configs and invalid view config getter functions * [React Native] Improve logging for missing view configs and invalid view config getter functions --- .../ReactPrivate/ReactNativeViewConfigRegistry.js | 9 ++++++++- .../src/__tests__/ReactNativeError-test.internal.js | 12 ++++++++++++ .../react-native/ReactNativeViewConfigRegistry.js | 9 ++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js index 05c8b93c9ee58..4fe8e6c56fe5b 100644 --- a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js +++ b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/ReactNativeViewConfigRegistry.js @@ -78,6 +78,12 @@ exports.register = function(name: string, callback: ViewConfigGetter): string { 'Tried to register two views with the same name %s', name, ); + invariant( + typeof callback === 'function', + 'View config getter callback for component `%s` must be a function (received `%s`)', + name, + callback === null ? 'null' : typeof callback, + ); viewConfigCallbacks.set(name, callback); return name; }; @@ -94,8 +100,9 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> { if (typeof callback !== 'function') { invariant( false, - 'View config not found for name %s.%s', + 'View config getter callback for component `%s` must be a function (received `%s`).%s', name, + callback === null ? 'null' : typeof callback, typeof name[0] === 'string' && /[a-z]/.test(name[0]) ? ' Make sure to start component names with a capital letter.' : '', diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js index 9abf0ee21aecb..f6a78667eda36 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js @@ -32,6 +32,18 @@ describe('ReactNativeError', () => { .computeComponentStackForErrorReporting; }); + it('should throw error if null component registration getter is used', () => { + expect(() => { + try { + createReactNativeComponentClass('View', null); + } catch (e) { + throw new Error(e.toString()); + } + }).toThrow( + 'Invariant Violation: View config getter callback for component `View` must be a function (received `null`)', + ); + }); + it('should be able to extract a component stack from a native view', () => { const View = createReactNativeComponentClass('View', () => ({ validAttributes: {foo: true}, diff --git a/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js b/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js index 7290c84546c50..2173fc84b3e70 100644 --- a/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js +++ b/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js @@ -75,6 +75,12 @@ exports.register = function(name: string, callback: ViewConfigGetter): string { 'Tried to register two views with the same name %s', name, ); + invariant( + typeof callback === 'function', + 'View config getter callback for component `%s` must be a function (received `%s`)', + name, + callback === null ? 'null' : typeof callback, + ); viewConfigCallbacks.set(name, callback); return name; }; @@ -91,8 +97,9 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> { if (typeof callback !== 'function') { invariant( false, - 'View config not found for name %s.%s', + 'View config getter callback for component `%s` must be a function (received `%s`).%s', name, + callback === null ? 'null' : typeof callback, typeof name[0] === 'string' && /[a-z]/.test(name[0]) ? ' Make sure to start component names with a capital letter.' : '',