1
/**
2
* Install the hook on window, which is an event emitter.
3
- * Note because Chrome content scripts cannot directly modify the window object,
4
- * we are evaling this function by inserting a script tag.
5
- * That's why we have to inline the whole event emitter implementation,
3
+ * Note: this global hook __REACT_DEVTOOLS_GLOBAL_HOOK__ is a de facto public API.
4
+ * It's especially important to avoid creating direct dependency on the DevTools Backend.
5
+ * That's why we still inline the whole event emitter implementation,
6
* the string format implementation, and part of the console implementation here.
7
*
8
* @flow
17
RendererInterface,
18
} from './backend/types';
19
20
-import {
21
- patchConsoleUsingWindowValues,
22
- registerRenderer as registerRendererWithConsole,
23
-} from './backend/console';
24
-import {attach} from './backend/renderer';
25
-import {SESSION_STORAGE_RELOAD_AND_PROFILE_KEY} from './constants';
26
-import {sessionStorageGetItem} from './storage';
27
-
20
declare var window: any;
21
22
export function installHook(target: any): DevToolsHook | null {
332
// * Disabling or marking logs during a double render in Strict Mode
333
// * Disable logging during re-renders to inspect hooks (see inspectHooksOfFiber)
334
//
343
- // For React Native, we intentionally patch early (during injection).
344
- // This provides React Native developers with components stacks even if they don't run DevTools.
345
- //
346
- // This won't work for DOM though, since this entire file is eval'ed and inserted as a script tag.
347
- // In that case, we'll only patch parts of the console that are needed during the first render
348
- // and patch everything else later (when the frontend attaches).
349
- //
350
- // Don't patch in test environments because we don't want to interfere with Jest's own console overrides.
351
- //
352
- // Note that because this function is inlined, this conditional check must only use static booleans.
353
- // Otherwise the extension will throw with an undefined error.
354
- // (See comments in the try/catch below for more context on inlining.)
355
- if (!__TEST__ && !__EXTENSION__) {
356
- try {
357
- // The installHook() function is injected by being stringified in the browser,
358
- // so imports outside of this function do not get included.
359
- //
360
- // Normally we could check "typeof patchConsole === 'function'",
361
- // but Webpack wraps imports with an object (e.g. _backend_console__WEBPACK_IMPORTED_MODULE_0__)
362
- // and the object itself will be undefined as well for the reasons mentioned above,
363
- // so we use try/catch instead.
335
+ // Allow patching console early (during injection) to
336
+ // provide developers with components stacks even if they don't run DevTools.
337
+ if (target.hasOwnProperty('__REACT_DEVTOOLS_CONSOLE_FUNCTIONS__')) {
338
+ const {registerRendererWithConsole, patchConsoleUsingWindowValues} =
339
+ target.__REACT_DEVTOOLS_CONSOLE_FUNCTIONS__;
340
+ if (
341
+ typeof registerRendererWithConsole === 'function' &&
342
+ typeof patchConsoleUsingWindowValues === 'function'
343
+ ) {
344
registerRendererWithConsole(renderer);
345
patchConsoleUsingWindowValues();
366
- } catch (error) {}
346
+ }
347
}
348
349
// If we have just reloaded to profile, we need to inject the renderer interface before the app loads.
350
// Otherwise the renderer won't yet exist and we can skip this step.
371
- if (
372
- sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'
373
- ) {
351
+ const attach = target.__REACT_DEVTOOLS_ATTACH__;
352
+ if (typeof attach === 'function') {
353
const rendererInterface = attach(hook, id, renderer, target);
354
hook.rendererInterfaces.set(id, rendererInterface);
355
}