From 8f2bcf3563d6234030243b47e7967394ae0ba6a7 Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Tue, 24 Sep 2019 16:26:08 -0700 Subject: [PATCH] [React Native] Improve logging for missing view configs and invalid view config getter functions --- .../ReactPrivate/ReactNativeViewConfigRegistry.js | 9 ++++++++- .../src/__tests__/ReactNativeError-test.internal.js | 10 ++++++++++ .../react-native/ReactNativeViewConfigRegistry.js | 9 ++++++++- 3 files changed, 26 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..a4dd86df63f21 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 must be a function: %s (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 registration not found for name %s (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..bb49369fe4399 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,16 @@ 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 must be a function: View (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..b43ad39ded9a2 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 must be a function: %s (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 registration not found for name %s (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.' : '',