mirror of
https://github.com/facebook/react.git
synced 2026-02-26 18:58:05 +00:00
I need to start clarifying where things are really actually Fibers and where they're not since I'm adding Server Components as a separate type of component instance which is not backed by a Fiber. Nothing in the front end should really know anything about what kind of renderer implementation we're inspecting and indeed it's already not always a "Fiber" in the legacy renderer. We typically refer to this as a "Component Instance" but the front end currently refers to it as an Element as it historically grew from the browser DevTools Elements tab. I also moved the renderer.js implementation into the `backend/fiber` folder. These are at the same level as `backend/legacy`. This clarifies that anything outside of this folder ideally shouldn't refer to a "Fiber". console.js and profilingHooks.js unfortunately use Fibers a lot which needs further refactoring. The profiler frontend also uses the term alot.
137 lines
3.9 KiB
JavaScript
137 lines
3.9 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 Agent from './agent';
|
|
|
|
import {attach} from './fiber/renderer';
|
|
import {attach as attachLegacy} from './legacy/renderer';
|
|
import {hasAssignedBackend} from './utils';
|
|
|
|
import type {DevToolsHook, ReactRenderer, RendererInterface} from './types';
|
|
|
|
// this is the backend that is compatible with all older React versions
|
|
function isMatchingRender(version: string): boolean {
|
|
return !hasAssignedBackend(version);
|
|
}
|
|
|
|
export type InitBackend = typeof initBackend;
|
|
|
|
export function initBackend(
|
|
hook: DevToolsHook,
|
|
agent: Agent,
|
|
global: Object,
|
|
): () => void {
|
|
if (hook == null) {
|
|
// DevTools didn't get injected into this page (maybe b'c of the contentType).
|
|
return () => {};
|
|
}
|
|
|
|
const subs = [
|
|
hook.sub(
|
|
'renderer-attached',
|
|
({
|
|
id,
|
|
renderer,
|
|
rendererInterface,
|
|
}: {
|
|
id: number,
|
|
renderer: ReactRenderer,
|
|
rendererInterface: RendererInterface,
|
|
...
|
|
}) => {
|
|
agent.setRendererInterface(id, rendererInterface);
|
|
|
|
// Now that the Store and the renderer interface are connected,
|
|
// it's time to flush the pending operation codes to the frontend.
|
|
rendererInterface.flushInitialOperations();
|
|
},
|
|
),
|
|
|
|
hook.sub('unsupported-renderer-version', (id: number) => {
|
|
agent.onUnsupportedRenderer(id);
|
|
}),
|
|
|
|
hook.sub('fastRefreshScheduled', agent.onFastRefreshScheduled),
|
|
hook.sub('operations', agent.onHookOperations),
|
|
hook.sub('traceUpdates', agent.onTraceUpdates),
|
|
|
|
// TODO Add additional subscriptions required for profiling mode
|
|
];
|
|
|
|
const attachRenderer = (id: number, renderer: ReactRenderer) => {
|
|
// only attach if the renderer is compatible with the current version of the backend
|
|
if (!isMatchingRender(renderer.reconcilerVersion || renderer.version)) {
|
|
return;
|
|
}
|
|
let rendererInterface = hook.rendererInterfaces.get(id);
|
|
|
|
// Inject any not-yet-injected renderers (if we didn't reload-and-profile)
|
|
if (rendererInterface == null) {
|
|
if (typeof renderer.findFiberByHostInstance === 'function') {
|
|
// react-reconciler v16+
|
|
rendererInterface = attach(hook, id, renderer, global);
|
|
} else if (renderer.ComponentTree) {
|
|
// react-dom v15
|
|
rendererInterface = attachLegacy(hook, id, renderer, global);
|
|
} else {
|
|
// Older react-dom or other unsupported renderer version
|
|
}
|
|
|
|
if (rendererInterface != null) {
|
|
hook.rendererInterfaces.set(id, rendererInterface);
|
|
}
|
|
}
|
|
|
|
// Notify the DevTools frontend about new renderers.
|
|
// This includes any that were attached early (via __REACT_DEVTOOLS_ATTACH__).
|
|
if (rendererInterface != null) {
|
|
hook.emit('renderer-attached', {
|
|
id,
|
|
renderer,
|
|
rendererInterface,
|
|
});
|
|
} else {
|
|
hook.emit('unsupported-renderer-version', id);
|
|
}
|
|
};
|
|
|
|
// Connect renderers that have already injected themselves.
|
|
hook.renderers.forEach((renderer, id) => {
|
|
attachRenderer(id, renderer);
|
|
});
|
|
|
|
// Connect any new renderers that injected themselves.
|
|
subs.push(
|
|
hook.sub(
|
|
'renderer',
|
|
({id, renderer}: {id: number, renderer: ReactRenderer, ...}) => {
|
|
attachRenderer(id, renderer);
|
|
},
|
|
),
|
|
);
|
|
|
|
hook.emit('react-devtools', agent);
|
|
hook.reactDevtoolsAgent = agent;
|
|
const onAgentShutdown = () => {
|
|
subs.forEach(fn => fn());
|
|
hook.rendererInterfaces.forEach(rendererInterface => {
|
|
rendererInterface.cleanup();
|
|
});
|
|
hook.reactDevtoolsAgent = null;
|
|
};
|
|
agent.addListener('shutdown', onAgentShutdown);
|
|
subs.push(() => {
|
|
agent.removeListener('shutdown', onAgentShutdown);
|
|
});
|
|
|
|
return () => {
|
|
subs.forEach(fn => fn());
|
|
};
|
|
}
|