Skip to content

Commit 7b5b561

Browse files
authored
[DevTools] Ignore new production renderers if we already use "worse" versions of React on a page (facebook#35994)
1 parent 014138d commit 7b5b561

File tree

6 files changed

+89
-15
lines changed

6 files changed

+89
-15
lines changed

packages/react-devtools-extensions/src/background/setExtensionIconAndPopup.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
19
/* global chrome */
210

311
'use strict';
12+
import type {ReactBuildType} from 'react-devtools-shared/src/backend/types';
413

5-
function setExtensionIconAndPopup(reactBuildType, tabId) {
14+
function setExtensionIconAndPopup(
15+
reactBuildType: ReactBuildType,
16+
tabId: number,
17+
) {
618
chrome.action.setIcon({
719
tabId,
820
path: {

packages/react-devtools-extensions/src/contentScripts/installHook.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
getProfilingSettings,
1111
} from 'react-devtools-shared/src/utils';
1212
import {postMessage} from './messages';
13+
import {createReactRendererListener} from './reactBuildType';
1314

1415
let resolveHookSettingsInjection: (settings: DevToolsHookSettings) => void;
1516
let resolveComponentFiltersInjection: (filters: Array<ComponentFilter>) => void;
@@ -67,17 +68,6 @@ if (!window.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {
6768
// Detect React
6869
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.on(
6970
'renderer',
70-
function ({reactBuildType}) {
71-
window.postMessage(
72-
{
73-
source: 'react-devtools-hook',
74-
payload: {
75-
type: 'react-renderer-attached',
76-
reactBuildType,
77-
},
78-
},
79-
'*',
80-
);
81-
},
71+
createReactRendererListener(window),
8272
);
8373
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
import type {ReactBuildType} from 'react-devtools-shared/src/backend/types';
10+
11+
function reduceReactBuild(
12+
currentReactBuildType: null | ReactBuildType,
13+
nextReactBuildType: ReactBuildType,
14+
): ReactBuildType {
15+
if (
16+
currentReactBuildType === null ||
17+
currentReactBuildType === 'production'
18+
) {
19+
return nextReactBuildType;
20+
}
21+
22+
// We only display the "worst" build type, so if we've already detected a non-production build,
23+
// we ignore any future production builds. This way if a page has multiple renderers,
24+
// and at least one of them is a non-production build, we'll display that instead of "production".
25+
return nextReactBuildType === 'production'
26+
? currentReactBuildType
27+
: nextReactBuildType;
28+
}
29+
30+
export function createReactRendererListener(target: {
31+
postMessage: Function,
32+
...
33+
}): ({reactBuildType: ReactBuildType}) => void {
34+
let displayedReactBuild: null | ReactBuildType = null;
35+
36+
return function ({reactBuildType}) {
37+
displayedReactBuild = reduceReactBuild(displayedReactBuild, reactBuildType);
38+
39+
target.postMessage(
40+
{
41+
source: 'react-devtools-hook',
42+
payload: {
43+
type: 'react-renderer-attached',
44+
reactBuildType: displayedReactBuild,
45+
},
46+
},
47+
'*',
48+
);
49+
};
50+
}

packages/react-devtools-shared/src/backend/types.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,3 +603,10 @@ export type DevToolsHookSettings = {
603603
export type DevToolsSettings = DevToolsHookSettings & {
604604
componentFilters: Array<ComponentFilter>,
605605
};
606+
607+
export type ReactBuildType =
608+
| 'deadcode'
609+
| 'development'
610+
| 'outdated'
611+
| 'production'
612+
| 'unminified';

packages/react-devtools-shared/src/hook.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
DevToolsBackend,
1818
DevToolsHookSettings,
1919
ProfilingSettings,
20+
ReactBuildType,
2021
} from './backend/types';
2122
import type {ComponentFilter} from './frontend/types';
2223

@@ -71,7 +72,7 @@ export function installHook(
7172
return null;
7273
}
7374

74-
function detectReactBuildType(renderer: ReactRenderer) {
75+
function detectReactBuildType(renderer: ReactRenderer): ReactBuildType {
7576
try {
7677
if (typeof renderer.version === 'string') {
7778
// React DOM Fiber (16+)
@@ -211,7 +212,7 @@ export function installHook(
211212
const id = ++uidCounter;
212213
renderers.set(id, renderer);
213214

214-
const reactBuildType = hasDetectedBadDCE
215+
const reactBuildType: ReactBuildType = hasDetectedBadDCE
215216
? 'deadcode'
216217
: detectReactBuildType(renderer);
217218

scripts/flow/react-devtools.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ declare const __IS_CHROME__: boolean;
1717
declare const __IS_EDGE__: boolean;
1818
declare const __IS_NATIVE__: boolean;
1919

20+
interface ExtensionAction {
21+
/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setIcon} */
22+
setIcon(details: {
23+
tabId: number,
24+
path?: string | {[iconSize: string]: string},
25+
}): void;
26+
/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/setPopup} */
27+
setPopup(details: {tabId: number, popup: string}): void;
28+
}
29+
2030
interface ExtensionDevtools {
2131
/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools/inspectedWindow} */
2232
inspectedWindow: $FlowFixMe;
@@ -73,6 +83,8 @@ interface ExtensionRuntime {
7383
extensionId: string,
7484
connectInfo?: {name?: string, includeTlsChannelId?: boolean},
7585
): ExtensionRuntimePort;
86+
/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/getURL} */
87+
getURL(path: string): string;
7688
/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage} */
7789
onMessage: ExtensionEvent<
7890
(
@@ -108,6 +120,8 @@ interface ExtensionTabs {
108120
}
109121

110122
interface ExtensionAPI {
123+
/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action} */
124+
action: ExtensionAction;
111125
devtools: ExtensionDevtools;
112126
/** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/permissions} */
113127
permissions: $FlowFixMe;

0 commit comments

Comments
 (0)