22
} from './cachedSettings';
23
24
import type {BackendBridge} from 'react-devtools-shared/src/bridge';
25
-import type {ComponentFilter} from 'react-devtools-shared/src/frontend/types';
25
+import type {
26
+ ComponentFilter,
27
+ Wall,
28
+} from 'react-devtools-shared/src/frontend/types';
29
import type {DevToolsHook} from 'react-devtools-shared/src/backend/types';
30
import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
31
313
});
314
}
315
}
316
+
317
+type ConnectWithCustomMessagingOptions = {
318
+ onSubscribe: (cb: Function) => void,
319
+ onUnsubscribe: (cb: Function) => void,
320
+ onMessage: (event: string, payload: any) => void,
321
+ settingsManager: ?DevToolsSettingsManager,
322
+ nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,
323
+ resolveRNStyle?: ResolveNativeStyle,
324
+};
325
+
326
+export function connectWithCustomMessagingProtocol({
327
+ onSubscribe,
328
+ onUnsubscribe,
329
+ onMessage,
330
+ settingsManager,
331
+ nativeStyleEditorValidAttributes,
332
+ resolveRNStyle,
333
+}: ConnectWithCustomMessagingOptions): Function {
334
+ if (hook == null) {
335
+ // DevTools didn't get injected into this page (maybe b'c of the contentType).
336
+ return;
337
+ }
338
+
339
+ if (settingsManager != null) {
340
+ try {
341
+ initializeUsingCachedSettings(settingsManager);
342
+ } catch (e) {
343
+ // If we call a method on devToolsSettingsManager that throws, or if
344
+ // is invalid data read out, don't throw and don't interrupt initialization
345
+ console.error(e);
346
+ }
347
+ }
348
+
349
+ const wall: Wall = {
350
+ listen(fn: Function) {
351
+ onSubscribe(fn);
352
+
353
+ return () => {
354
+ onUnsubscribe(fn);
355
+ };
356
+ },
357
+ send(event: string, payload: any) {
358
+ onMessage(event, payload);
359
+ },
360
+ };
361
+
362
+ const bridge: BackendBridge = new Bridge(wall);
363
+
364
+ bridge.addListener(
365
+ 'updateComponentFilters',
366
+ (componentFilters: Array<ComponentFilter>) => {
367
+ // Save filter changes in memory, in case DevTools is reloaded.
368
+ // In that case, the renderer will already be using the updated values.
369
+ // We'll lose these in between backend reloads but that can't be helped.
370
+ savedComponentFilters = componentFilters;
371
+ },
372
+ );
373
+
374
+ if (settingsManager != null) {
375
+ bridge.addListener('updateConsolePatchSettings', consolePatchSettings =>
376
+ cacheConsolePatchSettings(settingsManager, consolePatchSettings),
377
+ );
378
+ }
379
+
380
+ if (window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ == null) {
381
+ bridge.send('overrideComponentFilters', savedComponentFilters);
382
+ }
383
+
384
+ const agent = new Agent(bridge);
385
+ agent.addListener('shutdown', () => {
386
+ // If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,
387
+ // and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.
388
+ hook.emit('shutdown');
389
+ });
390
+
391
+ const unsubscribeBackend = initBackend(hook, agent, window);
392
+
393
+ const nativeStyleResolver: ResolveNativeStyle | void =
394
+ resolveRNStyle || hook.resolveRNStyle;
395
+
396
+ if (nativeStyleResolver != null) {
397
+ const validAttributes =
398
+ nativeStyleEditorValidAttributes ||
399
+ hook.nativeStyleEditorValidAttributes ||
400
+ null;
401
+
402
+ setupNativeStyleEditor(bridge, agent, nativeStyleResolver, validAttributes);
403
+ }
404
+
405
+ return unsubscribeBackend;
406
+}