From e9780bdc0f00364359f39e5a76a3e43eadb93a4b Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Thu, 14 Sep 2017 18:01:25 -0700 Subject: [PATCH] ReactNative sync (c3718c4...abce30f): the one about the Prepack optimizations Reviewed By: sophiebits Differential Revision: D5626312 fbshipit-source-id: f8158ccb14f991b681fba34fb23933042266939d --- Libraries/ART/ReactNativeART.js | 36 +- .../ReactNative/requireNativeComponent.js | 145 +- Libraries/Renderer/REVISION | 2 +- Libraries/Renderer/ReactNativeFiber-dev.js | 609 ++-- Libraries/Renderer/ReactNativeFiber-prod.js | 558 ++- Libraries/Renderer/ReactNativeStack-dev.js | 3054 ----------------- Libraries/Renderer/ReactNativeStack-prod.js | 2526 -------------- Libraries/Renderer/shims/ReactNative.js | 10 +- Libraries/Renderer/shims/ReactNativeTypes.js | 24 +- Libraries/Text/Text.js | 135 +- 10 files changed, 972 insertions(+), 6127 deletions(-) delete mode 100644 Libraries/Renderer/ReactNativeStack-dev.js delete mode 100644 Libraries/Renderer/ReactNativeStack-prod.js diff --git a/Libraries/ART/ReactNativeART.js b/Libraries/ART/ReactNativeART.js index a54fafdfe..4a56d0275 100644 --- a/Libraries/ART/ReactNativeART.js +++ b/Libraries/ART/ReactNativeART.js @@ -101,25 +101,29 @@ var TextAttributes = merge(RenderableAttributes, { // Native Components -var NativeSurfaceView = createReactNativeComponentClass({ - validAttributes: SurfaceViewAttributes, - uiViewClassName: 'ARTSurfaceView', -}); +var NativeSurfaceView = createReactNativeComponentClass('ARTSurfaceView', + () => ({ + validAttributes: SurfaceViewAttributes, + uiViewClassName: 'ARTSurfaceView', + })); -var NativeGroup = createReactNativeComponentClass({ - validAttributes: GroupAttributes, - uiViewClassName: 'ARTGroup', -}); +var NativeGroup = createReactNativeComponentClass('ARTGroup', + () => ({ + validAttributes: GroupAttributes, + uiViewClassName: 'ARTGroup', + })); -var NativeShape = createReactNativeComponentClass({ - validAttributes: ShapeAttributes, - uiViewClassName: 'ARTShape', -}); +var NativeShape = createReactNativeComponentClass('ARTShape', + () => ({ + validAttributes: ShapeAttributes, + uiViewClassName: 'ARTShape', + })); -var NativeText = createReactNativeComponentClass({ - validAttributes: TextAttributes, - uiViewClassName: 'ARTText', -}); +var NativeText = createReactNativeComponentClass('ARTText', + () => ({ + validAttributes: TextAttributes, + uiViewClassName: 'ARTText', + })); // Utilities diff --git a/Libraries/ReactNative/requireNativeComponent.js b/Libraries/ReactNative/requireNativeComponent.js index 5a795eeb5..3b3795f36 100644 --- a/Libraries/ReactNative/requireNativeComponent.js +++ b/Libraries/ReactNative/requireNativeComponent.js @@ -13,7 +13,6 @@ const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); const UIManager = require('UIManager'); -const UnimplementedView = require('UnimplementedView'); const createReactNativeComponentClass = require('createReactNativeComponentClass'); const insetsDiffer = require('insetsDiffer'); @@ -26,6 +25,7 @@ const verifyPropTypes = require('verifyPropTypes'); /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error * found when Flow v0.54 was deployed. To see the error delete this comment and * run Flow. */ +const invariant = require('fbjs/lib/invariant'); const warning = require('fbjs/lib/warning'); /** @@ -50,77 +50,86 @@ function requireNativeComponent( componentInterface?: ?ComponentInterface, extraConfig?: ?{nativeOnly?: Object}, ): React$ComponentType | string { - const viewConfig = UIManager[viewName]; - if (!viewConfig || !viewConfig.NativeProps) { - warning(false, 'Native component for "%s" does not exist', viewName); - return UnimplementedView; - } + // Don't load the ViewConfig from UIManager until it's needed for rendering. + // Lazy-loading this can help avoid Prepack deopts. + function getViewConfig() { + const viewConfig = UIManager[viewName]; - viewConfig.uiViewClassName = viewName; - viewConfig.validAttributes = {}; - - // ReactNative `View.propTypes` have been deprecated in favor of - // `ViewPropTypes`. In their place a temporary getter has been added with a - // deprecated warning message. Avoid triggering that warning here by using - // temporary workaround, __propTypesSecretDontUseThesePlease. - // TODO (bvaughn) Revert this particular change any time after April 1 - if (componentInterface) { - viewConfig.propTypes = - typeof componentInterface.__propTypesSecretDontUseThesePlease === 'object' - ? componentInterface.__propTypesSecretDontUseThesePlease - : componentInterface.propTypes; - } else { - viewConfig.propTypes = null; - } - - let baseModuleName = viewConfig.baseModuleName; - let nativeProps = { ...viewConfig.NativeProps }; - while (baseModuleName) { - const baseModule = UIManager[baseModuleName]; - if (!baseModule) { - warning(false, 'Base module "%s" does not exist', baseModuleName); - baseModuleName = null; - } else { - nativeProps = { ...nativeProps, ...baseModule.NativeProps }; - baseModuleName = baseModule.baseModuleName; - } - } - - for (const key in nativeProps) { - let useAttribute = false; - const attribute = {}; - - const differ = TypeToDifferMap[nativeProps[key]]; - if (differ) { - attribute.diff = differ; - useAttribute = true; - } - - const processor = TypeToProcessorMap[nativeProps[key]]; - if (processor) { - attribute.process = processor; - useAttribute = true; - } - - viewConfig.validAttributes[key] = useAttribute ? attribute : true; - } - - // Unfortunately, the current set up puts the style properties on the top - // level props object. We also need to add the nested form for API - // compatibility. This allows these props on both the top level and the - // nested style level. TODO: Move these to nested declarations on the - // native side. - viewConfig.validAttributes.style = ReactNativeStyleAttributes; - - if (__DEV__) { - componentInterface && verifyPropTypes( - componentInterface, - viewConfig, - extraConfig && extraConfig.nativeOnly + invariant( + viewConfig != null && + !viewConfig.NativeProps != null, + 'Native component for "%s" does not exist', + viewName ); + + viewConfig.uiViewClassName = viewName; + viewConfig.validAttributes = {}; + + // ReactNative `View.propTypes` have been deprecated in favor of + // `ViewPropTypes`. In their place a temporary getter has been added with a + // deprecated warning message. Avoid triggering that warning here by using + // temporary workaround, __propTypesSecretDontUseThesePlease. + // TODO (bvaughn) Revert this particular change any time after April 1 + if (componentInterface) { + viewConfig.propTypes = + typeof componentInterface.__propTypesSecretDontUseThesePlease === 'object' + ? componentInterface.__propTypesSecretDontUseThesePlease + : componentInterface.propTypes; + } else { + viewConfig.propTypes = null; + } + + let baseModuleName = viewConfig.baseModuleName; + let nativeProps = { ...viewConfig.NativeProps }; + while (baseModuleName) { + const baseModule = UIManager[baseModuleName]; + if (!baseModule) { + warning(false, 'Base module "%s" does not exist', baseModuleName); + baseModuleName = null; + } else { + nativeProps = { ...nativeProps, ...baseModule.NativeProps }; + baseModuleName = baseModule.baseModuleName; + } + } + + for (const key in nativeProps) { + let useAttribute = false; + const attribute = {}; + + const differ = TypeToDifferMap[nativeProps[key]]; + if (differ) { + attribute.diff = differ; + useAttribute = true; + } + + const processor = TypeToProcessorMap[nativeProps[key]]; + if (processor) { + attribute.process = processor; + useAttribute = true; + } + + viewConfig.validAttributes[key] = useAttribute ? attribute : true; + } + + // Unfortunately, the current set up puts the style properties on the top + // level props object. We also need to add the nested form for API + // compatibility. This allows these props on both the top level and the + // nested style level. TODO: Move these to nested declarations on the + // native side. + viewConfig.validAttributes.style = ReactNativeStyleAttributes; + + if (__DEV__) { + componentInterface && verifyPropTypes( + componentInterface, + viewConfig, + extraConfig && extraConfig.nativeOnly + ); + } + + return viewConfig; } - return createReactNativeComponentClass(viewConfig); + return createReactNativeComponentClass(viewName, getViewConfig); } const TypeToDifferMap = { diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index 41cea1949..bbde094eb 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -c3718c48f01fa6c2e04bd47226061769484c951b \ No newline at end of file +abce30f771e07670b3efac6ffdcab1a7139556a9 \ No newline at end of file diff --git a/Libraries/Renderer/ReactNativeFiber-dev.js b/Libraries/Renderer/ReactNativeFiber-dev.js index 480954d33..efdafee8c 100644 --- a/Libraries/Renderer/ReactNativeFiber-dev.js +++ b/Libraries/Renderer/ReactNativeFiber-dev.js @@ -14,7 +14,7 @@ __DEV__ && function() { var invariant = require("fbjs/lib/invariant"), require$$0 = require("fbjs/lib/warning"), ExceptionsManager = require("ExceptionsManager"), emptyObject = require("fbjs/lib/emptyObject"), react = require("react"), checkPropTypes = require("prop-types/checkPropTypes"), shallowEqual = require("fbjs/lib/shallowEqual"), deepDiffer = require("deepDiffer"), flattenStyle = require("flattenStyle"), TextInputState = require("TextInputState"), UIManager = require("UIManager"), deepFreezeAndThrowOnMutationInDev = require("deepFreezeAndThrowOnMutationInDev"); require("InitializeCore"); - var RCTEventEmitter = require("RCTEventEmitter"), emptyFunction = require("fbjs/lib/emptyFunction"), ExecutionEnvironment = require("fbjs/lib/ExecutionEnvironment"), performanceNow = require("fbjs/lib/performanceNow"), defaultShowDialog = function(capturedError) { + var RCTEventEmitter = require("RCTEventEmitter"), emptyFunction = require("fbjs/lib/emptyFunction"), Platform = require("Platform"), ExecutionEnvironment = require("fbjs/lib/ExecutionEnvironment"), performanceNow = require("fbjs/lib/performanceNow"), defaultShowDialog = function(capturedError) { return !0; }, showDialog = defaultShowDialog; function logCapturedError(capturedError) { @@ -92,7 +92,7 @@ __DEV__ && function() { var evtType = "react-" + (name || "invokeguardedcallback"); window.addEventListener("error", onError), fakeNode.addEventListener(evtType, callCallback, !1); var evt = document.createEvent("Event"); - evt.initEvent(evtType, !1, !1), fakeNode.dispatchEvent(evt), didError ? (didSetError ? isCrossOriginError && (error = new Error("A cross-origin error was thrown. React doesn't have access to " + "the actual error because it catches errors using a global " + 'error handler, in order to preserve the "Pause on exceptions" ' + "behavior of the DevTools. This is only an issue in DEV-mode; " + "in production, React uses a normal try-catch statement.\n\n" + "If you are using React from a CDN, ensure that the