diff --git a/backend/installGlobalHook.js b/backend/installGlobalHook.js index e94f0aa74e..8b88fdefe8 100644 --- a/backend/installGlobalHook.js +++ b/backend/installGlobalHook.js @@ -131,6 +131,55 @@ function installGlobalHook(window: Object) { let hasDetectedBadDCE = false; + function detectRendererName(renderer) { + if (renderer.rendererPackageName) { + return renderer.rendererPackageName; + } + // Try to detect old versions without id injected + try { + var toString = Function.prototype.toString; + if (typeof renderer.version === 'string') { + // React DOM Fiber (16+) + return 'react-dom'; + } + if (renderer.Mount && renderer.Mount._renderNewRootComponent) { + // React DOM Stack like renderer + var renderRootCode = toString.call( + renderer.Mount._renderNewRootComponent + ); + + // React DOM 15.* + if ( + renderRootCode.indexOf('ensureScrollValueMonitoring') !== -1 && + renderRootCode.indexOf('37') !== -1 + ) { + return 'react-dom'; + } + // React DOM Stack 0.13.*/0.14.* + if (renderRootCode.indexOf('_registerComponent') !== -1) { + return 'react-dom'; + } + // Something we're not aware of => not ReactDOM + return 'unknown'; + } + } catch (err) { + // TODO: Mirrors error handling of detectReactBuildType() + } + return 'unknown'; + } + function detectDuplicatedRenderers(renderers) { + // Detect if we have more than one ReactDOM instance + var renderersMap = {}; + + Object.keys(renderers).forEach(id => { + const name = detectRendererName(renderers[id]); + + if (name !== 'unknown') { + renderersMap[name] = renderersMap[name] ? renderersMap[name] + 1 : 1; + } + }); + return Object.keys(renderersMap).map(key => renderersMap[key]).some(rendererCount => rendererCount > 1); + } const hook = ({ // Shared between Stack and Fiber: _renderers: {}, @@ -164,9 +213,13 @@ function installGlobalHook(window: Object) { inject: function(renderer) { var id = Math.random().toString(16).slice(2); hook._renderers[id] = renderer; - var reactBuildType = hasDetectedBadDCE ? - 'deadcode' : - detectReactBuildType(renderer); + var isReactDuplicated = detectDuplicatedRenderers(hook._renderers); + + // Currently we overwrite buildType with each injected renderer's type + var duplicated = isReactDuplicated ? 'duplicated' : null; + var deadcode = hasDetectedBadDCE ? 'deadcode' : null; + + var reactBuildType = duplicated || deadcode || detectReactBuildType(renderer); hook.emit('renderer', {id, renderer, reactBuildType}); return id; }, diff --git a/shells/webextension/icons/128-duplicated.png b/shells/webextension/icons/128-duplicated.png new file mode 100644 index 0000000000..b6ecc88e13 Binary files /dev/null and b/shells/webextension/icons/128-duplicated.png differ diff --git a/shells/webextension/icons/16-duplicated.png b/shells/webextension/icons/16-duplicated.png new file mode 100644 index 0000000000..33d99798e0 Binary files /dev/null and b/shells/webextension/icons/16-duplicated.png differ diff --git a/shells/webextension/icons/32-duplicated.png b/shells/webextension/icons/32-duplicated.png new file mode 100644 index 0000000000..c4a6bda3e6 Binary files /dev/null and b/shells/webextension/icons/32-duplicated.png differ diff --git a/shells/webextension/icons/48-duplicated.png b/shells/webextension/icons/48-duplicated.png new file mode 100644 index 0000000000..f3224021a5 Binary files /dev/null and b/shells/webextension/icons/48-duplicated.png differ diff --git a/shells/webextension/icons/duplicated.svg b/shells/webextension/icons/duplicated.svg new file mode 100644 index 0000000000..6c9d347195 --- /dev/null +++ b/shells/webextension/icons/duplicated.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/shells/webextension/popups/duplicated.html b/shells/webextension/popups/duplicated.html new file mode 100644 index 0000000000..f012ee3868 --- /dev/null +++ b/shells/webextension/popups/duplicated.html @@ -0,0 +1,21 @@ + + +
+ This page is using multiple copies of React. 🚧 +
+
+ Note that using several copies of React may cause problems.
+
+
+ You can find the troubleshooting instructions in React Blog.
+
+ Open the developer tools, and the React tab will appear to the right. +
\ No newline at end of file