mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
Builds on #37048 by replacing `any`-based Bridge and Wall boundaries with typed `mixed` values and explicit runtime validation. Invalid messages and post-shutdown operations now throw, while shutdown reliably flushes queued messages even if cleanup fails. Strengthens the DevTools Bridge and Wall contracts: - Models event dictionaries as event-to-payload maps, using `void` for events without payloads. - Types `send(event, payload?)` directly, eliminating runtime payload-arity handling. - Replaces broad `any` transport types with `mixed` and boundary validation. - Throws on invalid lifecycle usage instead of warning or silently returning. - Ensures shutdown flushes queued messages even when Wall cleanup fails. - Updates Wall implementations and adds Bridge lifecycle coverage.
103 lines
2.8 KiB
JavaScript
103 lines
2.8 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import * as React from 'react';
|
|
import {createRoot} from 'react-dom/client';
|
|
import Bridge from 'react-devtools-shared/src/bridge';
|
|
import Store from 'react-devtools-shared/src/devtools/store';
|
|
import DevTools from 'react-devtools-shared/src/devtools/views/DevTools';
|
|
|
|
import type {
|
|
BrowserTheme,
|
|
Wall,
|
|
} from 'react-devtools-shared/src/frontend/types';
|
|
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
|
|
import type {
|
|
CanViewElementSource,
|
|
TabID,
|
|
ViewAttributeSource,
|
|
ViewElementSource,
|
|
} from 'react-devtools-shared/src/devtools/views/DevTools';
|
|
import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext';
|
|
import type {Config} from 'react-devtools-shared/src/devtools/store';
|
|
|
|
export function createBridge(wall?: Wall): FrontendBridge {
|
|
if (wall != null) {
|
|
return new Bridge(wall);
|
|
}
|
|
|
|
return new Bridge({listen: () => () => {}, send: () => {}});
|
|
}
|
|
|
|
export function createStore(bridge: FrontendBridge, config?: Config): Store {
|
|
return new Store(bridge, {
|
|
checkBridgeProtocolCompatibility: true,
|
|
supportsTraceUpdates: true,
|
|
supportsClickToInspect: true,
|
|
...config,
|
|
});
|
|
}
|
|
|
|
type InitializationOptions = {
|
|
bridge: FrontendBridge,
|
|
store: Store,
|
|
theme?: BrowserTheme,
|
|
viewAttributeSourceFunction?: ViewAttributeSource,
|
|
viewElementSourceFunction?: ViewElementSource,
|
|
canViewElementSourceFunction?: CanViewElementSource,
|
|
fetchFileWithCaching?: FetchFileWithCaching,
|
|
};
|
|
|
|
function initializeTab(
|
|
tab: TabID,
|
|
contentWindow: Element | Document,
|
|
options: InitializationOptions,
|
|
) {
|
|
const {
|
|
bridge,
|
|
store,
|
|
theme = 'light',
|
|
viewAttributeSourceFunction,
|
|
viewElementSourceFunction,
|
|
canViewElementSourceFunction,
|
|
fetchFileWithCaching,
|
|
} = options;
|
|
const root = createRoot(contentWindow);
|
|
|
|
root.render(
|
|
<DevTools
|
|
bridge={bridge}
|
|
browserTheme={theme}
|
|
store={store}
|
|
showTabBar={false}
|
|
overrideTab={tab}
|
|
warnIfLegacyBackendDetected={true}
|
|
enabledInspectedElementContextMenu={true}
|
|
viewAttributeSourceFunction={viewAttributeSourceFunction}
|
|
viewElementSourceFunction={viewElementSourceFunction}
|
|
canViewElementSourceFunction={canViewElementSourceFunction}
|
|
fetchFileWithCaching={fetchFileWithCaching}
|
|
/>,
|
|
);
|
|
}
|
|
|
|
export function initializeComponents(
|
|
contentWindow: Element | Document,
|
|
options: InitializationOptions,
|
|
): void {
|
|
initializeTab('components', contentWindow, options);
|
|
}
|
|
|
|
export function initializeProfiler(
|
|
contentWindow: Element | Document,
|
|
options: InitializationOptions,
|
|
): void {
|
|
initializeTab('profiler', contentWindow, options);
|
|
}
|