Fix Cannot read property 'sub' of undefined when navigating to plain-text pages (#17848)
Update various parts of DevTools to account for the fact that the global "hook" might be undefined if DevTools didn't inject it (due to the page's `contentType`) it (due to the page's `contentType`)
Mark Huang committed
Feb 3, 2020 at 04:04 UTC
08c1f79e1e13719ae2b79240bbd8f97178ddd791
6 files changed
+27
-14
packages/react-devtools-core/src/backend.js
+5
-1
@@ -32,7 +32,7 @@ type ConnectOptions = {
32
33
installHook(window);
34
35
-const hook: DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
35
+const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
36
37
let savedComponentFilters: Array<ComponentFilter> = getDefaultComponentFilters();
38
@@ -48,6 +48,10 @@ function debug(methodName: string, ...args) {
48
}
49
50
export function connectToDevTools(options: ?ConnectOptions) {
51
+ if (hook == null) {
52
+ // DevTools didn't get injected into this page (maybe b'c of the contentType).
53
+ return;
54
+ }
55
const {
56
host = 'localhost',
57
nativeStyleEditorValidAttributes,
packages/react-devtools-extensions/src/backend.js
+4
@@ -22,6 +22,10 @@ function welcome(event) {
22
window.addEventListener('message', welcome);
23
24
function setup(hook) {
25
+ if (hook == null) {
26
+ // DevTools didn't get injected into this page (maybe b'c of the contentType).
27
+ return;
28
+ }
29
const Agent = require('react-devtools-shared/src/backend/agent').default;
30
const Bridge = require('react-devtools-shared/src/bridge').default;
31
const {initBackend} = require('react-devtools-shared/src/backend');
packages/react-devtools-extensions/src/injectGlobalHook.js
+1
-1
@@ -88,7 +88,7 @@ if (sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true') {
88
89
// Inject a __REACT_DEVTOOLS_GLOBAL_HOOK__ global for React to interact with.
90
// Only do this for HTML documents though, to avoid e.g. breaking syntax highlighting for XML docs.
91
-if (document.contentType === 'text/html') {
91
+if ('text/html' === document.contentType) {
92
injectCode(
93
';(' +
94
installHook.toString() +
packages/react-devtools-extensions/src/main.js
+1
-1
@@ -271,7 +271,7 @@ function createPanelIfReactLoaded() {
271
// When the user chooses a different node in the browser Elements tab,
272
// copy it over to the hook object so that we can sync the selection.
273
chrome.devtools.inspectedWindow.eval(
274
- '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 !== $0) ?' +
274
+ '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__ && window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 !== $0) ?' +
275
'(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 = $0, true) :' +
276
'false',
277
(didSelectionChange, evalError) => {
packages/react-devtools-inline/src/backend.js
+12
-11
@@ -73,17 +73,18 @@ function finishActivation(contentWindow: window) {
73
const agent = new Agent(bridge);
74
75
const hook = contentWindow.__REACT_DEVTOOLS_GLOBAL_HOOK__;
76
-
77
- initBackend(hook, agent, contentWindow);
78
-
79
- // Setup React Native style editor if a renderer like react-native-web has injected it.
80
- if (hook.resolveRNStyle) {
81
- setupNativeStyleEditor(
82
- bridge,
83
- agent,
84
- hook.resolveRNStyle,
85
- hook.nativeStyleEditorValidAttributes,
86
- );
76
+ if (hook) {
77
+ initBackend(hook, agent, contentWindow);
78
+
79
+ // Setup React Native style editor if a renderer like react-native-web has injected it.
80
+ if (hook.resolveRNStyle) {
81
+ setupNativeStyleEditor(
82
+ bridge,
83
+ agent,
84
+ hook.resolveRNStyle,
85
+ hook.nativeStyleEditorValidAttributes,
86
+ );
87
+ }
88
}
89
}
90
packages/react-devtools-shared/src/backend/index.js
+4
@@ -19,6 +19,10 @@ export function initBackend(
19
agent: Agent,
20
global: Object,
21
): () => void {
22
+ if (hook == null) {
23
+ // DevTools didn't get injected into this page (maybe b'c of the contentType).
24
+ return () => {};
25
+ }
26
const subs = [
27
hook.sub(
28
'renderer-attached',