mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
Scheduling Profiler: De-emphasize React internal frames (#22588)
This commit adds code to all React bundles to explicitly register the beginning and ending of the module. This is done by creating Error objects (which capture the file name, line number, and column number) and passing them explicitly to a DevTools hook (when present). Next, as the Scheduling Profiler logs metadata to the User Timing API, it prints these module ranges along with other metadata (like Lane values and profiler version number). Lastly, the Scheduling Profiler UI compares stack frames to these ranges when drawing the flame graph and dims or de-emphasizes frames that fall within an internal module. The net effect of this is that user code (and 3rd party code) stands out clearly in the flame graph while React internal modules are dimmed. Internal module ranges are completely optional. Older profiling samples, or ones recorded without the React DevTools extension installed, will simply not dim the internal frames.
This commit is contained in:
@@ -9,13 +9,15 @@
|
||||
|
||||
declare var chrome: any;
|
||||
|
||||
import {__DEBUG__} from 'react-devtools-shared/src/constants';
|
||||
import {
|
||||
INTERNAL_EXTENSION_ID,
|
||||
LOCAL_EXTENSION_ID,
|
||||
__DEBUG__,
|
||||
} from 'react-devtools-shared/src/constants';
|
||||
import {getBrowserName} from './utils';
|
||||
import {
|
||||
EXTENSION_INSTALL_CHECK,
|
||||
EXTENSION_INSTALLATION_TYPE,
|
||||
INTERNAL_EXTENSION_ID,
|
||||
LOCAL_EXTENSION_ID,
|
||||
} from './constants';
|
||||
|
||||
const IS_CHROME = getBrowserName() === 'Chrome';
|
||||
|
||||
+6
-4
@@ -7,6 +7,12 @@
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
import {
|
||||
CHROME_WEBSTORE_EXTENSION_ID,
|
||||
INTERNAL_EXTENSION_ID,
|
||||
LOCAL_EXTENSION_ID,
|
||||
} from 'react-devtools-shared/src/constants';
|
||||
|
||||
declare var chrome: any;
|
||||
|
||||
export const CURRENT_EXTENSION_ID = chrome.runtime.id;
|
||||
@@ -15,10 +21,6 @@ export const EXTENSION_INSTALL_CHECK = 'extension-install-check';
|
||||
export const SHOW_DUPLICATE_EXTENSION_WARNING =
|
||||
'show-duplicate-extension-warning';
|
||||
|
||||
export const CHROME_WEBSTORE_EXTENSION_ID = 'fmkadmapgofadopljbjfkapdkoienihi';
|
||||
export const INTERNAL_EXTENSION_ID = 'dnjnjgbfilfphmojnmhliehogmojhclc';
|
||||
export const LOCAL_EXTENSION_ID = 'ikiahnapldjmdmpkmfhjdjilojjhgcbf';
|
||||
|
||||
export const EXTENSION_INSTALLATION_TYPE:
|
||||
| 'public'
|
||||
| 'internal'
|
||||
|
||||
@@ -374,6 +374,7 @@ function AutoSizedCanvas({
|
||||
surface,
|
||||
defaultFrame,
|
||||
data.flamechart,
|
||||
data.internalModuleSourceToRanges,
|
||||
data.duration,
|
||||
);
|
||||
flamechartViewRef.current = flamechartView;
|
||||
|
||||
+34
-6
@@ -11,6 +11,7 @@ import type {
|
||||
Flamechart,
|
||||
FlamechartStackFrame,
|
||||
FlamechartStackLayer,
|
||||
InternalModuleSourceToRanges,
|
||||
} from '../types';
|
||||
import type {
|
||||
Interaction,
|
||||
@@ -30,6 +31,7 @@ import {
|
||||
rectIntersectsRect,
|
||||
verticallyStackedLayout,
|
||||
} from '../view-base';
|
||||
import {isInternalModule} from './utils/moduleFilters';
|
||||
import {
|
||||
durationToWidth,
|
||||
positioningScaleFactor,
|
||||
@@ -76,6 +78,8 @@ class FlamechartStackLayerView extends View {
|
||||
/** A set of `stackLayer`'s frames, for efficient lookup. */
|
||||
_stackFrameSet: Set<FlamechartStackFrame>;
|
||||
|
||||
_internalModuleSourceToRanges: InternalModuleSourceToRanges;
|
||||
|
||||
_intrinsicSize: Size;
|
||||
|
||||
_hoveredStackFrame: FlamechartStackFrame | null = null;
|
||||
@@ -85,11 +89,13 @@ class FlamechartStackLayerView extends View {
|
||||
surface: Surface,
|
||||
frame: Rect,
|
||||
stackLayer: FlamechartStackLayer,
|
||||
internalModuleSourceToRanges: InternalModuleSourceToRanges,
|
||||
duration: number,
|
||||
) {
|
||||
super(surface, frame);
|
||||
this._stackLayer = stackLayer;
|
||||
this._stackFrameSet = new Set(stackLayer);
|
||||
this._internalModuleSourceToRanges = internalModuleSourceToRanges;
|
||||
this._intrinsicSize = {
|
||||
width: duration,
|
||||
height: FLAMECHART_FRAME_HEIGHT,
|
||||
@@ -160,9 +166,19 @@ class FlamechartStackLayerView extends View {
|
||||
}
|
||||
|
||||
const showHoverHighlight = _hoveredStackFrame === _stackLayer[i];
|
||||
context.fillStyle = showHoverHighlight
|
||||
? hoverColorForStackFrame(stackFrame)
|
||||
: defaultColorForStackFrame(stackFrame);
|
||||
|
||||
let textFillStyle;
|
||||
if (isInternalModule(this._internalModuleSourceToRanges, stackFrame)) {
|
||||
context.fillStyle = showHoverHighlight
|
||||
? COLORS.INTERNAL_MODULE_FRAME_HOVER
|
||||
: COLORS.INTERNAL_MODULE_FRAME;
|
||||
textFillStyle = COLORS.INTERNAL_MODULE_FRAME_TEXT;
|
||||
} else {
|
||||
context.fillStyle = showHoverHighlight
|
||||
? hoverColorForStackFrame(stackFrame)
|
||||
: defaultColorForStackFrame(stackFrame);
|
||||
textFillStyle = COLORS.TEXT_COLOR;
|
||||
}
|
||||
|
||||
const drawableRect = intersectionOfRects(nodeRect, visibleArea);
|
||||
context.fillRect(
|
||||
@@ -172,7 +188,9 @@ class FlamechartStackLayerView extends View {
|
||||
drawableRect.size.height,
|
||||
);
|
||||
|
||||
drawText(name, context, nodeRect, drawableRect);
|
||||
drawText(name, context, nodeRect, drawableRect, {
|
||||
fillStyle: textFillStyle,
|
||||
});
|
||||
}
|
||||
|
||||
// Render bottom border.
|
||||
@@ -264,13 +282,22 @@ export class FlamechartView extends View {
|
||||
surface: Surface,
|
||||
frame: Rect,
|
||||
flamechart: Flamechart,
|
||||
internalModuleSourceToRanges: InternalModuleSourceToRanges,
|
||||
duration: number,
|
||||
) {
|
||||
super(surface, frame, layeredLayout);
|
||||
this.setDataAndUpdateSubviews(flamechart, duration);
|
||||
this.setDataAndUpdateSubviews(
|
||||
flamechart,
|
||||
internalModuleSourceToRanges,
|
||||
duration,
|
||||
);
|
||||
}
|
||||
|
||||
setDataAndUpdateSubviews(flamechart: Flamechart, duration: number) {
|
||||
setDataAndUpdateSubviews(
|
||||
flamechart: Flamechart,
|
||||
internalModuleSourceToRanges: InternalModuleSourceToRanges,
|
||||
duration: number,
|
||||
) {
|
||||
const {surface, frame, _onHover, _hoveredStackFrame} = this;
|
||||
|
||||
// Clear existing rows on data update
|
||||
@@ -285,6 +312,7 @@ export class FlamechartView extends View {
|
||||
surface,
|
||||
frame,
|
||||
stackLayer,
|
||||
internalModuleSourceToRanges,
|
||||
duration,
|
||||
);
|
||||
this._verticalStackView.addSubview(rowView);
|
||||
|
||||
@@ -45,6 +45,9 @@ export const MIN_INTERVAL_SIZE_PX = 70;
|
||||
// TODO Replace this with "export let" vars
|
||||
export let COLORS = {
|
||||
BACKGROUND: '',
|
||||
INTERNAL_MODULE_FRAME: '',
|
||||
INTERNAL_MODULE_FRAME_HOVER: '',
|
||||
INTERNAL_MODULE_FRAME_TEXT: '',
|
||||
NATIVE_EVENT: '',
|
||||
NATIVE_EVENT_HOVER: '',
|
||||
NETWORK_PRIMARY: '',
|
||||
@@ -107,6 +110,15 @@ export function updateColorsToMatchTheme(element: Element): boolean {
|
||||
|
||||
COLORS = {
|
||||
BACKGROUND: computedStyle.getPropertyValue('--color-background'),
|
||||
INTERNAL_MODULE_FRAME: computedStyle.getPropertyValue(
|
||||
'--color-scheduling-profiler-internal-module',
|
||||
),
|
||||
INTERNAL_MODULE_FRAME_HOVER: computedStyle.getPropertyValue(
|
||||
'--color-scheduling-profiler-internal-module-hover',
|
||||
),
|
||||
INTERNAL_MODULE_FRAME_TEXT: computedStyle.getPropertyValue(
|
||||
'--color-scheduling-profiler-internal-module-text',
|
||||
),
|
||||
NATIVE_EVENT: computedStyle.getPropertyValue(
|
||||
'--color-scheduling-profiler-native-event',
|
||||
),
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
export const outerErrorA = new Error();
|
||||
|
||||
export const moduleStartError = new Error();
|
||||
export const innerError = new Error();
|
||||
export const moduleStopError = new Error();
|
||||
|
||||
export const outerErrorB = new Error();
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
export const moduleAStartError = new Error();
|
||||
export const innerErrorA = new Error();
|
||||
export const moduleAStopError = new Error();
|
||||
|
||||
export const outerError = new Error();
|
||||
|
||||
export const moduleBStartError = new Error();
|
||||
export const innerErrorB = new Error();
|
||||
export const moduleBStopError = new Error();
|
||||
Vendored
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its 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 {isInternalModule} from '../moduleFilters';
|
||||
|
||||
describe('isInternalModule', () => {
|
||||
let map;
|
||||
|
||||
function createFlamechartStackFrame(scriptUrl, locationLine, locationColumn) {
|
||||
return {
|
||||
name: 'test',
|
||||
timestamp: 0,
|
||||
duration: 1,
|
||||
scriptUrl,
|
||||
locationLine,
|
||||
locationColumn,
|
||||
};
|
||||
}
|
||||
|
||||
function createStackFrame(fileName, lineNumber, columnNumber) {
|
||||
return {
|
||||
columnNumber: columnNumber,
|
||||
lineNumber: lineNumber,
|
||||
fileName: fileName,
|
||||
functionName: 'test',
|
||||
source: ` at test (${fileName}:${lineNumber}:${columnNumber})`,
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
map = new Map();
|
||||
map.set('foo', [
|
||||
[createStackFrame('foo', 10, 0), createStackFrame('foo', 15, 100)],
|
||||
]);
|
||||
map.set('bar', [
|
||||
[createStackFrame('bar', 10, 0), createStackFrame('bar', 15, 100)],
|
||||
[createStackFrame('bar', 20, 0), createStackFrame('bar', 25, 100)],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should properly identify stack frames within the provided module ranges', () => {
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('foo', 10, 0)),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('foo', 12, 35)),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('foo', 15, 100)),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('bar', 12, 0)),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('bar', 22, 125)),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should properly identify stack frames outside of the provided module ranges', () => {
|
||||
expect(isInternalModule(map, createFlamechartStackFrame('foo', 9, 0))).toBe(
|
||||
false,
|
||||
);
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('foo', 15, 101)),
|
||||
).toBe(false);
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('bar', 17, 0)),
|
||||
).toBe(false);
|
||||
expect(
|
||||
isInternalModule(map, createFlamechartStackFrame('baz', 12, 0)),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its 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 type {
|
||||
FlamechartStackFrame,
|
||||
InternalModuleSourceToRanges,
|
||||
} from '../../types';
|
||||
|
||||
import {
|
||||
CHROME_WEBSTORE_EXTENSION_ID,
|
||||
INTERNAL_EXTENSION_ID,
|
||||
LOCAL_EXTENSION_ID,
|
||||
} from 'react-devtools-shared/src/constants';
|
||||
|
||||
export function isInternalModule(
|
||||
internalModuleSourceToRanges: InternalModuleSourceToRanges,
|
||||
flamechartStackFrame: FlamechartStackFrame,
|
||||
): boolean {
|
||||
const {locationColumn, locationLine, scriptUrl} = flamechartStackFrame;
|
||||
|
||||
if (scriptUrl == null || locationColumn == null || locationLine == null) {
|
||||
// This could indicate a browser-internal API like performance.mark().
|
||||
return false;
|
||||
}
|
||||
|
||||
// Internal modules are only registered if DevTools was running when the profile was captured,
|
||||
// but DevTools should also hide its own frames to avoid over-emphasizing them.
|
||||
if (
|
||||
// Handle webpack-internal:// sources
|
||||
scriptUrl.includes('/react-devtools') ||
|
||||
scriptUrl.includes('/react_devtools') ||
|
||||
// Filter out known extension IDs
|
||||
scriptUrl.includes(CHROME_WEBSTORE_EXTENSION_ID) ||
|
||||
scriptUrl.includes(INTERNAL_EXTENSION_ID) ||
|
||||
scriptUrl.includes(LOCAL_EXTENSION_ID)
|
||||
// Unfortunately this won't get everything, like relatively loaded chunks or Web Worker files.
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Filter out React internal packages.
|
||||
const ranges = internalModuleSourceToRanges.get(scriptUrl);
|
||||
if (ranges != null) {
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const [startStackFrame, stopStackFrame] = ranges[i];
|
||||
|
||||
const isAfterStart =
|
||||
locationLine > startStackFrame.lineNumber ||
|
||||
(locationLine === startStackFrame.lineNumber &&
|
||||
locationColumn >= startStackFrame.columnNumber);
|
||||
const isBeforeStop =
|
||||
locationLine < stopStackFrame.lineNumber ||
|
||||
(locationLine === stopStackFrame.lineNumber &&
|
||||
locationColumn <= stopStackFrame.columnNumber);
|
||||
|
||||
if (isAfterStart && isBeforeStop) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
+4
@@ -282,6 +282,7 @@ describe('preprocessData', () => {
|
||||
"componentMeasures": Array [],
|
||||
"duration": 0.005,
|
||||
"flamechart": Array [],
|
||||
"internalModuleSourceToRanges": Map {},
|
||||
"laneToLabelMap": Map {
|
||||
0 => "Sync",
|
||||
1 => "InputContinuousHydration",
|
||||
@@ -449,6 +450,7 @@ describe('preprocessData', () => {
|
||||
"componentMeasures": Array [],
|
||||
"duration": 0.011,
|
||||
"flamechart": Array [],
|
||||
"internalModuleSourceToRanges": Map {},
|
||||
"laneToLabelMap": Map {
|
||||
0 => "Sync",
|
||||
1 => "InputContinuousHydration",
|
||||
@@ -636,6 +638,7 @@ describe('preprocessData', () => {
|
||||
"componentMeasures": Array [],
|
||||
"duration": 0.013,
|
||||
"flamechart": Array [],
|
||||
"internalModuleSourceToRanges": Map {},
|
||||
"laneToLabelMap": Map {
|
||||
0 => "Sync",
|
||||
1 => "InputContinuousHydration",
|
||||
@@ -914,6 +917,7 @@ describe('preprocessData', () => {
|
||||
],
|
||||
"duration": 0.031,
|
||||
"flamechart": Array [],
|
||||
"internalModuleSourceToRanges": Map {},
|
||||
"laneToLabelMap": Map {
|
||||
0 => "Sync",
|
||||
1 => "InputContinuousHydration",
|
||||
|
||||
+59
@@ -13,6 +13,7 @@ import {
|
||||
} from '@elg/speedscope';
|
||||
import type {TimelineEvent} from '@elg/speedscope';
|
||||
import type {
|
||||
ErrorStackFrame,
|
||||
BatchUID,
|
||||
Flamechart,
|
||||
Milliseconds,
|
||||
@@ -30,6 +31,7 @@ import type {
|
||||
import {REACT_TOTAL_NUM_LANES, SCHEDULING_PROFILER_VERSION} from '../constants';
|
||||
import InvalidProfileError from './InvalidProfileError';
|
||||
import {getBatchRange} from '../utils/getBatchRange';
|
||||
import ErrorStackParser from 'error-stack-parser';
|
||||
|
||||
type MeasureStackElement = {|
|
||||
type: ReactMeasureType,
|
||||
@@ -43,6 +45,8 @@ type ProcessorState = {|
|
||||
asyncProcessingPromises: Promise<any>[],
|
||||
batchUID: BatchUID,
|
||||
currentReactComponentMeasure: ReactComponentMeasure | null,
|
||||
internalModuleCurrentStackFrame: ErrorStackFrame | null,
|
||||
internalModuleStackStringSet: Set<string>,
|
||||
measureStack: MeasureStackElement[],
|
||||
nativeEventStack: NativeEvent[],
|
||||
nextRenderShouldGenerateNewBatchID: boolean,
|
||||
@@ -793,6 +797,49 @@ function processTimelineEvent(
|
||||
);
|
||||
} // eslint-disable-line brace-style
|
||||
|
||||
// Internal module ranges
|
||||
else if (name.startsWith('--react-internal-module-start-')) {
|
||||
const stackFrameStart = name.substr(30);
|
||||
|
||||
if (!state.internalModuleStackStringSet.has(stackFrameStart)) {
|
||||
state.internalModuleStackStringSet.add(stackFrameStart);
|
||||
|
||||
const parsedStackFrameStart = parseStackFrame(stackFrameStart);
|
||||
|
||||
state.internalModuleCurrentStackFrame = parsedStackFrameStart;
|
||||
}
|
||||
} else if (name.startsWith('--react-internal-module-stop-')) {
|
||||
const stackFrameStop = name.substr(19);
|
||||
|
||||
if (!state.internalModuleStackStringSet.has(stackFrameStop)) {
|
||||
state.internalModuleStackStringSet.add(stackFrameStop);
|
||||
|
||||
const parsedStackFrameStop = parseStackFrame(stackFrameStop);
|
||||
|
||||
if (
|
||||
parsedStackFrameStop !== null &&
|
||||
state.internalModuleCurrentStackFrame !== null
|
||||
) {
|
||||
const parsedStackFrameStart = state.internalModuleCurrentStackFrame;
|
||||
|
||||
state.internalModuleCurrentStackFrame = null;
|
||||
|
||||
const range = [parsedStackFrameStart, parsedStackFrameStop];
|
||||
const ranges = currentProfilerData.internalModuleSourceToRanges.get(
|
||||
parsedStackFrameStart.fileName,
|
||||
);
|
||||
if (ranges == null) {
|
||||
currentProfilerData.internalModuleSourceToRanges.set(
|
||||
parsedStackFrameStart.fileName,
|
||||
[range],
|
||||
);
|
||||
} else {
|
||||
ranges.push(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // eslint-disable-line brace-style
|
||||
|
||||
// Other user timing marks/measures
|
||||
else if (ph === 'R' || ph === 'n') {
|
||||
// User Timing mark
|
||||
@@ -855,6 +902,15 @@ function preprocessFlamechart(rawData: TimelineEvent[]): Flamechart {
|
||||
return flamechart;
|
||||
}
|
||||
|
||||
function parseStackFrame(stackFrame: string): ErrorStackFrame | null {
|
||||
const error = new Error();
|
||||
error.stack = stackFrame;
|
||||
|
||||
const frames = ErrorStackParser.parse(error);
|
||||
|
||||
return frames.length === 1 ? frames[0] : null;
|
||||
}
|
||||
|
||||
export default async function preprocessData(
|
||||
timeline: TimelineEvent[],
|
||||
): Promise<ReactProfilerData> {
|
||||
@@ -870,6 +926,7 @@ export default async function preprocessData(
|
||||
componentMeasures: [],
|
||||
duration: 0,
|
||||
flamechart,
|
||||
internalModuleSourceToRanges: new Map(),
|
||||
laneToLabelMap: new Map(),
|
||||
laneToReactMeasureMap,
|
||||
nativeEvents: [],
|
||||
@@ -913,6 +970,8 @@ export default async function preprocessData(
|
||||
asyncProcessingPromises: [],
|
||||
batchUID: 0,
|
||||
currentReactComponentMeasure: null,
|
||||
internalModuleCurrentStackFrame: null,
|
||||
internalModuleStackStringSet: new Set(),
|
||||
measureStack: [],
|
||||
nativeEventStack: [],
|
||||
nextRenderShouldGenerateNewBatchID: true,
|
||||
|
||||
@@ -17,6 +17,12 @@ export type Return<T> = Return_<*, T>;
|
||||
|
||||
// Project types
|
||||
|
||||
export type ErrorStackFrame = {
|
||||
fileName: string,
|
||||
lineNumber: number,
|
||||
columnNumber: number,
|
||||
};
|
||||
|
||||
export type Milliseconds = number;
|
||||
|
||||
export type ReactLane = number;
|
||||
@@ -169,11 +175,17 @@ export type ViewState = {|
|
||||
viewToMutableViewStateMap: Map<string, mixed>,
|
||||
|};
|
||||
|
||||
export type InternalModuleSourceToRanges = Map<
|
||||
string,
|
||||
Array<[ErrorStackFrame, ErrorStackFrame]>,
|
||||
>;
|
||||
|
||||
export type ReactProfilerData = {|
|
||||
batchUIDToMeasuresMap: Map<BatchUID, ReactMeasure[]>,
|
||||
componentMeasures: ReactComponentMeasure[],
|
||||
duration: number,
|
||||
flamechart: Flamechart,
|
||||
internalModuleSourceToRanges: InternalModuleSourceToRanges,
|
||||
laneToLabelMap: Map<ReactLane, string>,
|
||||
laneToReactMeasureMap: Map<ReactLane, ReactMeasure[]>,
|
||||
nativeEvents: NativeEvent[],
|
||||
|
||||
@@ -420,6 +420,11 @@ export type DevToolsHook = {
|
||||
didError?: boolean,
|
||||
) => void,
|
||||
|
||||
// Scheduling Profiler internal module filtering
|
||||
getInternalModuleRanges: () => Array<[string, string]>,
|
||||
registerInternalModuleStart: (moduleStartError: Error) => void,
|
||||
registerInternalModuleStop: (moduleStopError: Error) => void,
|
||||
|
||||
// Testing
|
||||
dangerous_setTargetConsoleForTesting?: (fakeConsole: Object) => void,
|
||||
...
|
||||
|
||||
+10
@@ -7,6 +7,10 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
export const CHROME_WEBSTORE_EXTENSION_ID = 'fmkadmapgofadopljbjfkapdkoienihi';
|
||||
export const INTERNAL_EXTENSION_ID = 'dnjnjgbfilfphmojnmhliehogmojhclc';
|
||||
export const LOCAL_EXTENSION_ID = 'ikiahnapldjmdmpkmfhjdjilojjhgcbf';
|
||||
|
||||
// Flip this flag to true to enable verbose console debug logging.
|
||||
export const __DEBUG__ = false;
|
||||
|
||||
@@ -147,6 +151,9 @@ export const THEME_STYLES: {[style: Theme | DisplayDensity]: any} = {
|
||||
'--color-resize-bar-active': '#dcdcdc',
|
||||
'--color-resize-bar-border': '#d1d1d1',
|
||||
'--color-resize-bar-dot': '#333333',
|
||||
'--color-scheduling-profiler-internal-module': '#d1d1d1',
|
||||
'--color-scheduling-profiler-internal-module-hover': '#c9c9c9',
|
||||
'--color-scheduling-profiler-internal-module-text': '#444',
|
||||
'--color-scheduling-profiler-native-event': '#ccc',
|
||||
'--color-scheduling-profiler-native-event-hover': '#aaa',
|
||||
'--color-scheduling-profiler-network-primary': '#fcf3dc',
|
||||
@@ -288,6 +295,9 @@ export const THEME_STYLES: {[style: Theme | DisplayDensity]: any} = {
|
||||
'--color-resize-bar-active': '#31363f',
|
||||
'--color-resize-bar-border': '#3d424a',
|
||||
'--color-resize-bar-dot': '#cfd1d5',
|
||||
'--color-scheduling-profiler-internal-module': '#303542',
|
||||
'--color-scheduling-profiler-internal-module-hover': '#363b4a',
|
||||
'--color-scheduling-profiler-internal-module-text': '#7f8899',
|
||||
'--color-scheduling-profiler-native-event': '#b2b2b2',
|
||||
'--color-scheduling-profiler-native-event-hover': '#949494',
|
||||
'--color-scheduling-profiler-network-primary': '#fcf3dc',
|
||||
|
||||
+41
@@ -490,6 +490,40 @@ export function installHook(target: any): DevToolsHook | null {
|
||||
}
|
||||
}
|
||||
|
||||
type StackFrameString = string;
|
||||
|
||||
const openModuleRangesStack: Array<StackFrameString> = [];
|
||||
const moduleRanges: Array<[StackFrameString, StackFrameString]> = [];
|
||||
|
||||
function getTopStackFrameString(error: Error): StackFrameString | null {
|
||||
const frames = error.stack.split('\n');
|
||||
const frame = frames.length > 1 ? frames[1] : null;
|
||||
return frame;
|
||||
}
|
||||
|
||||
function getInternalModuleRanges(): Array<
|
||||
[StackFrameString, StackFrameString],
|
||||
> {
|
||||
return moduleRanges;
|
||||
}
|
||||
|
||||
function registerInternalModuleStart(error: Error) {
|
||||
const startStackFrame = getTopStackFrameString(error);
|
||||
if (startStackFrame !== null) {
|
||||
openModuleRangesStack.push(startStackFrame);
|
||||
}
|
||||
}
|
||||
|
||||
function registerInternalModuleStop(error: Error) {
|
||||
if (openModuleRangesStack.length > 0) {
|
||||
const startStackFrame = openModuleRangesStack.pop();
|
||||
const stopStackFrame = getTopStackFrameString(error);
|
||||
if (stopStackFrame !== null) {
|
||||
moduleRanges.push([startStackFrame, stopStackFrame]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: More meaningful names for "rendererInterfaces" and "renderers".
|
||||
const fiberRoots = {};
|
||||
const rendererInterfaces = new Map();
|
||||
@@ -520,6 +554,13 @@ export function installHook(target: any): DevToolsHook | null {
|
||||
onCommitFiberRoot,
|
||||
onPostCommitFiberRoot,
|
||||
setStrictMode,
|
||||
|
||||
// Schedule Profiler runtime helpers.
|
||||
// These internal React modules to report their own boundaries
|
||||
// which in turn enables the profiler to dim or filter internal frames.
|
||||
getInternalModuleRanges,
|
||||
registerInternalModuleStart,
|
||||
registerInternalModuleStop,
|
||||
};
|
||||
|
||||
if (__TEST__) {
|
||||
|
||||
@@ -98,6 +98,22 @@ function markVersionMetadata() {
|
||||
markAndClear(`--profiler-version-${SCHEDULING_PROFILER_VERSION}`);
|
||||
}
|
||||
|
||||
function markInternalModuleRanges() {
|
||||
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
|
||||
if (
|
||||
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
|
||||
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.getInternalModuleRanges === 'function'
|
||||
) {
|
||||
const ranges = __REACT_DEVTOOLS_GLOBAL_HOOK__.getInternalModuleRanges();
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const [startStackFrame, stopStackFrame] = ranges[i];
|
||||
|
||||
markAndClear(`--react-internal-module-start-${startStackFrame}`);
|
||||
markAndClear(`--react-internal-module-stop-${stopStackFrame}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function markCommitStarted(lanes: Lanes): void {
|
||||
if (enableSchedulingProfiler) {
|
||||
if (supportsUserTimingV3) {
|
||||
@@ -114,6 +130,7 @@ export function markCommitStarted(lanes: Lanes): void {
|
||||
// we can log this data only once (when started) and remove the per-commit logging.
|
||||
markVersionMetadata();
|
||||
markLaneToLabelMetadata();
|
||||
markInternalModuleRanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
|
||||
|
||||
// Don't require this file directly; it's embedded by Rollup during build.
|
||||
|
||||
if (
|
||||
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
|
||||
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===
|
||||
'function'
|
||||
) {
|
||||
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
|
||||
|
||||
// Don't require this file directly; it's embedded by Rollup during build.
|
||||
|
||||
if (
|
||||
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
|
||||
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===
|
||||
'function'
|
||||
) {
|
||||
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());
|
||||
}
|
||||
@@ -440,7 +440,8 @@ function getPlugins(
|
||||
bundleType,
|
||||
globalName,
|
||||
filename,
|
||||
moduleType
|
||||
moduleType,
|
||||
bundle.wrapWithModuleBoundaries
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -80,6 +80,7 @@ const bundles = [
|
||||
entry: 'react',
|
||||
global: 'React',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
@@ -90,6 +91,7 @@ const bundles = [
|
||||
entry: 'react/unstable-shared-subset',
|
||||
global: 'React',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -108,6 +110,7 @@ const bundles = [
|
||||
entry: 'react/jsx-runtime',
|
||||
global: 'JSXRuntime',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
@@ -128,6 +131,7 @@ const bundles = [
|
||||
entry: 'react/jsx-dev-runtime',
|
||||
global: 'JSXDEVRuntime',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
@@ -138,6 +142,7 @@ const bundles = [
|
||||
entry: 'react-fetch/index.browser',
|
||||
global: 'ReactFetch',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -148,6 +153,7 @@ const bundles = [
|
||||
entry: 'react-fetch/index.node',
|
||||
global: 'ReactFetch',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'http', 'https'],
|
||||
},
|
||||
|
||||
@@ -158,6 +164,7 @@ const bundles = [
|
||||
entry: 'react-fs/index.browser.server',
|
||||
global: 'ReactFilesystem',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -168,6 +175,7 @@ const bundles = [
|
||||
entry: 'react-fs/index.node.server',
|
||||
global: 'ReactFilesystem',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'fs/promises', 'path'],
|
||||
},
|
||||
|
||||
@@ -178,6 +186,7 @@ const bundles = [
|
||||
entry: 'react-pg/index.browser.server',
|
||||
global: 'ReactPostgres',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -188,6 +197,7 @@ const bundles = [
|
||||
entry: 'react-pg/index.node.server',
|
||||
global: 'ReactPostgres',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'pg'],
|
||||
},
|
||||
|
||||
@@ -208,6 +218,7 @@ const bundles = [
|
||||
entry: 'react-dom',
|
||||
global: 'ReactDOM',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -219,6 +230,7 @@ const bundles = [
|
||||
global: 'ReactDOMForked',
|
||||
enableNewReconciler: true,
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -229,6 +241,7 @@ const bundles = [
|
||||
entry: 'react-dom/test-utils',
|
||||
global: 'ReactTestUtils',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'react-dom'],
|
||||
},
|
||||
|
||||
@@ -240,6 +253,7 @@ const bundles = [
|
||||
entry: 'react-dom/testing',
|
||||
global: 'ReactDOMTesting',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -253,6 +267,7 @@ const bundles = [
|
||||
name: 'react-dom-server-legacy.browser',
|
||||
global: 'ReactDOMServer',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
@@ -268,6 +283,7 @@ const bundles = [
|
||||
name: 'react-dom-server-legacy.node',
|
||||
externals: ['react', 'stream'],
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -284,6 +300,7 @@ const bundles = [
|
||||
name: 'react-dom-server.browser',
|
||||
global: 'ReactDOMServer',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
{
|
||||
@@ -293,6 +310,7 @@ const bundles = [
|
||||
name: 'react-dom-server.node',
|
||||
global: 'ReactDOMServer',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
{
|
||||
@@ -301,6 +319,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-relay/src/ReactDOMServerFB',
|
||||
global: 'ReactDOMServer',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -311,6 +330,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-webpack/writer.browser.server',
|
||||
global: 'ReactServerDOMWriter',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
{
|
||||
@@ -319,6 +339,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-webpack/writer.node.server',
|
||||
global: 'ReactServerDOMWriter',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -329,6 +350,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-webpack',
|
||||
global: 'ReactServerDOMReader',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -339,6 +361,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-webpack/plugin',
|
||||
global: 'ReactServerWebpackPlugin',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['fs', 'path', 'url', 'neo-async'],
|
||||
},
|
||||
|
||||
@@ -349,6 +372,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-webpack/node-loader',
|
||||
global: 'ReactServerWebpackNodeLoader',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['acorn'],
|
||||
},
|
||||
|
||||
@@ -359,6 +383,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-webpack/node-register',
|
||||
global: 'ReactFlightWebpackNodeRegister',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['url', 'module'],
|
||||
},
|
||||
|
||||
@@ -369,6 +394,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-relay/server',
|
||||
global: 'ReactFlightDOMRelayServer', // TODO: Rename to Writer
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [
|
||||
'react',
|
||||
'ReactFlightDOMRelayServerIntegration',
|
||||
@@ -383,6 +409,7 @@ const bundles = [
|
||||
entry: 'react-server-dom-relay',
|
||||
global: 'ReactFlightDOMRelayClient', // TODO: Rename to Reader
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [
|
||||
'react',
|
||||
'ReactFlightDOMRelayClientIntegration',
|
||||
@@ -397,6 +424,7 @@ const bundles = [
|
||||
entry: 'react-server-native-relay/server',
|
||||
global: 'ReactFlightNativeRelayServer', // TODO: Rename to Writer
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [
|
||||
'react',
|
||||
'ReactFlightNativeRelayServerIntegration',
|
||||
@@ -412,6 +440,7 @@ const bundles = [
|
||||
entry: 'react-server-native-relay',
|
||||
global: 'ReactFlightNativeRelayClient', // TODO: Rename to Reader
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [
|
||||
'react',
|
||||
'ReactFlightNativeRelayClientIntegration',
|
||||
@@ -427,6 +456,7 @@ const bundles = [
|
||||
entry: 'react-suspense-test-utils',
|
||||
global: 'ReactSuspenseTestUtils',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -445,6 +475,7 @@ const bundles = [
|
||||
global: 'ReactART',
|
||||
externals: ['react'],
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
// Include JSX
|
||||
@@ -468,6 +499,7 @@ const bundles = [
|
||||
global: 'ReactNativeRenderer',
|
||||
externals: ['react-native', 'ReactNativeInternalFeatureFlags'],
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: true,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -482,6 +514,7 @@ const bundles = [
|
||||
global: 'ReactNativeRenderer',
|
||||
externals: ['react-native'],
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: true,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -500,6 +533,7 @@ const bundles = [
|
||||
global: 'ReactFabric',
|
||||
externals: ['react-native', 'ReactNativeInternalFeatureFlags'],
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: true,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -514,6 +548,7 @@ const bundles = [
|
||||
global: 'ReactFabric',
|
||||
externals: ['react-native'],
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: true,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -544,6 +579,7 @@ const bundles = [
|
||||
'ReactNativeInternalFeatureFlags',
|
||||
],
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -559,6 +595,7 @@ const bundles = [
|
||||
entry: 'react-noop-renderer',
|
||||
global: 'ReactNoopRenderer',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'scheduler', 'scheduler/unstable_mock', 'expect'],
|
||||
},
|
||||
|
||||
@@ -569,6 +606,7 @@ const bundles = [
|
||||
entry: 'react-noop-renderer/persistent',
|
||||
global: 'ReactNoopRendererPersistent',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'scheduler', 'expect'],
|
||||
},
|
||||
|
||||
@@ -579,6 +617,7 @@ const bundles = [
|
||||
entry: 'react-noop-renderer/server',
|
||||
global: 'ReactNoopRendererServer',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'scheduler', 'expect'],
|
||||
},
|
||||
|
||||
@@ -589,6 +628,7 @@ const bundles = [
|
||||
entry: 'react-noop-renderer/flight-server',
|
||||
global: 'ReactNoopFlightServer',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [
|
||||
'react',
|
||||
'scheduler',
|
||||
@@ -604,6 +644,7 @@ const bundles = [
|
||||
entry: 'react-noop-renderer/flight-client',
|
||||
global: 'ReactNoopFlightClient',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [
|
||||
'react',
|
||||
'scheduler',
|
||||
@@ -619,6 +660,7 @@ const bundles = [
|
||||
entry: 'react-reconciler',
|
||||
global: 'ReactReconciler',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -629,6 +671,7 @@ const bundles = [
|
||||
entry: 'react-server',
|
||||
global: 'ReactServer',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -639,6 +682,7 @@ const bundles = [
|
||||
entry: 'react-server/flight',
|
||||
global: 'ReactFlightServer',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -649,6 +693,7 @@ const bundles = [
|
||||
entry: 'react-client/flight',
|
||||
global: 'ReactFlightClient',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -659,6 +704,7 @@ const bundles = [
|
||||
entry: 'react-reconciler/reflection',
|
||||
global: 'ReactFiberTreeReflection',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -669,6 +715,7 @@ const bundles = [
|
||||
entry: 'react-reconciler/constants',
|
||||
global: 'ReactReconcilerConstants',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -686,6 +733,7 @@ const bundles = [
|
||||
entry: 'react-is',
|
||||
global: 'ReactIs',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -696,6 +744,7 @@ const bundles = [
|
||||
entry: 'react-debug-tools',
|
||||
global: 'ReactDebugTools',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -708,6 +757,7 @@ const bundles = [
|
||||
entry: 'react-cache',
|
||||
global: 'ReactCacheOld',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'scheduler'],
|
||||
},
|
||||
|
||||
@@ -719,6 +769,7 @@ const bundles = [
|
||||
global: 'createSubscription',
|
||||
externals: ['react'],
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -734,6 +785,7 @@ const bundles = [
|
||||
entry: 'use-subscription',
|
||||
global: 'useSubscription',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -744,6 +796,7 @@ const bundles = [
|
||||
entry: 'use-sync-external-store',
|
||||
global: 'useSyncExternalStore',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
@@ -754,6 +807,7 @@ const bundles = [
|
||||
entry: 'use-sync-external-store/extra',
|
||||
global: 'useSyncExternalStoreExtra',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['react', 'use-sync-external-store'],
|
||||
},
|
||||
|
||||
@@ -764,6 +818,7 @@ const bundles = [
|
||||
entry: 'use-sync-external-store/index.native',
|
||||
global: 'useSyncExternalStoreNative',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['react', 'ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
@@ -783,6 +838,7 @@ const bundles = [
|
||||
entry: 'scheduler',
|
||||
global: 'Scheduler',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: true,
|
||||
externals: ['ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
@@ -802,6 +858,7 @@ const bundles = [
|
||||
entry: 'scheduler/unstable_mock',
|
||||
global: 'SchedulerMock',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
@@ -818,6 +875,7 @@ const bundles = [
|
||||
entry: 'scheduler/unstable_post_task',
|
||||
global: 'SchedulerPostTask',
|
||||
minifyWithProdErrorCodes: true,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -828,6 +886,7 @@ const bundles = [
|
||||
entry: 'jest-react',
|
||||
global: 'JestReact',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: ['react', 'scheduler', 'scheduler/unstable_mock'],
|
||||
},
|
||||
|
||||
@@ -842,6 +901,7 @@ const bundles = [
|
||||
entry: 'eslint-plugin-react-hooks',
|
||||
global: 'ESLintPluginReactHooks',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
|
||||
@@ -852,6 +912,7 @@ const bundles = [
|
||||
entry: 'react-refresh/babel',
|
||||
global: 'ReactFreshBabelPlugin',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
{
|
||||
@@ -860,6 +921,7 @@ const bundles = [
|
||||
entry: 'react-refresh/runtime',
|
||||
global: 'ReactFreshRuntime',
|
||||
minifyWithProdErrorCodes: false,
|
||||
wrapWithModuleBoundaries: false,
|
||||
externals: [],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const {resolve} = require('path');
|
||||
const {readFileSync} = require('fs');
|
||||
const {bundleTypes, moduleTypes} = require('./bundles');
|
||||
const reactVersion = require('../../package.json').version;
|
||||
|
||||
@@ -25,6 +27,26 @@ const {
|
||||
|
||||
const {RECONCILER} = moduleTypes;
|
||||
|
||||
function registerInternalModuleStart(globalName) {
|
||||
const path = resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'packages/shared/registerInternalModuleStart.js'
|
||||
);
|
||||
return String(readFileSync(path)).trim();
|
||||
}
|
||||
|
||||
function registerInternalModuleStop(globalName) {
|
||||
const path = resolve(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'packages/shared/registerInternalModuleStop.js'
|
||||
);
|
||||
return String(readFileSync(path)).trim();
|
||||
}
|
||||
|
||||
const license = ` * Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
@@ -319,7 +341,35 @@ ${source}
|
||||
},
|
||||
};
|
||||
|
||||
function wrapBundle(source, bundleType, globalName, filename, moduleType) {
|
||||
function wrapBundle(
|
||||
source,
|
||||
bundleType,
|
||||
globalName,
|
||||
filename,
|
||||
moduleType,
|
||||
wrapWithModuleBoundaries
|
||||
) {
|
||||
if (wrapWithModuleBoundaries) {
|
||||
switch (bundleType) {
|
||||
case NODE_DEV:
|
||||
case NODE_PROFILING:
|
||||
case FB_WWW_DEV:
|
||||
case FB_WWW_PROFILING:
|
||||
case RN_OSS_DEV:
|
||||
case RN_OSS_PROFILING:
|
||||
case RN_FB_DEV:
|
||||
case RN_FB_PROFILING:
|
||||
// Certain DEV and Profiling bundles should self-register their own module boundaries with DevTools.
|
||||
// This allows the Scheduling Profiler to de-emphasize (dim) internal stack frames.
|
||||
source = `
|
||||
${registerInternalModuleStart(globalName)}
|
||||
${source}
|
||||
${registerInternalModuleStop(globalName)}
|
||||
`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleType === RECONCILER) {
|
||||
// Standalone reconciler is only used by third-party renderers.
|
||||
// It is handled separately.
|
||||
|
||||
Reference in New Issue
Block a user