Skip to content

Commit 5a31758

Browse files
authored
[DevTools] Allow inspection before streaming has finished in Chrome (facebook#34360)
1 parent ba6590d commit 5a31758

File tree

5 files changed

+61
-9
lines changed

5 files changed

+61
-9
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ module.exports = {
577577
$AsyncIterator: 'readonly',
578578
Iterator: 'readonly',
579579
AsyncIterator: 'readonly',
580+
IntervalID: 'readonly',
580581
IteratorResult: 'readonly',
581582
JSONValue: 'readonly',
582583
JSResourceReference: 'readonly',

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const contentScriptsToInject = [
66
js: ['build/proxy.js'],
77
matches: ['<all_urls>'],
88
persistAcrossSessions: true,
9-
runAt: 'document_end',
9+
runAt: 'document_start',
1010
world: chrome.scripting.ExecutionWorld.ISOLATED,
1111
},
1212
{
Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,41 @@
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

3-
export function executeScriptInIsolatedWorld({target, files}) {
11+
export function executeScriptInIsolatedWorld({
12+
target,
13+
files,
14+
}: {
15+
files: any,
16+
target: any,
17+
}): Promise<void> {
418
return chrome.scripting.executeScript({
519
target,
620
files,
721
world: chrome.scripting.ExecutionWorld.ISOLATED,
822
});
923
}
1024

11-
export function executeScriptInMainWorld({target, files}) {
25+
export function executeScriptInMainWorld({
26+
target,
27+
files,
28+
injectImmediately,
29+
}: {
30+
files: any,
31+
target: any,
32+
// It's nice to have this required to make active choices.
33+
injectImmediately: boolean,
34+
}): Promise<void> {
1235
return chrome.scripting.executeScript({
1336
target,
1437
files,
38+
injectImmediately,
1539
world: chrome.scripting.ExecutionWorld.MAIN,
1640
});
1741
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* global chrome */
22

3+
import {__DEBUG__} from 'react-devtools-shared/src/constants';
34
import setExtensionIconAndPopup from './setExtensionIconAndPopup';
45
import {executeScriptInMainWorld} from './executeScript';
56

@@ -25,6 +26,7 @@ export function handleBackendManagerMessage(message, sender) {
2526
payload.versions.forEach(version => {
2627
if (EXTENSION_CONTAINED_VERSIONS.includes(version)) {
2728
executeScriptInMainWorld({
29+
injectImmediately: true,
2830
target: {tabId: sender.tab.id},
2931
files: [`/build/react_devtools_backend_${version}.js`],
3032
});
@@ -79,9 +81,19 @@ export function handleDevToolsPageMessage(message) {
7981
}
8082

8183
executeScriptInMainWorld({
84+
injectImmediately: true,
8285
target: {tabId},
8386
files: ['/build/backendManager.js'],
84-
});
87+
}).then(
88+
() => {
89+
if (__DEBUG__) {
90+
console.log('Successfully injected backend manager');
91+
}
92+
},
93+
reason => {
94+
console.error('Failed to inject backend manager:', reason);
95+
},
96+
);
8597

8698
break;
8799
}

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
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';
412

5-
window.addEventListener('pageshow', function ({target}) {
13+
function injectProxy({target}: {target: any}) {
614
// Firefox's behaviour for injecting this content script can be unpredictable
715
// While navigating the history, some content scripts might not be re-injected and still be alive
816
if (!window.__REACT_DEVTOOLS_PROXY_INJECTED__) {
@@ -14,15 +22,19 @@ window.addEventListener('pageshow', function ({target}) {
1422
// The backend waits to install the global hook until notified by the content script.
1523
// In the event of a page reload, the content script might be loaded before the backend manager is injected.
1624
// Because of this we need to poll the backend manager until it has been initialized.
17-
const intervalID = setInterval(() => {
25+
const intervalID: IntervalID = setInterval(() => {
1826
if (backendInitialized) {
1927
clearInterval(intervalID);
2028
} else {
2129
sayHelloToBackendManager();
2230
}
2331
}, 500);
2432
}
25-
});
33+
}
34+
35+
window.addEventListener('pagereveal', injectProxy);
36+
// For backwards compat with browsers not implementing `pagereveal` which is a fairly new event.
37+
window.addEventListener('pageshow', injectProxy);
2638

2739
window.addEventListener('pagehide', function ({target}) {
2840
if (target !== window.document) {
@@ -45,7 +57,7 @@ function sayHelloToBackendManager() {
4557
);
4658
}
4759

48-
function handleMessageFromDevtools(message) {
60+
function handleMessageFromDevtools(message: any) {
4961
window.postMessage(
5062
{
5163
source: 'react-devtools-content-script',
@@ -55,7 +67,7 @@ function handleMessageFromDevtools(message) {
5567
);
5668
}
5769

58-
function handleMessageFromPage(event) {
70+
function handleMessageFromPage(event: any) {
5971
if (event.source !== window || !event.data) {
6072
return;
6173
}
@@ -65,6 +77,7 @@ function handleMessageFromPage(event) {
6577
case 'react-devtools-bridge': {
6678
backendInitialized = true;
6779

80+
// $FlowFixMe[incompatible-use]
6881
port.postMessage(event.data.payload);
6982
break;
7083
}
@@ -99,6 +112,8 @@ function connectPort() {
99112

100113
window.addEventListener('message', handleMessageFromPage);
101114

115+
// $FlowFixMe[incompatible-use]
102116
port.onMessage.addListener(handleMessageFromDevtools);
117+
// $FlowFixMe[incompatible-use]
103118
port.onDisconnect.addListener(handleDisconnect);
104119
}

0 commit comments

Comments
 (0)