Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DO NOT MERGE] Replay React Devtools fork preview #15

Draft
wants to merge 2 commits into
base: react-main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions packages/react-devtools-extensions/src/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,56 @@ import type {DevToolsHook} from 'react-devtools-shared/src/backend/types';
import Agent from 'react-devtools-shared/src/backend/agent';
import Bridge from 'react-devtools-shared/src/bridge';
import {initBackend} from 'react-devtools-shared/src/backend';
import setupNativeStyleEditor from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';

import {COMPACT_VERSION_NAME} from './utils';

window.logMessage('RDT initializing');
setup(window.__REACT_DEVTOOLS_GLOBAL_HOOK__);
window.logMessage('RDT setup complete');

function setup(hook: ?DevToolsHook) {
if (hook == null) {
return;
}

const bridge = new Bridge<any, any>({
listen(fn) {
const listener = (event: any) => {
if (
event.source !== window ||
!event.data ||
event.data.source !== 'react-devtools-content-script' ||
!event.data.payload
) {
return;
}
fn(event.data.payload);
};
window.addEventListener('message', listener);
return () => {
window.removeEventListener('message', listener);
};
},
send(event: string, payload: any, transferable: any) {
window.postMessage(
{
source: 'react-devtools-bridge',
payload: {event, payload},
},
'*',
transferable,
);
},
});

const agent = new Agent(bridge);
initBackend(hook, agent, window);

hook.backends.set(COMPACT_VERSION_NAME, {
Agent,
Bridge,
initBackend,
setupNativeStyleEditor,
setupNativeStyleEditor: () => {},
});

hook.emit('devtools-backend-installed', COMPACT_VERSION_NAME);
Expand Down
28 changes: 26 additions & 2 deletions packages/react-devtools-extensions/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
/* global chrome */
// /* global chrome */

import type {BrowserTheme} from 'react-devtools-shared/src/devtools/views/DevTools';
// import type {BrowserTheme} from 'react-devtools-shared/src/devtools/views/DevTools';

// REPLAY Our RDT integration is only for Chrome currently
export const IS_EDGE = false; // navigator.userAgent.indexOf('Edg') >= 0;
export const IS_FIREFOX = false; // navigator.userAgent.indexOf('Firefox') >= 0;
export const IS_CHROME = true; //IS_EDGE === false && IS_FIREFOX === false;

export type BrowserName = 'Chrome' | 'Firefox' | 'Edge';

/*
export function getBrowserName(): BrowserName {
if (IS_EDGE) {
return 'Edge';
}
if (IS_FIREFOX) {
return 'Firefox';
}
if (IS_CHROME) {
return 'Chrome';
}
throw new Error(
'Expected browser name to be one of Chrome, Edge or Firefox.',
);
}

export function getBrowserTheme(): BrowserTheme {
if (__IS_CHROME__) {
Expand All @@ -20,6 +43,7 @@ export function getBrowserTheme(): BrowserTheme {
}
}
}
*/

export const COMPACT_VERSION_NAME = 'compact';
export const EXTENSION_CONTAINED_VERSIONS = [COMPACT_VERSION_NAME];
4 changes: 2 additions & 2 deletions packages/react-devtools-extensions/webpack.backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const featureFlagTarget = process.env.FEATURE_FLAG_TARGET || 'extension-oss';

module.exports = {
mode: __DEV__ ? 'development' : 'production',
devtool: false,
devtool: __DEV__ ? 'cheap-module-source-map' : 'source-map',
entry: {
backend: './src/backend.js',
},
Expand All @@ -56,7 +56,7 @@ module.exports = {
},
},
optimization: {
minimize: false,
minimize: true,
},
plugins: [
new Webpack.ProvidePlugin({
Expand Down
16 changes: 8 additions & 8 deletions packages/react-devtools-extensions/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ module.exports = {
mode: __DEV__ ? 'development' : 'production',
devtool: false,
entry: {
background: './src/background/index.js',
backendManager: './src/contentScripts/backendManager.js',
fileFetcher: './src/contentScripts/fileFetcher.js',
main: './src/main/index.js',
panel: './src/panel.js',
proxy: './src/contentScripts/proxy.js',
prepareInjection: './src/contentScripts/prepareInjection.js',
renderer: './src/contentScripts/renderer.js',
// background: './src/background/index.js',
// backendManager: './src/contentScripts/backendManager.js',
// fileFetcher: './src/contentScripts/fileFetcher.js',
// main: './src/main/index.js',
// panel: './src/panel.js',
// proxy: './src/contentScripts/proxy.js',
// prepareInjection: './src/contentScripts/prepareInjection.js',
// renderer: './src/contentScripts/renderer.js',
installHook: './src/contentScripts/installHook.js',
},
output: {
Expand Down
96 changes: 23 additions & 73 deletions packages/react-devtools-shared/src/backend/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,7 @@
*/

import EventEmitter from '../events';
import throttle from 'lodash.throttle';
import {
SESSION_STORAGE_LAST_SELECTION_KEY,
SESSION_STORAGE_RELOAD_AND_PROFILE_KEY,
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
__DEBUG__,
} from '../constants';
import {
sessionStorageGetItem,
sessionStorageRemoveItem,
sessionStorageSetItem,
} from 'react-devtools-shared/src/storage';
import setupHighlighter from './views/Highlighter';
import {
initialize as setupTraceUpdates,
toggleEnabled as setTraceUpdatesEnabled,
} from './views/TraceUpdates';
import {__DEBUG__} from '../constants';
import {patch as patchConsole} from './console';
import {currentBridgeProtocol} from 'react-devtools-shared/src/bridge';

Expand Down Expand Up @@ -165,26 +149,6 @@ export default class Agent extends EventEmitter<{
constructor(bridge: BackendBridge) {
super();

if (
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true'
) {
this._recordChangeDescriptions =
sessionStorageGetItem(
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
) === 'true';
this._isProfiling = true;

sessionStorageRemoveItem(SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY);
sessionStorageRemoveItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY);
}

const persistedSelectionString = sessionStorageGetItem(
SESSION_STORAGE_LAST_SELECTION_KEY,
);
if (persistedSelectionString != null) {
this._persistedSelection = JSON.parse(persistedSelectionString);
}

this._bridge = bridge;

bridge.addListener('clearErrorsAndWarnings', this.clearErrorsAndWarnings);
Expand All @@ -202,7 +166,6 @@ export default class Agent extends EventEmitter<{
bridge.addListener('overrideError', this.overrideError);
bridge.addListener('overrideSuspense', this.overrideSuspense);
bridge.addListener('overrideValueAtPath', this.overrideValueAtPath);
bridge.addListener('reloadAndProfile', this.reloadAndProfile);
bridge.addListener('renamePath', this.renamePath);
bridge.addListener('setTraceUpdatesEnabled', this.setTraceUpdatesEnabled);
bridge.addListener('startProfiling', this.startProfiling);
Expand Down Expand Up @@ -243,16 +206,30 @@ export default class Agent extends EventEmitter<{

// Notify the frontend if the backend supports the Storage API (e.g. localStorage).
// If not, features like reload-and-profile will not work correctly and must be disabled.
let isBackendStorageAPISupported = false;
try {
localStorage.getItem('test');
isBackendStorageAPISupported = true;
} catch (error) {}
const isBackendStorageAPISupported = false;

bridge.send('isBackendStorageAPISupported', isBackendStorageAPISupported);
bridge.send('isSynchronousXHRSupported', isSynchronousXHRSupported());

setupHighlighter(bridge, this);
setupTraceUpdates(this);
window.__RECORD_REPLAY_REACT_DEVTOOLS_SEND_MESSAGE__ = (
inEvent,
inData,
) => {
let rv;
this._bridge = ({
send(event, data) {
rv = {event, data};
},
}: any);
try {
this[inEvent](inData);
} catch (err) {
window.logMessage(
`Error executing bridge message '${inEvent}': ${err}, ${err.stack}`,
);
}
return rv;
};
}

get rendererInterfaces(): {[key: RendererID]: RendererInterface, ...} {
Expand Down Expand Up @@ -429,7 +406,6 @@ export default class Agent extends EventEmitter<{
this._persistedSelection = null;
this._persistedSelectionMatch = null;
renderer.setTrackedPath(null);
this._throttledPersistSelection(rendererID, id);
}

// TODO: If there was a way to change the selected DOM element
Expand Down Expand Up @@ -582,12 +558,6 @@ export default class Agent extends EventEmitter<{

reloadAndProfile: (recordChangeDescriptions: boolean) => void =
recordChangeDescriptions => {
sessionStorageSetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY, 'true');
sessionStorageSetItem(
SESSION_STORAGE_RECORD_CHANGE_DESCRIPTIONS_KEY,
recordChangeDescriptions ? 'true' : 'false',
);

// This code path should only be hit if the shell has explicitly told the Store that it supports profiling.
// In that case, the shell must also listen for this specific message to know when it needs to reload the app.
// The agent can't do this in a way that is renderer agnostic.
Expand Down Expand Up @@ -640,10 +610,9 @@ export default class Agent extends EventEmitter<{

setTraceUpdatesEnabled: (traceUpdatesEnabled: boolean) => void =
traceUpdatesEnabled => {
traceUpdatesEnabled = false;
this._traceUpdatesEnabled = traceUpdatesEnabled;

setTraceUpdatesEnabled(traceUpdatesEnabled);

for (const rendererID in this._rendererInterfaces) {
const renderer = ((this._rendererInterfaces[
(rendererID: any)
Expand Down Expand Up @@ -838,23 +807,4 @@ export default class Agent extends EventEmitter<{
onUnsupportedRenderer(rendererID: number) {
this._bridge.send('unsupportedRendererVersion', rendererID);
}

_throttledPersistSelection: any = throttle(
(rendererID: number, id: number) => {
// This is throttled, so both renderer and selected ID
// might not be available by the time we read them.
// This is why we need the defensive checks here.
const renderer = this._rendererInterfaces[rendererID];
const path = renderer != null ? renderer.getPathForElement(id) : null;
if (path !== null) {
sessionStorageSetItem(
SESSION_STORAGE_LAST_SELECTION_KEY,
JSON.stringify(({rendererID, path}: PersistedSelection)),
);
} else {
sessionStorageRemoveItem(SESSION_STORAGE_LAST_SELECTION_KEY);
}
},
1000,
);
}
6 changes: 5 additions & 1 deletion packages/react-devtools-shared/src/backend/console.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ export function registerRenderer(
// currentDispatcherRef gets injected for v16.8+ to support hooks inspection.
// getCurrentFiber gets injected for v16.9+.
if (currentDispatcherRef != null && typeof getCurrentFiber === 'function') {
const {ReactTypeOfWork} = getInternalReactConstants(version);
const {ReactTypeOfWork} = getInternalReactConstants(
version,
// REPLAY Our fork will never run this code anyway, make Flow happy
() => 0,
);

injectedRenderers.set(renderer, {
currentDispatcherRef,
Expand Down
5 changes: 3 additions & 2 deletions packages/react-devtools-shared/src/backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import Agent from './agent';

import {attach} from './renderer';
import {attach as attachLegacy} from './legacy/renderer';
import {hasAssignedBackend} from './utils';

import type {DevToolsHook, ReactRenderer, RendererInterface} from './types';
Expand Down Expand Up @@ -78,7 +77,9 @@ export function initBackend(
rendererInterface = attach(hook, id, renderer, global);
} else if (renderer.ComponentTree) {
// react-dom v15
rendererInterface = attachLegacy(hook, id, renderer, global);
// REPLAY We do not support React 15 or earlier for our RDT integration.
// Don't let this connect or save operations.
// rendererInterface = attachLegacy(hook, id, renderer, global);
} else {
// Older react-dom or other unsupported renderer version
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,7 @@ export function attach(
getSerializedElementValueByPath,
deletePath,
flushInitialOperations,
flushPendingEvents,
getBestMatchForTrackedPath,
getDisplayNameForFiberID,
getFiberForNative,
Expand Down
Loading