From 99428968fb1736bbcab89da8eb8cbfa317db066f Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Tue, 24 Sep 2019 16:26:08 -0700 Subject: [PATCH 1/2] [React Native] Improve logging for missing view configs and invalid view config getter functions --- .../ReactPrivate/ReactNativeViewConfigRegistry.js | 9 ++++++++- .../src/__tests__/ReactNativeError-test.internal.js | 11 +++++++++++ .../react-native/ReactNativeViewConfigRegistry.js | 9 ++++++++- 3 files changed, 27 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..42c07a645a7f8 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,17 @@ describe('ReactNativeError', () => { .computeComponentStackForErrorReporting; }); + it('should throw error if null component registration getter is used', () => { + let error; + try { + createReactNativeComponentClass('View', null); + } catch (e) { + error = e; + } + + expect(error.toString()).toBe('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.' : '', From 9eea5d5b68b737e1b59f5006bfb839bf8f8e147f Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Tue, 24 Sep 2019 17:00:09 -0700 Subject: [PATCH 2/2] [React Native] Improve logging for missing view configs and invalid view config getter functions --- .../ReactNativeViewConfigRegistry.js | 4 ++-- .../__tests__/ReactNativeError-test.internal.js | 17 +++++++++-------- .../ReactNativeViewConfigRegistry.js | 4 ++-- 3 files changed, 13 insertions(+), 12 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 a4dd86df63f21..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 @@ -80,7 +80,7 @@ exports.register = function(name: string, callback: ViewConfigGetter): string { ); invariant( typeof callback === 'function', - 'View config getter callback must be a function: %s (received %s)', + 'View config getter callback for component `%s` must be a function (received `%s`)', name, callback === null ? 'null' : typeof callback, ); @@ -100,7 +100,7 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> { if (typeof callback !== 'function') { invariant( false, - 'View config registration not found for name %s (received %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]) 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 42c07a645a7f8..f6a78667eda36 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js @@ -33,14 +33,15 @@ describe('ReactNativeError', () => { }); it('should throw error if null component registration getter is used', () => { - let error; - try { - createReactNativeComponentClass('View', null); - } catch (e) { - error = e; - } - - expect(error.toString()).toBe('Invariant Violation: View config getter callback must be a function: View (received null)'); + 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', () => { diff --git a/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js b/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js index b43ad39ded9a2..2173fc84b3e70 100644 --- a/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js +++ b/scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js @@ -77,7 +77,7 @@ exports.register = function(name: string, callback: ViewConfigGetter): string { ); invariant( typeof callback === 'function', - 'View config getter callback must be a function: %s (received %s)', + 'View config getter callback for component `%s` must be a function (received `%s`)', name, callback === null ? 'null' : typeof callback, ); @@ -97,7 +97,7 @@ exports.get = function(name: string): ReactNativeBaseComponentViewConfig<> { if (typeof callback !== 'function') { invariant( false, - 'View config registration not found for name %s (received %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])