From 1f0334f0bcfa211da978c5e75016333369b04404 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 13 Sep 2017 23:33:15 +0100 Subject: [PATCH 1/2] Add bad DCE detection for React 16 --- backend/installGlobalHook.js | 51 +++++++++++--------- shells/webextension/icons/128-deadcode.png | Bin 0 -> 5201 bytes shells/webextension/icons/16-deadcode.png | Bin 0 -> 638 bytes shells/webextension/icons/32-deadcode.png | Bin 0 -> 1318 bytes shells/webextension/icons/48-deadcode.png | Bin 0 -> 2001 bytes shells/webextension/icons/deadcode.svg | 1 + shells/webextension/popups/deadcode.html | 24 +++++++++ shells/webextension/popups/development.html | 2 +- shells/webextension/popups/disabled.html | 2 +- shells/webextension/popups/outdated.html | 2 +- shells/webextension/popups/production.html | 2 +- shells/webextension/popups/unminified.html | 2 +- 12 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 shells/webextension/icons/128-deadcode.png create mode 100644 shells/webextension/icons/16-deadcode.png create mode 100644 shells/webextension/icons/32-deadcode.png create mode 100644 shells/webextension/icons/48-deadcode.png create mode 100644 shells/webextension/icons/deadcode.svg create mode 100644 shells/webextension/popups/deadcode.html diff --git a/backend/installGlobalHook.js b/backend/installGlobalHook.js index 93973c90f9..9676be1974 100644 --- a/backend/installGlobalHook.js +++ b/backend/installGlobalHook.js @@ -22,7 +22,6 @@ function installGlobalHook(window: Object) { } function detectReactBuildType(renderer) { try { - var toString = Function.prototype.toString; if (typeof renderer.version === 'string') { // React DOM Fiber (16+) if (renderer.bundleType > 0) { @@ -31,29 +30,17 @@ function installGlobalHook(window: Object) { // but might add 2 (PROFILE) in the future. return 'development'; } - // The above should cover envification, but we should still make sure - // that the bundle code has been uglified. - var findFiberCode = toString.call(renderer.findFiberByHostInstance); - // Filter out bad results (if that is even possible): - if (findFiberCode.indexOf('function') !== 0) { - // Hope for the best if we're not sure. - return 'production'; - } - - // By now we know that it's envified--but what if it's not minified? - // This can be bad too, as it means DEV code is still there. - - // FIXME: this is fragile! - // We should replace this check with check on a specially passed - // function. This also doesn't detect lack of dead code elimination - // (although this is not a problem since flat bundles). - if (findFiberCode.indexOf('getClosestInstanceFromNode') !== -1) { - return 'unminified'; - } - // We're good. + // React 16 uses flat bundles. If we report the bundle as production + // version, it means we also minified and envified it ourselves. return 'production'; + // Note: There is still a risk that the CommonJS entry point has not + // been envified or uglified. In this case the user would have *both* + // development and production bundle, but only the prod one would run. + // This would be really bad. We have a separate check for this because + // it happens *outside* of the renderer injection. See `checkDCE` below. } + var toString = Function.prototype.toString; if (renderer.Mount && renderer.Mount._renderNewRootComponent) { // React DOM Stack var renderRootCode = toString.call(renderer.Mount._renderNewRootComponent); @@ -141,14 +128,34 @@ function installGlobalHook(window: Object) { } return 'production'; } + + let hasDetectedBadDCE = false; + const hook = ({ // Shared between Stack and Fiber: _renderers: {}, helpers: {}, + checkDCE: function(fn) { + // This runs for production versions of React. + // Needs to be super safe. + try { + var toString = Function.prototype.toString; + var code = toString.call(fn); + // This is a string embedded in the passed function under DEV-only + // condition. However the function executes only in PROD. Therefore, + // if we see it, dead code elimination did not work. + if (code.indexOf('^_^') > -1) { + // Remember to report during next injection. + hasDetectedBadDCE = true; + } + } catch (err) { } + }, inject: function(renderer) { var id = Math.random().toString(16).slice(2); hook._renderers[id] = renderer; - var reactBuildType = detectReactBuildType(renderer); + var reactBuildType = hasDetectedBadDCE ? + 'deadcode' : + detectReactBuildType(renderer); hook.emit('renderer', {id, renderer, reactBuildType}); return id; }, diff --git a/shells/webextension/icons/128-deadcode.png b/shells/webextension/icons/128-deadcode.png new file mode 100644 index 0000000000000000000000000000000000000000..b6ecc88e13ac082da3b82b48179b8a665fef6214 GIT binary patch literal 5201 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 LNkvXXu0mjfgeJQI literal 0 HcmV?d00001 diff --git a/shells/webextension/icons/16-deadcode.png b/shells/webextension/icons/16-deadcode.png new file mode 100644 index 0000000000000000000000000000000000000000..33d99798e07b27bd48862e9d5779206bc96f9e4b GIT binary patch literal 638 zcmV-^0)hRBP)0 z5Ee=iwzklA@y)=lrIw46Om=qOn|a^&y?M58v8zh}>hXUTmx_zswGHq$HAC`vt(+rt z5oOnJ@LG}8OU1>(+Z|9M)wuj(gd0&I#gf;DaNhv06`H;9$5q#WMK8*HAt+4rwLM`cMUdq%=7LO-CU}b*ZqMO%`w2<$H1O2(= zHYz%M8Gazvii01k@Fg^yOKPa~D40&Bxk>1Z3@w{S^nMQ#!>^GQRBd7s56!M+EjQtB zj6whM8Ql*bVQz09sl0)AH9gg-kg%(aRvV9NQnZ~o9 zzZk{fm2!Aw+ld1$4NRk1mpwjY)bC77&E&8_!ugbvH$({Hg)g#j&dDN9JNs$R`Huht Y0J(_O53sM9y8r+H07*qoM6N<$g5#(xe*gdg literal 0 HcmV?d00001 diff --git a/shells/webextension/icons/32-deadcode.png b/shells/webextension/icons/32-deadcode.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a6bda3e6a6d0df9388f3beff37e254a91df25c GIT binary patch literal 1318 zcmV+>1=;$EP)_r`D3!8(9ZZPOzH)}VTUMvIY zO?R^j>(!KY%-^(KY@6hyO=1$i=S{zOPI^pY9P@?4NxppN{dwN!eZCXhUxyAf5z(Z$ zUZ?-pu8V6xc|pNxGv=i7f`XTluvgpRXltjYH;<5`wVl@IW-0mmG-VebSnl=g*+<@R zFS)zAX=C9Q#U?IOUQbr^Zxb9SR0{sm7vGWM)hI0-x`boc%1=L-oMT_;<5Sci62KY~ z#9rM0Ir(nIBq}0+$`Kq+kN`dh2ai!etfSiK*jZA&KH7fz9PeMgG|tJv8V?@kq_l7! z#UsDemjIvy>lJ2rV> zPPB)zOVNt{?bYB1;WRN?aOUdl=IUi%JHPp{v=T9U!GuGNuHKV+KnKwxfDHyd;Q*3Sm~WEj2^Ve#huV zvJ3G-0`Os_A29V~_s%oY!OqXdO9AhX4Aa`RNrv9N`&Ck0F8*zCe1x6O=^2Wwt#+F`A#dP{)ho9k}ilu0mNM?`MxkW$Lgg@Ehn#QnJYjdi!n9cEZ zDH^AFfs&P}WqP4VrUG86@kT=nB&%Bl60oq(y~Q!s#_p}rdpDQ)``)tZVek)s^1LvS zu*mp6YJTe-=0f`KqRIu29wVF6Ne@MP@GykMb9BKA|44D7E`Gi>0kE>j&Ma#H5MJ3dSWcSOWGjXQ zLYR=6r5MlyDg;Locg4tHO5}vF2CU{x&qP+&slVAvk(G5OBFrlgINcEtcUygj5wyQ3 zyR%$9?qQ#czU^t*oO?%U@7K`;-v?Wtuw2jO>CaTA{?ky^G|DBdU#9@+@sQ6H3@td= z)L@!`3t}?P-d<(Y>N<{bx>=c?D{#PaF#`O9Et+9GU8LvprM5g%0;nEmffY%o9_lPM zAehmh1yDdB(dJND9Y@~ literal 0 HcmV?d00001 diff --git a/shells/webextension/icons/48-deadcode.png b/shells/webextension/icons/48-deadcode.png new file mode 100644 index 0000000000000000000000000000000000000000..f3224021a560c7d543178c3159c05cee9eebac9f GIT binary patch literal 2001 zcmV;?2QK)DP)So#v3TzJq(Wsh2i& zG*EU}yE;NUI=Ua^#KHHdqnNVGCe=}=#Ur0>;3YW+duL9bgXdyAqwo>N50zKe81@MAWi+;L1Q<+bnF0{c*V&D zTR-`lJXO`EYcpM)H2TG524rS|`h8UP&KY*x%qDJqN26CSXD$OJhu_e_kA3qMh40=W zEfC;na#ZVMQ5{hrkP&0nDnl*24ugY}3M?`w_r>*ib&^S#>%HpDAEkS8#p!0sEeSGs zq&qq?NRh{X(M)$Imq1?mMs^TD5oLUi*UjfIvt#1;-xr%{zVA0$ni%H;=V2Y^u0$g= z_e*zXG9b~PX#X~84N(O!M6v9|8IGu@YCD5M29{@M=+W6zmeED|T&K#RwhLU>phYkb49)Gc2mt6fpxWMm!iyGC0vSUYNiY^i22FbkYZz{r)>g74r2_yPJbH|q&ln}C ze>A9+5%duZItFvV&X76u3GRj2fLHVmzDu%T>@n#fD@Qad%>z&Z9ybBtKVCn;pkvY8 z&adV1h@y^DftTi%Kmd4*f$H=ji0{C6iIxHeV6kGbBrOEKE`9AS%5l3H?2`{e>Si6R zc{pWmPfY8mi5XF#1;kM62l@b;U0R_lgHv>Ce2#8UhUxBXglhdBa%(xPbygw~^6%M8 z`8#*16713MF{~&T&Y9^eoG<#y(gEB^JOzLMbN#cV!Gcu6L06za&k!6P|KWxX{_Xxz z>I+9{IJ(5g!2BY0OoZuBiI1Itki)gOho&Yxg0(m@MC0GzNNViq&fEM72axrJKl}Ay zu3{l0JB%jC;l!I_&Da~*1BiV-G^LzaPPz`CVeS3riu7nNDOn;K$YUeoP+GYv`YaR` z14H%+@N#p`MGp@rKV}p&Th+CO)4U_$0-|y6PZ&2gsyAXK7EO7s)%R$|h)BI-&uhP@J-BK}8RbEFp3Cw&Sv!4yj6Qzyl)9!C`0rZ3 zJEa4`qsR5RW0?WjRD+YPXbahq`j^rPHXhU0PgWL^-<6zLe1v3F7M^K!IIq!~L z>^yiLR9Ro>W#BmQzH@4xS{_cAGSuV9BA+MDfPyRBE*_G=0MHn2VH2TeDJ5i57AXhJ zni^CKXP1=tLX?m_?3JaDt`1G>&3RwV0W;u61HEG4bxkkuxvkqu>E**mRx!|;#2moG ziP$FHoU26xfeukJRo+}W`(T^_8SUEkG74xK4>~)C>I=N=5Xy1gavBlk=&A#Kf#yaj z$);U&5SsI<8dTD-rgI>&L=}D)HI@bRbB$Kz&7+p*i>bnf$=0WY8@pAeIy#` znLCgw`o`hZrfS~I+Ex8SVsoYvN)4akKo+{wC@06i4|vjeb_sCJibfG_VWdRb1PfhK zT;EXY=Sa)?r58$d2hwS1Z7tw^^-YXo2fbR>ssVrm;{cUelQa zjvlW=F1WXB+*OE=I<_kU&ZC=bXAyqBGs(fa11bfDNrJAHXHySze8 z6$O006LaJMp5R}k4W1oMAPBsj)AWAx#?M&<6kNNZw4A|&tm-Ta3Dmnf1JoR1Lly1e_2s) j>ar{oz*-0F{|YbwKA#E$9zpcP00000NkvXXu0mjf*nPMD literal 0 HcmV?d00001 diff --git a/shells/webextension/icons/deadcode.svg b/shells/webextension/icons/deadcode.svg new file mode 100644 index 0000000000..ccd6e66906 --- /dev/null +++ b/shells/webextension/icons/deadcode.svg @@ -0,0 +1 @@ +development780780 \ No newline at end of file diff --git a/shells/webextension/popups/deadcode.html b/shells/webextension/popups/deadcode.html new file mode 100644 index 0000000000..2f617cbe7d --- /dev/null +++ b/shells/webextension/popups/deadcode.html @@ -0,0 +1,24 @@ + + +

+ This page includes an extra development build of React. 🚧 +

+

+ The React build on this page includes both development and production versions because dead code elimination has not been applied correctly. +
+
+ This makes its size larger, and causes React to run slower. +
+
+ Make sure to set up dead code elimination before deployment. +

+
+

+ Open the developer tools, and the React tab will appear to the right. +

diff --git a/shells/webextension/popups/development.html b/shells/webextension/popups/development.html index 2f3f80fce5..3f9985b07a 100644 --- a/shells/webextension/popups/development.html +++ b/shells/webextension/popups/development.html @@ -2,7 +2,7 @@ diff --git a/shells/webextension/popups/disabled.html b/shells/webextension/popups/disabled.html index db048781df..061d0d4b4d 100644 --- a/shells/webextension/popups/disabled.html +++ b/shells/webextension/popups/disabled.html @@ -2,7 +2,7 @@ diff --git a/shells/webextension/popups/outdated.html b/shells/webextension/popups/outdated.html index 66269d9180..3933ef48e2 100644 --- a/shells/webextension/popups/outdated.html +++ b/shells/webextension/popups/outdated.html @@ -2,7 +2,7 @@ diff --git a/shells/webextension/popups/production.html b/shells/webextension/popups/production.html index 81417e83c3..6899ead477 100644 --- a/shells/webextension/popups/production.html +++ b/shells/webextension/popups/production.html @@ -2,7 +2,7 @@ diff --git a/shells/webextension/popups/unminified.html b/shells/webextension/popups/unminified.html index d8b8b7428f..043e3d6804 100644 --- a/shells/webextension/popups/unminified.html +++ b/shells/webextension/popups/unminified.html @@ -2,7 +2,7 @@ From e0159b13b76f6d435b358775e27a011374999de6 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 13 Sep 2017 23:58:42 +0100 Subject: [PATCH 2/2] Throw an error in setTimeout for reporting --- backend/installGlobalHook.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/installGlobalHook.js b/backend/installGlobalHook.js index 9676be1974..8bbb431f26 100644 --- a/backend/installGlobalHook.js +++ b/backend/installGlobalHook.js @@ -147,6 +147,17 @@ function installGlobalHook(window: Object) { if (code.indexOf('^_^') > -1) { // Remember to report during next injection. hasDetectedBadDCE = true; + // Bonus: throw an exception hoping that it gets picked up by + // a reporting system. Not synchronously so that it doesn't break the + // calling code. + setTimeout(function() { + throw new Error( + 'React is running in production mode, but dead code ' + + 'elimination has not been applied. Read how to correctly ' + + 'configure React for production: ' + + 'https://fburl.com/react-perf-use-the-production-build' + ); + }); } } catch (err) { } },