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

Ensure sync-xhr is allowed before reload and profile (#20879)

Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>

Chris Dobson committed Mar 11, 2021 at 15:31 UTC bd245c1bab1a1f965cb51f5d01406a2770244930
4 files changed +58 -9
packages/react-devtools-shared/src/backend/agent.js
+2
@@ -38,6 +38,7 @@ import type {
38 RendererInterface,
39 } from './types';
40 import type {ComponentFilter} from '../types';
41 +import {isSynchronousXHRSupported} from './utils';
42
43 const debug = (methodName, ...args) => {
44 if (__DEBUG__) {
@@ -221,6 +222,7 @@ export default class Agent extends EventEmitter<{|
222 isBackendStorageAPISupported = true;
223 } catch (error) {}
224 bridge.send('isBackendStorageAPISupported', isBackendStorageAPISupported);
225 + bridge.send('isSynchronousXHRSupported', isSynchronousXHRSupported());
226
227 setupHighlighter(bridge, this);
228 setupTraceUpdates(this);
packages/react-devtools-shared/src/backend/utils.js
+8
@@ -183,3 +183,11 @@ export function format(
183
184 return '' + formatted;
185 }
186 +
187 +export function isSynchronousXHRSupported(): boolean {
188 + return !!(
189 + window.document &&
190 + window.document.featurePolicy &&
191 + window.document.featurePolicy.allowsFeature('sync-xhr')
192 + );
193 +}
packages/react-devtools-shared/src/bridge.js
+1
@@ -122,6 +122,7 @@ export type BackendEvents = {|
122 extensionBackendInitialized: [],
123 inspectedElement: [InspectedElementPayload],
124 isBackendStorageAPISupported: [boolean],
125 + isSynchronousXHRSupported: [boolean],
126 operations: [Array<number>],
127 ownersList: [OwnersList],
128 overrideComponentFilters: [Array<ComponentFilter>],
packages/react-devtools-shared/src/devtools/store.js
+47 -9
@@ -111,6 +111,12 @@ export default class Store extends EventEmitter<{|
111 // If not, features like reload-and-profile will not work correctly and must be disabled.
112 _isBackendStorageAPISupported: boolean = false;
113
114 + // Can DevTools use sync XHR requests?
115 + // If not, features like reload-and-profile will not work correctly and must be disabled.
116 + // This current limitation applies only to web extension builds
117 + // and will need to be reconsidered in the future if we add support for reload to React Native.
118 + _isSynchronousXHRSupported: boolean = false;
119 +
120 _nativeStyleEditorValidAttributes: $ReadOnlyArray<string> | null = null;
121
122 // Map of element (id) to the set of elements (ids) it owns.
@@ -195,12 +201,16 @@ export default class Store extends EventEmitter<{|
201 bridge.addListener('shutdown', this.onBridgeShutdown);
202 bridge.addListener(
203 'isBackendStorageAPISupported',
198 - this.onBridgeStorageSupported,
204 + this.onBackendStorageAPISupported,
205 );
206 bridge.addListener(
207 'isNativeStyleEditorSupported',
208 this.onBridgeNativeStyleEditorSupported,
209 );
210 + bridge.addListener(
211 + 'isSynchronousXHRSupported',
212 + this.onBridgeSynchronousXHRSupported,
213 + );
214 bridge.addListener(
215 'unsupportedRendererVersion',
216 this.onBridgeUnsupportedRendererVersion,
@@ -359,11 +369,16 @@ export default class Store extends EventEmitter<{|
369 get supportsProfiling(): boolean {
370 return this._supportsProfiling;
371 }
372 +
373 get supportsReloadAndProfile(): boolean {
374 // Does the DevTools shell support reloading and eagerly injecting the renderer interface?
364 - // And if so, can the backend use the localStorage API?
365 - // Both of these are required for the reload-and-profile feature to work.
366 - return this._supportsReloadAndProfile && this._isBackendStorageAPISupported;
375 + // And if so, can the backend use the localStorage API and sync XHR?
376 + // All of these are currently required for the reload-and-profile feature to work.
377 + return (
378 + this._supportsReloadAndProfile &&
379 + this._isBackendStorageAPISupported &&
380 + this._isSynchronousXHRSupported
381 + );
382 }
383
384 get supportsTraceUpdates(): boolean {
@@ -1130,20 +1145,43 @@ export default class Store extends EventEmitter<{|
1145 debug('onBridgeShutdown', 'unsubscribing from Bridge');
1146 }
1147
1133 - this._bridge.removeListener('operations', this.onBridgeOperations);
1134 - this._bridge.removeListener('shutdown', this.onBridgeShutdown);
1135 - this._bridge.removeListener(
1148 + const bridge = this._bridge;
1149 + bridge.removeListener('operations', this.onBridgeOperations);
1150 + bridge.removeListener(
1151 + 'overrideComponentFilters',
1152 + this.onBridgeOverrideComponentFilters,
1153 + );
1154 + bridge.removeListener('shutdown', this.onBridgeShutdown);
1155 + bridge.removeListener(
1156 'isBackendStorageAPISupported',
1137 - this.onBridgeStorageSupported,
1157 + this.onBackendStorageAPISupported,
1158 + );
1159 + bridge.removeListener(
1160 + 'isNativeStyleEditorSupported',
1161 + this.onBridgeNativeStyleEditorSupported,
1162 + );
1163 + bridge.removeListener(
1164 + 'isSynchronousXHRSupported',
1165 + this.onBridgeSynchronousXHRSupported,
1166 + );
1167 + bridge.removeListener(
1168 + 'unsupportedRendererVersion',
1169 + this.onBridgeUnsupportedRendererVersion,
1170 );
1171 };
1172
1141 - onBridgeStorageSupported = (isBackendStorageAPISupported: boolean) => {
1173 + onBackendStorageAPISupported = (isBackendStorageAPISupported: boolean) => {
1174 this._isBackendStorageAPISupported = isBackendStorageAPISupported;
1175
1176 this.emit('supportsReloadAndProfile');
1177 };
1178
1179 + onBridgeSynchronousXHRSupported = (isSynchronousXHRSupported: boolean) => {
1180 + this._isSynchronousXHRSupported = isSynchronousXHRSupported;
1181 +
1182 + this.emit('supportsReloadAndProfile');
1183 + };
1184 +
1185 onBridgeUnsupportedRendererVersion = () => {
1186 this._unsupportedRendererVersionDetected = true;
1187