@samitouri / QOS-React-2 / commits / dc8580e64d

New NPM package react-devtools-inline (#363)

Brian Vaughn committed Aug 5, 2019 at 10:09 UTC dc8580e64df475709fd693f87ef85ae25e5181dd
21 files changed +440 -116
.eslintignore
+1
@@ -5,6 +5,7 @@ shells/browser/firefox/build
5 shells/browser/shared/build
6 shells/dev/dist
7 packages/react-devtools-core/dist
8 +packages/react-devtools-inline/dist
9 vendor
10 *.js.snap
11
.gitignore
+4 -2
@@ -4,11 +4,13 @@
4 /shells/browser/firefox/*.pem
5 /shells/browser/shared/build
6 /packages/react-devtools-core/dist
7 +/packages/react-devtools-inline/dist
8 /shells/dev/dist
9 build
10 /node_modules
10 -/packages/react-devtools-core/node_modules/
11 -/packages/react-devtools/node_modules/
11 +/packages/react-devtools-core/node_modules
12 +/packages/react-devtools-inline/node_modules
13 +/packages/react-devtools/node_modules
14 npm-debug.log
15 yarn-error.log
16 .DS_Store
package.json
+2
@@ -34,6 +34,8 @@
34 "scripts": {
35 "build:core:backend": "cd ./packages/react-devtools-core && yarn build:backend",
36 "build:core:standalone": "cd ./packages/react-devtools-core && yarn build:standalone",
37 + "build:core": "cd ./packages/react-devtools-core && yarn build",
38 + "build:inline": "cd ./packages/react-devtools-inline && yarn build",
39 "build:demo": "cd ./shells/dev && cross-env NODE_ENV=development cross-env TARGET=remote webpack --config webpack.config.js",
40 "build:extension": "cross-env NODE_ENV=production yarn run build:extension:chrome && yarn run build:extension:firefox",
41 "build:extension:dev": "cross-env NODE_ENV=development yarn run build:extension:chrome && yarn run build:extension:firefox",
packages/react-devtools-core/package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "react-devtools-core",
3 - "version": "4.0.0-alpha.6",
3 + "version": "4.0.0-alpha.7",
4 "description": "Use react-devtools outside of the browser",
5 "license": "MIT",
6 "main": "./dist/backend.js",
packages/react-devtools-inline/README.md new
+134
@@ -0,0 +1,134 @@
1 +# `react-devtools-inline`
2 +
3 +React DevTools implementation for embedding within a browser-based IDE (e.g. [CodeSandbox](https://codesandbox.io/), [StackBlitz](https://stackblitz.com/)).
4 +
5 +This is a low-level package. If you're looking for the standalone DevTools app, **use the `react-devtools` package instead.**
6 +
7 +## Usage
8 +
9 +This package exports two entry points: a frontend (to be run in the main `window`) and a backend (to be installed and run within an `iframe`<sup>1</sup>).
10 +
11 +The frontend and backend can be initialized in any order, but **the backend must not be activated until after the frontend has been initialized**. Because of this, the simplest sequence is:
12 +
13 +1. Frontend (DevTools interface) initialized in the main `window`.
14 +1. Backend initialized in an `iframe`.
15 +1. Backend activated.
16 +
17 +<sup>1</sup> Sandboxed iframes are supported.
18 +
19 +## API
20 +
21 +### `react-devtools-inline/backend`
22 +
23 +* **`initialize(contentWindow)`** -
24 +Installs the global hook on the window. This hook is how React and DevTools communicate. **This method must be called before React is loaded.** (This means before any `import` or `require` statements!)
25 +* **`activate(contentWindow)`** -
26 +Lets the backend know when the frontend is ready. It should not be called until after the frontend has been initialized, else the frontend might miss important tree-initialization events.
27 +
28 +```js
29 +import { activate, initialize } from 'react-devtools-inline/backend';
30 +
31 +// Call this before importing React (or any other packages that might import React).
32 +initialize();
33 +
34 +// Call this only once the frontend has been initialized.
35 +activate();
36 +```
37 +
38 +### `react-devtools-inline/frontend`
39 +
40 +* **`initialize(contentWindow)`** -
41 +Configures the DevTools interface to listen to the `window` the backend was injected into. This method returns a React component that can be rendered directly.
42 +
43 +```js
44 +import { initialize } from 'react-devtools-inline/frontend';
45 +
46 +// This should be the iframe the backend hook has been installed in.
47 +const iframe = document.getElementById(frameID);
48 +const contentWindow = iframe.contentWindow;
49 +
50 +// This returns a React component that can be rendered into your app.
51 +// <DevTools {...props} />
52 +const DevTools = initialize(contentWindow);
53 +```
54 +
55 +## Examples
56 +
57 +### Configuring a same-origin `iframe`
58 +
59 +The simplest way to use this package is to install the hook from the parent `window`. This is possible if the `iframe` is not sandboxed and there are no cross-origin restrictions.
60 +
61 +```js
62 +import {
63 + activate as activateBackend,
64 + initialize as initializeBackend
65 +} from 'react-devtools-inline/backend';
66 +import { initialize as initializeFrontend } from 'react-devtools-inline/frontend';
67 +
68 +// The React app you want to inspect with DevTools is running within this iframe:
69 +const iframe = document.getElementById('target');
70 +const { contentWindow } = iframe;
71 +
72 +// Installs the global hook into the iframe.
73 +// This be called before React is loaded into that frame.
74 +initializeBackend(contentWindow);
75 +
76 +// React application can be injected into <iframe> at any time now...
77 +
78 +// Initialize DevTools UI to listen to the hook we just installed.
79 +// This returns a React component we can render anywhere in the parent window.
80 +const DevTools = initializeFrontend(contentWindow);
81 +
82 +// <DevTools /> interface can be rendered in the parent window at any time now...
83 +
84 +// Let the backend know the frontend is ready and listening.
85 +activateBackend(contentWindow);
86 +```
87 +
88 +### Configuring a sandboxed `iframe`
89 +
90 +Sandboxed `iframe`s are also supported but require more complex initialization.
91 +
92 +**`iframe.html`**
93 +```js
94 +import { activate, initialize } from 'react-devtools-inline/backend';
95 +
96 +// The DevTooks hook needs to be installed before React is even required!
97 +// The safest way to do this is probably to install it in a separate script tag.
98 +initialize(window);
99 +
100 +// Wait for the frontend to let us know that it's ready.
101 +window.addEventListener('message', ({ data }) => {
102 + switch (data.type) {
103 + case 'activate':
104 + activate(window);
105 + break;
106 + default:
107 + break;
108 + }
109 +});
110 +```
111 +
112 +**`main-window.html`**
113 +```js
114 +import { initialize } from 'react-devtools-inline/frontend';
115 +
116 +const iframe = document.getElementById('target');
117 +const { contentWindow } = iframe;
118 +
119 +// Initialize DevTools UI to listen to the iframe.
120 +// This returns a React component we can render anywhere in the main window.
121 +const DevTools = initialize(contentWindow);
122 +
123 +// Let the backend know to initialize itself.
124 +// We can't do this directly because the iframe is sandboxed.
125 +// Only initialize the backend once the DevTools frontend has been initialized.
126 +iframe.onload = () => {
127 + contentWindow.postMessage(
128 + {
129 + type: 'activate',
130 + },
131 + '*'
132 + );
133 +};
134 +```
\ No newline at end of file
packages/react-devtools-inline/backend.js new
+1
@@ -0,0 +1 @@
1 +module.exports = require('./dist/backend');
packages/react-devtools-inline/frontend.js new
+1
@@ -0,0 +1 @@
1 +module.exports = require('./dist/frontend');
packages/react-devtools-inline/package.json new
+25
@@ -0,0 +1,25 @@
1 +{
2 + "name": "react-devtools-inline",
3 + "version": "4.0.0-alpha.7",
4 + "description": "Embed react-devtools within a website",
5 + "license": "MIT",
6 + "main": "./dist/backend.js",
7 + "repository": {
8 + "url": "https://github.com/bvaughn/react-devtools-experimental.git",
9 + "type": "git"
10 + },
11 + "files": [
12 + "dist",
13 + "backend.js",
14 + "frontend.js"
15 + ],
16 + "scripts": {
17 + "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
18 + "prepublish": "yarn run build",
19 + "start": "cross-env NODE_ENV=development webpack --config webpack.config.js --watch"
20 + },
21 + "dependencies": {},
22 + "devDependencies": {
23 + "cross-env": "^3.1.4"
24 + }
25 +}
packages/react-devtools-inline/src/backend.js new
+96
@@ -0,0 +1,96 @@
1 +/** @flow */
2 +
3 +import Agent from 'src/backend/agent';
4 +import Bridge from 'src/bridge';
5 +import { initBackend } from 'src/backend';
6 +import { installHook } from 'src/hook';
7 +import setupNativeStyleEditor from 'src/backend/NativeStyleEditor/setupNativeStyleEditor';
8 +import {
9 + MESSAGE_TYPE_GET_SAVED_PREFERENCES,
10 + MESSAGE_TYPE_SAVED_PREFERENCES,
11 +} from './constants';
12 +
13 +function startActivation(contentWindow: window) {
14 + const { parent } = contentWindow;
15 +
16 + const onMessage = ({ data }) => {
17 + switch (data.type) {
18 + case MESSAGE_TYPE_SAVED_PREFERENCES:
19 + // This is the only message we're listening for,
20 + // so it's safe to cleanup after we've received it.
21 + contentWindow.removeEventListener('message', onMessage);
22 +
23 + const { appendComponentStack, componentFilters } = data;
24 +
25 + contentWindow.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = appendComponentStack;
26 + contentWindow.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = componentFilters;
27 +
28 + // TRICKY
29 + // The backend entry point may be required in the context of an iframe or the parent window.
30 + // If it's required within the parent window, store the saved values on it as well,
31 + // since the injected renderer interface will read from window.
32 + // Technically we don't need to store them on the contentWindow in this case,
33 + // but it doesn't really hurt anything to store them there too.
34 + if (contentWindow !== window) {
35 + window.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = appendComponentStack;
36 + window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = componentFilters;
37 + }
38 +
39 + finishActivation(contentWindow);
40 + break;
41 + default:
42 + break;
43 + }
44 + };
45 +
46 + contentWindow.addEventListener('message', onMessage);
47 +
48 + // The backend may be unable to read saved preferences directly,
49 + // because they are stored in localStorage within the context of the extension (on the frontend).
50 + // Instead it relies on the extension to pass preferences through.
51 + // Because we might be in a sandboxed iframe, we have to ask for them by way of postMessage().
52 + parent.postMessage({ type: MESSAGE_TYPE_GET_SAVED_PREFERENCES }, '*');
53 +}
54 +
55 +function finishActivation(contentWindow: window) {
56 + const { parent } = contentWindow;
57 +
58 + const bridge = new Bridge({
59 + listen(fn) {
60 + const onMessage = event => {
61 + fn(event.data);
62 + };
63 + contentWindow.addEventListener('message', onMessage);
64 + return () => {
65 + contentWindow.removeEventListener('message', onMessage);
66 + };
67 + },
68 + send(event: string, payload: any, transferable?: Array<any>) {
69 + parent.postMessage({ event, payload }, '*', transferable);
70 + },
71 + });
72 +
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 + );
87 + }
88 +}
89 +
90 +export function activate(contentWindow: window): void {
91 + startActivation(contentWindow);
92 +}
93 +
94 +export function initialize(contentWindow: window): void {
95 + installHook(contentWindow);
96 +}
packages/react-devtools-inline/src/constants.js new
+6
@@ -0,0 +1,6 @@
1 +/** @flow */
2 +
3 +export const MESSAGE_TYPE_GET_SAVED_PREFERENCES =
4 + 'React::DevTools::getSavedPreferences';
5 +export const MESSAGE_TYPE_SAVED_PREFERENCES =
6 + 'React::DevTools::savedPreferences';
packages/react-devtools-inline/src/frontend.js new
+68
@@ -0,0 +1,68 @@
1 +/** @flow */
2 +
3 +import React, { forwardRef } from 'react';
4 +import Bridge from 'src/bridge';
5 +import Store from 'src/devtools/store';
6 +import DevTools from 'src/devtools/views/DevTools';
7 +import { getSavedComponentFilters, getAppendComponentStack } from 'src/utils';
8 +import {
9 + MESSAGE_TYPE_GET_SAVED_PREFERENCES,
10 + MESSAGE_TYPE_SAVED_PREFERENCES,
11 +} from './constants';
12 +
13 +import type { FrontendBridge } from 'src/bridge';
14 +import type { Props } from 'src/devtools/views/DevTools';
15 +
16 +export function initialize(
17 + contentWindow: window
18 +): React$AbstractComponent<Props, mixed> {
19 + const onMessage = ({ data, origin, source }) => {
20 + switch (data.type) {
21 + case MESSAGE_TYPE_GET_SAVED_PREFERENCES:
22 + // This is the only message we're listening for,
23 + // so it's safe to cleanup after we've received it.
24 + window.removeEventListener('message', onMessage);
25 +
26 + // The renderer interface can't read saved preferences directly,
27 + // because they are stored in localStorage within the context of the extension.
28 + // Instead it relies on the extension to pass them through.
29 + contentWindow.postMessage(
30 + {
31 + type: MESSAGE_TYPE_SAVED_PREFERENCES,
32 + appendComponentStack: getAppendComponentStack(),
33 + componentFilters: getSavedComponentFilters(),
34 + },
35 + '*'
36 + );
37 + break;
38 + default:
39 + break;
40 + }
41 + };
42 +
43 + window.addEventListener('message', onMessage);
44 +
45 + const bridge: FrontendBridge = new Bridge({
46 + listen(fn) {
47 + const onMessage = ({ data }) => {
48 + fn(data);
49 + };
50 + window.addEventListener('message', onMessage);
51 + return () => {
52 + window.removeEventListener('message', onMessage);
53 + };
54 + },
55 + send(event: string, payload: any, transferable?: Array<any>) {
56 + contentWindow.postMessage({ event, payload }, '*', transferable);
57 + },
58 + });
59 +
60 + const store: Store = new Store(bridge);
61 +
62 + const ForwardRef = forwardRef<Props, mixed>((props, ref) => (
63 + <DevTools ref={ref} bridge={bridge} store={store} {...props} />
64 + ));
65 + ForwardRef.displayName = 'DevTools';
66 +
67 + return ForwardRef;
68 +}
packages/react-devtools-inline/webpack.config.js new
+74
@@ -0,0 +1,74 @@
1 +const { resolve } = require('path');
2 +const { DefinePlugin } = require('webpack');
3 +const { getGitHubURL, getVersionString } = require('../../shells/utils');
4 +
5 +const NODE_ENV = process.env.NODE_ENV;
6 +if (!NODE_ENV) {
7 + console.error('NODE_ENV not set');
8 + process.exit(1);
9 +}
10 +
11 +const __DEV__ = true; // NODE_ENV === 'development';
12 +
13 +const GITHUB_URL = getGitHubURL();
14 +const DEVTOOLS_VERSION = getVersionString();
15 +
16 +module.exports = {
17 + mode: __DEV__ ? 'development' : 'production',
18 + devtool: false,
19 + entry: {
20 + backend: './src/backend.js',
21 + frontend: './src/frontend.js',
22 + },
23 + output: {
24 + path: __dirname + '/dist',
25 + filename: '[name].js',
26 + library: '[name]',
27 + libraryTarget: 'commonjs2',
28 + },
29 + resolve: {
30 + alias: {
31 + src: resolve(__dirname, '../../src'),
32 + },
33 + },
34 + externals: {
35 + react: 'react',
36 + 'react-dom': 'react-dom',
37 + scheduler: 'scheduler',
38 + },
39 + plugins: [
40 + new DefinePlugin({
41 + __DEV__: __DEV__,
42 + 'process.env.DEVTOOLS_VERSION': `"${DEVTOOLS_VERSION}"`,
43 + 'process.env.GITHUB_URL': `"${GITHUB_URL}"`,
44 + 'process.env.NODE_ENV': `"${NODE_ENV}"`,
45 + }),
46 + ],
47 + module: {
48 + rules: [
49 + {
50 + test: /\.js$/,
51 + loader: 'babel-loader',
52 + options: {
53 + configFile: resolve(__dirname, '../../babel.config.js'),
54 + },
55 + },
56 + {
57 + test: /\.css$/,
58 + use: [
59 + {
60 + loader: 'style-loader',
61 + },
62 + {
63 + loader: 'css-loader',
64 + options: {
65 + sourceMap: true,
66 + modules: true,
67 + localIdentName: '[local]___[hash:base64:5]',
68 + },
69 + },
70 + ],
71 + },
72 + ],
73 + },
74 +};
packages/react-devtools/package.json
+2 -2
@@ -1,6 +1,6 @@
1 {
2 "name": "react-devtools",
3 - "version": "4.0.0-alpha.6",
3 + "version": "4.0.0-alpha.7",
4 "description": "Use react-devtools outside of the browser",
5 "license": "MIT",
6 "repository": {
@@ -25,7 +25,7 @@
25 "electron": "^5.0.0",
26 "ip": "^1.1.4",
27 "minimist": "^1.2.0",
28 - "react-devtools-core": "4.0.0-alpha.6",
28 + "react-devtools-core": "4.0.0-alpha.7",
29 "update-notifier": "^2.1.0"
30 }
31 }
shells/browser/shared/src/main.js
-2
@@ -63,7 +63,6 @@ function createPanelIfReactLoaded() {
63
64 let componentsPortalContainer = null;
65 let profilerPortalContainer = null;
66 - let settingsPortalContainer = null;
66
67 let cloneStyleTags = null;
68 let mostRecentOverrideTab = null;
@@ -142,7 +141,6 @@ function createPanelIfReactLoaded() {
141 componentsPortalContainer,
142 overrideTab,
143 profilerPortalContainer,
145 - settingsPortalContainer,
144 showTabBar: false,
145 showWelcomeToTheNewDevToolsDialog: true,
146 store,
shells/dev/src/backend.js deleted
-37
@@ -1,37 +0,0 @@
1 -/** @flow */
2 -
3 -import Agent from 'src/backend/agent';
4 -import Bridge from 'src/bridge';
5 -import { initBackend } from 'src/backend';
6 -import setupNativeStyleEditor from 'src/backend/NativeStyleEditor/setupNativeStyleEditor';
7 -
8 -const bridge = new Bridge({
9 - listen(fn) {
10 - const listener = event => {
11 - fn(event.data);
12 - };
13 - window.addEventListener('message', listener);
14 - return () => {
15 - window.removeEventListener('message', listener);
16 - };
17 - },
18 - send(event: string, payload: any, transferable?: Array<any>) {
19 - window.parent.postMessage({ event, payload }, '*', transferable);
20 - },
21 -});
22 -
23 -const agent = new Agent(bridge);
24 -
25 -const hook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
26 -
27 -initBackend(hook, agent, window.parent);
28 -
29 -// Setup React Native style editor if a renderer like react-native-web has injected it.
30 -if (!!hook.resolveRNStyle) {
31 - setupNativeStyleEditor(
32 - bridge,
33 - agent,
34 - hook.resolveRNStyle,
35 - hook.nativeStyleEditorValidAttributes
36 - );
37 -}
shells/dev/src/devtools.js
+13 -41
@@ -3,24 +3,21 @@
3 import { createElement } from 'react';
4 // $FlowFixMe Flow does not yet know about createRoot()
5 import { unstable_createRoot as createRoot } from 'react-dom';
6 -import Bridge from 'src/bridge';
7 -import { installHook } from 'src/hook';
6 +import {
7 + activate as activateBackend,
8 + initialize as initializeBackend,
9 +} from 'react-devtools-inline/backend';
10 +import { initialize as initializeFrontend } from 'react-devtools-inline/frontend';
11 import { initDevTools } from 'src/devtools';
9 -import Store from 'src/devtools/store';
10 -import DevTools from 'src/devtools/views/DevTools';
11 -import { getSavedComponentFilters, getAppendComponentStack } from 'src/utils';
12
13 const iframe = ((document.getElementById('target'): any): HTMLIFrameElement);
14
15 const { contentDocument, contentWindow } = iframe;
16
17 -// The renderer interface can't read saved component filters directly,
18 -// because they are stored in localStorage within the context of the extension.
19 -// Instead it relies on the extension to pass filters through.
20 -contentWindow.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = getSavedComponentFilters();
21 -contentWindow.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = getAppendComponentStack();
17 +// Helps with positioning Overlay UI.
18 +contentWindow.__REACT_DEVTOOLS_TARGET_WINDOW__ = window;
19
23 -installHook(contentWindow);
20 +initializeBackend(contentWindow);
21
22 const container = ((document.getElementById('devtools'): any): HTMLElement);
23
@@ -48,46 +45,21 @@ mountButton.addEventListener('click', function() {
45 inject('dist/app.js', () => {
46 initDevTools({
47 connect(cb) {
51 - const bridge = new Bridge({
52 - listen(fn) {
53 - const listener = ({ data }) => {
54 - fn(data);
55 - };
56 - // Preserve the reference to the window we subscribe to, so we can unsubscribe from it when required.
57 - const contentWindowParent = contentWindow.parent;
58 - contentWindowParent.addEventListener('message', listener);
59 - return () => {
60 - contentWindowParent.removeEventListener('message', listener);
61 - };
62 - },
63 - send(event: string, payload: any, transferable?: Array<any>) {
64 - contentWindow.postMessage({ event, payload }, '*', transferable);
65 - },
66 - });
48 + const DevTools = initializeFrontend(contentWindow);
49
68 - cb(bridge);
69 -
70 - const store = new Store(bridge);
50 + // Activate the backend only once the DevTools frontend Store has been initialized.
51 + // Otherwise the Store may miss important initial tree op codes.
52 + activateBackend(contentWindow);
53
54 const root = createRoot(container);
73 - const batch = root.createBatch();
74 - batch.render(
55 + root.render(
56 createElement(DevTools, {
76 - bridge,
57 browserTheme: 'light',
58 showTabBar: true,
59 showWelcomeToTheNewDevToolsDialog: true,
80 - store,
60 warnIfLegacyBackendDetected: true,
61 })
62 );
84 - batch.then(() => {
85 - batch.commit();
86 -
87 - // Initialize the backend only once the DevTools frontend Store has been initialized.
88 - // Otherwise the Store may miss important initial tree op codes.
89 - inject('dist/backend.js');
90 - });
63 },
64
65 onReload(reloadFn) {
shells/dev/webpack.config.js
+8 -3
@@ -16,6 +16,8 @@ if (!TARGET) {
16
17 const __DEV__ = NODE_ENV === 'development';
18
19 +const root = resolve(__dirname, '../..');
20 +
21 const GITHUB_URL = getGitHubURL();
22 const DEVTOOLS_VERSION = getVersionString();
23
@@ -24,12 +26,15 @@ const config = {
26 devtool: false,
27 entry: {
28 app: './app/index.js',
27 - backend: './src/backend.js',
29 devtools: './src/devtools.js',
30 },
31 resolve: {
32 alias: {
32 - src: resolve(__dirname, '../../src'),
33 + 'react-devtools-inline': resolve(
34 + root,
35 + 'packages/react-devtools-inline/src/'
36 + ),
37 + src: resolve(root, 'src'),
38 },
39 },
40 plugins: [
@@ -45,7 +50,7 @@ const config = {
50 test: /\.js$/,
51 loader: 'babel-loader',
52 options: {
48 - configFile: require.resolve('../../babel.config.js'),
53 + configFile: resolve(root, 'babel.config.js'),
54 },
55 },
56 {
src/backend/views/Highlighter/Overlay.js
+2 -11
@@ -153,20 +153,11 @@ export default class Overlay {
153
154 constructor() {
155 // Find the root window, because overlays are positioned relative to it.
156 - let currentWindow = window;
157 - while (currentWindow !== currentWindow.parent) {
158 - currentWindow = currentWindow.parent;
159 - }
156 + let currentWindow = window.__REACT_DEVTOOLS_TARGET_WINDOW__ || window;
157 this.window = currentWindow;
158
159 // When opened in shells/dev, the tooltip should be bound by the app iframe, not by the topmost window.
163 - let tipBoundsWindow = window;
164 - while (
165 - tipBoundsWindow !== tipBoundsWindow.parent &&
166 - !tipBoundsWindow.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')
167 - ) {
168 - tipBoundsWindow = tipBoundsWindow.parent;
169 - }
160 + let tipBoundsWindow = window.__REACT_DEVTOOLS_TARGET_WINDOW__ || window;
161 this.tipBoundsWindow = tipBoundsWindow;
162
163 const doc = currentWindow.document;
src/devtools/store.js
+1 -1
@@ -114,7 +114,7 @@ export default class Store extends EventEmitter<{|
114
115 // These options may be initially set by a confiugraiton option when constructing the Store.
116 // In the case of "supportsProfiling", the option may be updated based on the injected renderers.
117 - _supportsNativeInspection: boolean = false;
117 + _supportsNativeInspection: boolean = true;
118 _supportsProfiling: boolean = false;
119 _supportsReloadAndProfile: boolean = false;
120
src/devtools/views/DevTools.js
-3
@@ -59,7 +59,6 @@ export type Props = {|
59 // but individual tabs (e.g. Components, Profiling) can be rendered into portals within their browser panels.
60 componentsPortalContainer?: Element,
61 profilerPortalContainer?: Element,
62 - settingsPortalContainer?: Element,
62 |};
63
64 const componentsTab = {
@@ -85,7 +84,6 @@ export default function DevTools({
84 componentsPortalContainer,
85 overrideTab,
86 profilerPortalContainer,
88 - settingsPortalContainer,
87 showTabBar = false,
88 showWelcomeToTheNewDevToolsDialog = false,
89 store,
@@ -113,7 +111,6 @@ export default function DevTools({
111 browserTheme={browserTheme}
112 componentsPortalContainer={componentsPortalContainer}
113 profilerPortalContainer={profilerPortalContainer}
116 - settingsPortalContainer={settingsPortalContainer}
114 >
115 <ViewElementSourceContext.Provider value={viewElementSource}>
116 <TreeContextController>
src/devtools/views/Settings/SettingsContext.js
+1 -13
@@ -41,7 +41,6 @@ type Props = {|
41 children: React$Node,
42 componentsPortalContainer?: Element,
43 profilerPortalContainer?: Element,
44 - settingsPortalContainer?: Element,
44 |};
45
46 function SettingsContextController({
@@ -49,7 +48,6 @@ function SettingsContextController({
48 children,
49 componentsPortalContainer,
50 profilerPortalContainer,
52 - settingsPortalContainer,
51 }: Props) {
52 const bridge = useContext(BridgeContext);
53
@@ -82,18 +80,8 @@ function SettingsContextController({
80 .documentElement: any): HTMLElement)
81 );
82 }
85 - if (settingsPortalContainer != null) {
86 - array.push(
87 - ((settingsPortalContainer.ownerDocument
88 - .documentElement: any): HTMLElement)
89 - );
90 - }
83 return array;
92 - }, [
93 - componentsPortalContainer,
94 - profilerPortalContainer,
95 - settingsPortalContainer,
96 - ]);
84 + }, [componentsPortalContainer, profilerPortalContainer]);
85
86 const computedStyle = getComputedStyle((document.body: any));
87 const comfortableLineHeight = parseInt(