@@ -20,20 +20,94 @@ function installGlobalHook(window: Object) {
2020 if ( window . __REACT_DEVTOOLS_GLOBAL_HOOK__ ) {
2121 return ;
2222 }
23+ function detectReactBuildType ( renderer ) {
24+ try {
25+ var toString = Function . prototype . toString ;
26+ if ( typeof renderer . version === 'string' ) {
27+ // React DOM Fiber (16+)
28+ if ( renderer . bundleType > 0 ) {
29+ // This is not a production build.
30+ // We are currently only using 0 (PROD) and 1 (DEV)
31+ // but might add 2 (PROFILE) in the future.
32+ return 'development' ;
33+ }
34+ // The above should cover envification, but we should still make sure
35+ // that the bundle code has been uglified.
36+ var findFiberCode = toString . call ( renderer . findFiberByHostInstance ) ;
37+ // Filter out bad results (if that is even possible):
38+ if ( findFiberCode . indexOf ( 'function' ) !== 0 ) {
39+ // Hope for the best if we're not sure.
40+ return 'production' ;
41+ }
42+ // By now we know that it's envified--but what if it's not minified?
43+ // This can be bad too, as it means DEV code is still there.
44+ // Let's check the first argument. It should be a single letter.
45+ if ( ! ( / f u n c t i o n [ \s \w ] * \( \w [ , \) ] / . test ( findFiberCode ) ) ) {
46+ return 'development' ;
47+ }
48+ // We're good.
49+ return 'production' ;
50+ }
51+ if ( renderer . Mount && renderer . Mount . _renderNewRootComponent ) {
52+ // React DOM Stack
53+ var renderRootCode = toString . call ( renderer . Mount . _renderNewRootComponent ) ;
54+ // Filter out bad results (if that is even possible):
55+ if ( renderRootCode . indexOf ( 'function' ) !== 0 ) {
56+ // Hope for the best if we're not sure.
57+ return 'production' ;
58+ }
59+ // React DOM Stack < 15.1.0
60+ // If it contains "storedMeasure" call, it's wrapped in ReactPerf (DEV only).
61+ // This would be true even if it's minified, as method name still matches.
62+ if ( renderRootCode . indexOf ( 'storedMeasure' ) !== - 1 ) {
63+ return 'development' ;
64+ }
65+ // React DOM Stack >= 15.1.0, < 16
66+ // If it contains a warning message, it's a DEV build.
67+ // This would be true even if it's minified, as the message would stay.
68+ if ( renderRootCode . indexOf ( 'should be a pure function' ) !== - 1 ) {
69+ return 'development' ;
70+ }
71+ // By now we know that it's envified--but what if it's not minified?
72+ // This can be bad too, as it means DEV code is still there.
73+ // Let's check the first argument. It should be a single letter.
74+ // We know this function gets more than one argument in all supported
75+ // versions, and if it doesn't have arguments, it's wrapped in ReactPerf
76+ // (which also indicates a DEV build, although we should've filtered
77+ // that out earlier).
78+ if ( ! ( / f u n c t i o n \s * \( \w \, / . test ( renderRootCode ) ) ) {
79+ return 'development' ;
80+ }
81+ // Seems like we're using the production version.
82+ // Now let's check if we're still on 0.14 or lower:
83+ if ( renderRootCode . indexOf ( '._registerComponent' ) !== - 1 ) {
84+ // TODO: we can remove the condition above once 16
85+ // is older than a year. Since this branch only runs
86+ // for Stack, we can flip it completely when Stack
87+ // is old enough. The branch for Fiber is above,
88+ // and it can check renderer.version directly.
89+ return 'outdated' ;
90+ }
91+ // We're all good.
92+ return 'production' ;
93+ }
94+ } catch ( err ) {
95+ // Weird environments may exist.
96+ // This code needs a higher fault tolerance
97+ // because it runs even with closed DevTools.
98+ // TODO: should we catch errors in all injected code, and not just this part?
99+ }
100+ return 'production' ;
101+ }
23102 const hook = ( {
24103 // Shared between Stack and Fiber:
25104 _renderers : { } ,
26105 helpers : { } ,
27106 inject : function ( renderer ) {
28- if ( typeof renderer . version === 'number' && renderer . version > 1 ) {
29- // This Fiber version is too new and not supported yet.
30- // The version field is declared in ReactFiberDevToolsHook.
31- // Only Fiber releases have the version field.
32- return null ;
33- }
34107 var id = Math . random ( ) . toString ( 16 ) . slice ( 2 ) ;
35108 hook . _renderers [ id ] = renderer ;
36- hook . emit ( 'renderer' , { id, renderer} ) ;
109+ var reactBuildType = detectReactBuildType ( renderer ) ;
110+ hook . emit ( 'renderer' , { id, renderer, reactBuildType} ) ;
37111 return id ;
38112 } ,
39113 _listeners : { } ,
0 commit comments