157
firstChild: null | DevToolsInstance,
158
nextSibling: null | DevToolsInstance,
159
source: null | string | Error | Source, // source location of this component function, or owned child stack
160
- errors: null | Map<string, number>, // error messages and count
161
- warnings: null | Map<string, number>, // warning messages and count
160
+ logCount: number, // total number of errors/warnings last seen
161
treeBaseDuration: number, // the profiled time of the last render of this subtree
162
data: Fiber, // one of a Fiber pair
163
};
170
firstChild: null,
171
nextSibling: null,
172
source: null,
174
- errors: null,
175
- warnings: null,
173
+ logCount: 0,
174
treeBaseDuration: 0,
175
data: fiber,
176
};
185
firstChild: null | DevToolsInstance,
186
nextSibling: null | DevToolsInstance,
187
source: null | string | Error | Source, // always null here.
190
- errors: null, // error messages and count
191
- warnings: null, // warning messages and count
188
+ logCount: number, // total number of errors/warnings last seen
189
treeBaseDuration: number, // the profiled time of the last render of this subtree
190
data: Fiber, // one of a Fiber pair
191
};
198
parent: null,
199
firstChild: null,
200
nextSibling: null,
204
- componentStack: null,
205
- errors: null,
206
- warnings: null,
201
+ source: null,
202
+ logCount: 0,
203
treeBaseDuration: 0,
204
data: fiber,
205
}: any);
217
firstChild: null | DevToolsInstance,
218
nextSibling: null | DevToolsInstance,
219
source: null | string | Error | Source, // source location of this server component, or owned child stack
224
- // Errors and Warnings happen per ReactComponentInfo which can appear in
225
- // multiple places but we track them per stateful VirtualInstance so
226
- // that old errors/warnings don't disappear when the instance is refreshed.
227
- errors: null | Map<string, number>, // error messages and count
228
- warnings: null | Map<string, number>, // warning messages and count
220
+ logCount: number, // total number of errors/warnings last seen
221
treeBaseDuration: number, // the profiled time of the last render of this subtree
222
// The latest info for this instance. This can be updated over time and the
223
// same info can appear in more than once ServerComponentInstance.
234
firstChild: null,
235
nextSibling: null,
236
source: null,
245
- errors: null,
246
- warnings: null,
237
+ logCount: 0,
238
treeBaseDuration: 0,
239
data: debugEntry,
240
};
959
toggleProfilingStatus = response.toggleProfilingStatus;
960
}
961
971
- // Tracks Fibers with recently changed number of error/warning messages.
972
- // These collections store the Fiber rather than the DevToolsInstance,
973
- // in order to avoid generating an DevToolsInstance for Fibers that never get mounted
974
- // (due to e.g. Suspense or error boundaries).
975
- // onErrorOrWarning() adds Fibers and recordPendingErrorsAndWarnings() later clears them.
976
- const fibersWithChangedErrorOrWarningCounts: Set<Fiber> = new Set();
977
- const pendingFiberToErrorsMap: WeakMap<
978
- Fiber,
979
- Map<string, number>,
980
- > = new WeakMap();
981
- const pendingFiberToWarningsMap: WeakMap<
982
- Fiber,
983
- Map<string, number>,
984
- > = new WeakMap();
962
+ type ComponentLogs = {
963
+ errors: Map<string, number>,
964
+ errorsCount: number,
965
+ warnings: Map<string, number>,
966
+ warningsCount: number,
967
+ };
968
+ // Tracks Errors/Warnings logs added to a Fiber. They are added before the commit and get
969
+ // picked up a FiberInstance. This keeps it around as long as the Fiber is alive which
970
+ // lets the Fiber get reparented/remounted and still observe the previous errors/warnings.
971
+ // Unless we explicitly clear the logs from a Fiber.
972
+ const fiberToComponentLogsMap: WeakMap<Fiber, ComponentLogs> = new WeakMap();
973
+ // Tracks whether we've performed a commit since the last log. This is used to know
974
+ // whether we received any new logs between the commit and post commit phases. I.e.
975
+ // if any passive effects called console.warn / console.error.
976
+ let needsToFlushComponentLogs = false;
977
+
978
+ function bruteForceFlushErrorsAndWarnings() {
979
+ // Refresh error/warning count for all mounted unfiltered Fibers.
980
+ let hasChanges = false;
981
+ // eslint-disable-next-line no-for-of-loops/no-for-of-loops
982
+ for (const devtoolsInstance of idToDevToolsInstanceMap.values()) {
983
+ if (devtoolsInstance.kind === FIBER_INSTANCE) {
984
+ const fiber = devtoolsInstance.data;
985
+ const componentLogsEntry = fiberToComponentLogsMap.get(fiber);
986
+ const changed = recordConsoleLogs(devtoolsInstance, componentLogsEntry);
987
+ if (changed) {
988
+ hasChanges = true;
989
+ updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);
990
+ }
991
+ } else {
992
+ // Virtual Instances cannot log in passive effects and so never appear here.
993
+ }
994
+ }
995
+ if (hasChanges) {
996
+ flushPendingEvents();
997
+ }
998
+ }
999
1000
function clearErrorsAndWarnings() {
1001
+ // Note, this only clears logs for Fibers that have instances. If they're filtered
1002
+ // and then mount, the logs are there. Ensuring we only clear what you've seen.
1003
+ // If we wanted to clear the whole set, we'd replace fiberToComponentLogsMap with a
1004
+ // new WeakMap.
1005
+
1006
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
1007
for (const devtoolsInstance of idToDevToolsInstanceMap.values()) {
989
- devtoolsInstance.errors = null;
990
- devtoolsInstance.warnings = null;
1008
if (devtoolsInstance.kind === FIBER_INSTANCE) {
992
- fibersWithChangedErrorOrWarningCounts.add(devtoolsInstance.data);
1009
+ const fiber = devtoolsInstance.data;
1010
+ fiberToComponentLogsMap.delete(fiber);
1011
+ if (fiber.alternate) {
1012
+ fiberToComponentLogsMap.delete(fiber.alternate);
1013
+ }
1014
} else {
1015
// TODO: Handle VirtualInstance.
1016
}
996
- updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);
1017
+ const changed = recordConsoleLogs(devtoolsInstance, undefined);
1018
+ if (changed) {
1019
+ updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);
1020
+ }
1021
}
1022
flushPendingEvents();
1023
}
1024
1001
- function clearMessageCountHelper(
1002
- instanceID: number,
1003
- pendingFiberToMessageCountMap: WeakMap<Fiber, Map<string, number>>,
1004
- forError: boolean,
1005
- ) {
1025
+ function clearConsoleLogsHelper(instanceID: number, type: 'error' | 'warn') {
1026
const devtoolsInstance = idToDevToolsInstanceMap.get(instanceID);
1027
if (devtoolsInstance !== undefined) {
1008
- let changed = false;
1009
- if (forError) {
1010
- if (
1011
- devtoolsInstance.errors !== null &&
1012
- devtoolsInstance.errors.size > 0
1013
- ) {
1014
- changed = true;
1015
- }
1016
- devtoolsInstance.errors = null;
1017
- } else {
1018
- if (
1019
- devtoolsInstance.warnings !== null &&
1020
- devtoolsInstance.warnings.size > 0
1021
- ) {
1022
- changed = true;
1023
- }
1024
- devtoolsInstance.warnings = null;
1025
- }
1028
if (devtoolsInstance.kind === FIBER_INSTANCE) {
1029
const fiber = devtoolsInstance.data;
1028
- // Throw out any pending changes.
1029
- pendingFiberToMessageCountMap.delete(fiber);
1030
-
1031
- if (changed) {
1032
- // If previous flushed counts have changed, schedule an update too.
1033
- fibersWithChangedErrorOrWarningCounts.add(fiber);
1034
- flushPendingEvents();
1035
-
1036
- updateMostRecentlyInspectedElementIfNecessary(instanceID);
1037
- } else {
1038
- fibersWithChangedErrorOrWarningCounts.delete(fiber);
1030
+ const componentLogsEntry = fiberToComponentLogsMap.get(fiber);
1031
+ if (componentLogsEntry !== undefined) {
1032
+ if (type === 'error') {
1033
+ componentLogsEntry.errors.clear();
1034
+ componentLogsEntry.errorsCount = 0;
1035
+ } else {
1036
+ componentLogsEntry.warnings.clear();
1037
+ componentLogsEntry.warningsCount = 0;
1038
+ }
1039
+ const changed = recordConsoleLogs(
1040
+ devtoolsInstance,
1041
+ componentLogsEntry,
1042
+ );
1043
+ if (changed) {
1044
+ flushPendingEvents();
1045
+ updateMostRecentlyInspectedElementIfNecessary(devtoolsInstance.id);
1046
+ }
1047
}
1048
} else {
1049
// TODO: Handle VirtualInstance.
1052
}
1053
1054
function clearErrorsForElementID(instanceID: number) {
1047
- clearMessageCountHelper(instanceID, pendingFiberToErrorsMap, true);
1055
+ clearConsoleLogsHelper(instanceID, 'error');
1056
}
1057
1058
function clearWarningsForElementID(instanceID: number) {
1051
- clearMessageCountHelper(instanceID, pendingFiberToWarningsMap, false);
1059
+ clearConsoleLogsHelper(instanceID, 'warn');
1060
}
1061
1062
function updateMostRecentlyInspectedElementIfNecessary(
1094
// [Warning: %o, {...}] and [Warning: %o, {...}] will be considered as the same message,
1095
// even if objects are different
1096
const message = formatConsoleArgumentsToSingleString(...args);
1089
- if (__DEBUG__) {
1090
- const fiberInstance = fiberToFiberInstanceMap.get(fiber);
1091
- if (fiberInstance !== undefined) {
1092
- debug('onErrorOrWarning', fiberInstance, null, `${type}: "${message}"`);
1093
- }
1094
- }
1095
-
1096
- // Mark this Fiber as needed its warning/error count updated during the next flush.
1097
- fibersWithChangedErrorOrWarningCounts.add(fiber);
1097
1098
// Track the warning/error for later.
1100
- const fiberMap =
1101
- type === 'error' ? pendingFiberToErrorsMap : pendingFiberToWarningsMap;
1102
- const messageMap = fiberMap.get(fiber);
1103
- if (messageMap != null) {
1104
- const count = messageMap.get(message) || 0;
1105
- messageMap.set(message, count + 1);
1099
+ let componentLogsEntry = fiberToComponentLogsMap.get(fiber);
1100
+ if (componentLogsEntry === undefined && fiber.alternate !== null) {
1101
+ componentLogsEntry = fiberToComponentLogsMap.get(fiber.alternate);
1102
+ if (componentLogsEntry !== undefined) {
1103
+ // Use the same set for both Fibers.
1104
+ fiberToComponentLogsMap.set(fiber, componentLogsEntry);
1105
+ }
1106
+ }
1107
+ if (componentLogsEntry === undefined) {
1108
+ componentLogsEntry = {
1109
+ errors: new Map(),
1110
+ errorsCount: 0,
1111
+ warnings: new Map(),
1112
+ warningsCount: 0,
1113
+ };
1114
+ fiberToComponentLogsMap.set(fiber, componentLogsEntry);
1115
+ }
1116
+
1117
+ const messageMap =
1118
+ type === 'error'
1119
+ ? componentLogsEntry.errors
1120
+ : componentLogsEntry.warnings;
1121
+ const count = messageMap.get(message) || 0;
1122
+ messageMap.set(message, count + 1);
1123
+ if (type === 'error') {
1124
+ componentLogsEntry.errorsCount++;
1125
} else {
1107
- fiberMap.set(fiber, new Map([[message, 1]]));
1126
+ componentLogsEntry.warningsCount++;
1127
}
1128
1110
- // Passive effects may trigger errors or warnings too;
1111
- // In this case, we should wait until the rest of the passive effects have run,
1112
- // but we shouldn't wait until the next commit because that might be a long time.
1113
- // This would also cause "tearing" between an inspected Component and the tree view.
1114
- // Then again we don't want to flush too soon because this could be an error during async rendering.
1115
- // Use a debounce technique to ensure that we'll eventually flush.
1116
- flushPendingErrorsAndWarningsAfterDelay();
1129
+ // The changes will be flushed later when we commit.
1130
+
1131
+ // If the log happened in a passive effect, then this happens after we've
1132
+ // already committed the new tree so the change won't show up until we rerender
1133
+ // that component again. We need to visit a Component with passive effects in
1134
+ // handlePostCommitFiberRoot again to ensure that we flush the changes after passive.
1135
+ needsToFlushComponentLogs = true;
1136
}
1137
1138
// Patching the console enables DevTools to do a few useful things:
1349
currentRoot = (null: any);
1350
});
1351
1333
- // Also re-evaluate all error and warning counts given the new filters.
1334
- reevaluateErrorsAndWarnings();
1352
flushPendingEvents();
1353
+
1354
+ needsToFlushComponentLogs = false;
1355
}
1356
1357
function getEnvironmentNames(): Array<string> {
1549
// When a mount or update is in progress, this value tracks the root that is being operated on.
1550
let currentRoot: FiberInstance = (null: any);
1551
1533
- // Returns a FiberInstance if one has already been generated for the Fiber or null if one has not been generated.
1534
- // Use this method while e.g. logging to avoid over-retaining Fibers.
1535
- function getFiberInstanceUnsafe(fiber: Fiber): FiberInstance | null {
1536
- const fiberInstance = fiberToFiberInstanceMap.get(fiber);
1537
- if (fiberInstance !== undefined) {
1538
- return fiberInstance;
1539
- } else {
1540
- const {alternate} = fiber;
1541
- if (alternate !== null) {
1542
- const alternateInstance = fiberToFiberInstanceMap.get(alternate);
1543
- if (alternateInstance !== undefined) {
1544
- return alternateInstance;
1545
- }
1546
- }
1547
- }
1548
- return null;
1549
- }
1550
-
1551
- function getFiberIDUnsafe(fiber: Fiber): number | null {
1552
- const fiberInstance = getFiberInstanceUnsafe(fiber);
1553
- return fiberInstance === null ? null : fiberInstance.id;
1554
- }
1555
-
1552
// Removes a Fiber (and its alternate) from the Maps used to track their id.
1553
// This method should always be called when a Fiber is unmounting.
1554
function untrackFiber(nearestInstance: DevToolsInstance, fiber: Fiber) {
1846
}
1847
}
1848
1853
- let flushPendingErrorsAndWarningsAfterDelayTimeoutID: null | TimeoutID = null;
1854
-
1855
- function clearPendingErrorsAndWarningsAfterDelay() {
1856
- if (flushPendingErrorsAndWarningsAfterDelayTimeoutID !== null) {
1857
- clearTimeout(flushPendingErrorsAndWarningsAfterDelayTimeoutID);
1858
- flushPendingErrorsAndWarningsAfterDelayTimeoutID = null;
1859
- }
1860
- }
1861
-
1862
- function flushPendingErrorsAndWarningsAfterDelay() {
1863
- clearPendingErrorsAndWarningsAfterDelay();
1864
-
1865
- flushPendingErrorsAndWarningsAfterDelayTimeoutID = setTimeout(() => {
1866
- flushPendingErrorsAndWarningsAfterDelayTimeoutID = null;
1867
-
1868
- if (pendingOperations.length > 0) {
1869
- // On the off chance that something else has pushed pending operations,
1870
- // we should bail on warnings; it's probably not safe to push midway.
1871
- return;
1872
- }
1873
-
1874
- recordPendingErrorsAndWarnings();
1875
-
1876
- if (shouldBailoutWithPendingOperations()) {
1877
- // No warnings or errors to flush; we can bail out early here too.
1878
- return;
1879
- }
1880
-
1881
- // We can create a smaller operations array than flushPendingEvents()
1882
- // because we only need to flush warning and error counts.
1883
- // Only a few pieces of fixed information are required up front.
1884
- const operations: OperationsArray = new Array(
1885
- 3 + pendingOperations.length,
1886
- );
1887
- operations[0] = rendererID;
1888
- if (currentRoot === null) {
1889
- // TODO: This is not always safe so this field is probably not needed.
1890
- operations[1] = -1;
1891
- } else {
1892
- operations[1] = currentRoot.id;
1893
- }
1894
- operations[2] = 0; // String table size
1895
- for (let j = 0; j < pendingOperations.length; j++) {
1896
- operations[3 + j] = pendingOperations[j];
1897
- }
1898
-
1899
- flushOrQueueOperations(operations);
1900
-
1901
- pendingOperations.length = 0;
1902
- }, 1000);
1903
- }
1904
-
1905
- function reevaluateErrorsAndWarnings() {
1906
- fibersWithChangedErrorOrWarningCounts.clear();
1907
- // eslint-disable-next-line no-for-of-loops/no-for-of-loops
1908
- for (const devtoolsInstance of idToDevToolsInstanceMap.values()) {
1909
- if (devtoolsInstance.kind === FIBER_INSTANCE) {
1910
- fibersWithChangedErrorOrWarningCounts.add(devtoolsInstance.data);
1911
- } else {
1912
- // TODO: Handle VirtualInstance.
1913
- }
1914
- }
1915
- recordPendingErrorsAndWarnings();
1916
- }
1917
-
1918
- function mergeMapsAndGetCountHelper(
1919
- fiber: Fiber,
1920
- fiberID: number,
1921
- pendingFiberToMessageCountMap: WeakMap<Fiber, Map<string, number>>,
1922
- forError: boolean,
1923
- ): number {
1924
- let newCount = 0;
1925
-
1926
- const devtoolsInstance = idToDevToolsInstanceMap.get(fiberID);
1927
-
1928
- if (devtoolsInstance === undefined) {
1929
- return 0;
1930
- }
1931
-
1932
- let messageCountMap = forError
1933
- ? devtoolsInstance.errors
1934
- : devtoolsInstance.warnings;
1935
-
1936
- const pendingMessageCountMap = pendingFiberToMessageCountMap.get(fiber);
1937
- if (pendingMessageCountMap != null) {
1938
- if (messageCountMap === null) {
1939
- messageCountMap = pendingMessageCountMap;
1940
- if (forError) {
1941
- devtoolsInstance.errors = pendingMessageCountMap;
1942
- } else {
1943
- devtoolsInstance.warnings = pendingMessageCountMap;
1944
- }
1945
- } else {
1946
- // This Flow refinement should not be necessary and yet...
1947
- const refinedMessageCountMap = ((messageCountMap: any): Map<
1948
- string,
1949
- number,
1950
- >);
1951
-
1952
- pendingMessageCountMap.forEach((pendingCount, message) => {
1953
- const previousCount = refinedMessageCountMap.get(message) || 0;
1954
- refinedMessageCountMap.set(message, previousCount + pendingCount);
1955
- });
1849
+ function recordConsoleLogs(
1850
+ instance: FiberInstance | VirtualInstance,
1851
+ componentLogsEntry: void | ComponentLogs,
1852
+ ): boolean {
1853
+ if (componentLogsEntry === undefined) {
1854
+ if (instance.logCount === 0) {
1855
+ // Nothing has changed.
1856
+ return false;
1857
}
1957
- }
1958
-
1959
- if (!shouldFilterFiber(fiber)) {
1960
- if (messageCountMap != null) {
1961
- messageCountMap.forEach(count => {
1962
- newCount += count;
1963
- });
1858
+ // Reset to zero.
1859
+ instance.logCount = 0;
1860
+ pushOperation(TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS);
1861
+ pushOperation(instance.id);
1862
+ pushOperation(0);
1863
+ pushOperation(0);
1864
+ return true;
1865
+ } else {
1866
+ const totalCount =
1867
+ componentLogsEntry.errorsCount + componentLogsEntry.warningsCount;
1868
+ if (instance.logCount === totalCount) {
1869
+ // Nothing has changed.
1870
+ return false;
1871
}
1872
+ // Update counts.
1873
+ instance.logCount = totalCount;
1874
+ pushOperation(TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS);
1875
+ pushOperation(instance.id);
1876
+ pushOperation(componentLogsEntry.errorsCount);
1877
+ pushOperation(componentLogsEntry.warningsCount);
1878
+ return true;
1879
}
1966
-
1967
- pendingFiberToMessageCountMap.delete(fiber);
1968
-
1969
- return newCount;
1970
- }
1971
-
1972
- function recordPendingErrorsAndWarnings() {
1973
- clearPendingErrorsAndWarningsAfterDelay();
1974
-
1975
- fibersWithChangedErrorOrWarningCounts.forEach(fiber => {
1976
- const fiberID = getFiberIDUnsafe(fiber);
1977
- if (fiberID === null) {
1978
- // Don't send updates for Fibers that didn't mount due to e.g. Suspense or an error boundary.
1979
- } else {
1980
- const errorCount = mergeMapsAndGetCountHelper(
1981
- fiber,
1982
- fiberID,
1983
- pendingFiberToErrorsMap,
1984
- true,
1985
- );
1986
- const warningCount = mergeMapsAndGetCountHelper(
1987
- fiber,
1988
- fiberID,
1989
- pendingFiberToWarningsMap,
1990
- false,
1991
- );
1992
-
1993
- pushOperation(TREE_OPERATION_UPDATE_ERRORS_OR_WARNINGS);
1994
- pushOperation(fiberID);
1995
- pushOperation(errorCount);
1996
- pushOperation(warningCount);
1997
-
1998
- // Only clear the ones that we've already shown. Leave others in case
1999
- // they mount later.
2000
- pendingFiberToErrorsMap.delete(fiber);
2001
- pendingFiberToWarningsMap.delete(fiber);
2002
- }
2003
- });
2004
- fibersWithChangedErrorOrWarningCounts.clear();
1880
}
1881
1882
function flushPendingEvents(root: Object): void {
2008
- // Add any pending errors and warnings to the operations array.
2009
- recordPendingErrorsAndWarnings();
2010
-
1883
if (shouldBailoutWithPendingOperations()) {
1884
// If we aren't profiling, we can just bail out here.
1885
// No use sending an empty update over the bridge.
2132
}
2133
}
2134
2135
+ let componentLogsEntry = fiberToComponentLogsMap.get(fiber);
2136
+ if (componentLogsEntry === undefined && fiber.alternate !== null) {
2137
+ componentLogsEntry = fiberToComponentLogsMap.get(fiber.alternate);
2138
+ }
2139
+ recordConsoleLogs(fiberInstance, componentLogsEntry);
2140
+
2141
if (isProfilingSupported) {
2142
recordProfilingDurations(fiberInstance, null);
2143
}
2237
2238
idToDevToolsInstanceMap.delete(fiberInstance.id);
2239
2362
- // Restore any errors/warnings associated with this fiber to the pending
2363
- // map. I.e. treat it as before we tracked the instances. This lets us
2364
- // restore them if we remount the same Fibers later. Otherwise we rely
2365
- // on the GC of the Fibers to clean them up.
2366
- if (fiberInstance.errors !== null) {
2367
- pendingFiberToErrorsMap.set(fiber, fiberInstance.errors);
2368
- fiberInstance.errors = null;
2369
- }
2370
- if (fiberInstance.warnings !== null) {
2371
- pendingFiberToWarningsMap.set(fiber, fiberInstance.warnings);
2372
- fiberInstance.warnings = null;
2373
- }
2374
-
2240
if (fiberToFiberInstanceMap.get(fiber) === fiberInstance) {
2241
fiberToFiberInstanceMap.delete(fiber);
2242
}
3380
}
3381
3382
if (fiberInstance !== null) {
3383
+ let componentLogsEntry = fiberToComponentLogsMap.get(
3384
+ fiberInstance.data,
3385
+ );
3386
+ if (componentLogsEntry === undefined && fiberInstance.data.alternate) {
3387
+ componentLogsEntry = fiberToComponentLogsMap.get(
3388
+ fiberInstance.data.alternate,
3389
+ );
3390
+ }
3391
+ recordConsoleLogs(fiberInstance, componentLogsEntry);
3392
+
3393
const isProfilingSupported =
3394
nextFiber.hasOwnProperty('treeBaseDuration');
3395
if (isProfilingSupported) {
3494
mountFiberRecursively(root.current, false);
3495
3496
flushPendingEvents(root);
3497
+
3498
+ needsToFlushComponentLogs = false;
3499
currentRoot = (null: any);
3500
});
3501
}
3518
passiveEffectDuration;
3519
}
3520
}
3521
+
3522
+ if (needsToFlushComponentLogs) {
3523
+ // We received new logs after commit. I.e. in a passive effect. We need to
3524
+ // traverse the tree to find the affected ones. If we just moved the whole
3525
+ // tree traversal from handleCommitFiberRoot to handlePostCommitFiberRoot
3526
+ // this wouldn't be needed. For now we just brute force check all instances.
3527
+ // This is not that common of a case.
3528
+ bruteForceFlushErrorsAndWarnings();
3529
+ }
3530
}
3531
3532
function handleCommitFiberRoot(
3636
// We're done here.
3637
flushPendingEvents(root);
3638
3639
+ needsToFlushComponentLogs = false;
3640
+
3641
if (traceUpdatesEnabled) {
3642
hook.emit('traceUpdates', traceUpdatesForNodes);
3643
}
4225
source = getSourceForFiberInstance(fiberInstance);
4226
}
4227
4228
+ const componentLogsEntry = fiberToComponentLogsMap.get(fiber);
4229
+
4230
return {
4231
id: fiberInstance.id,
4232
4277
props: memoizedProps,
4278
state: showState ? memoizedState : null,
4279
errors:
4390
- fiberInstance.errors === null
4280
+ componentLogsEntry === undefined
4281
? []
4392
- : Array.from(fiberInstance.errors.entries()),
4282
+ : Array.from(componentLogsEntry.errors.entries()),
4283
warnings:
4394
- fiberInstance.warnings === null
4284
+ componentLogsEntry === undefined
4285
? []
4396
- : Array.from(fiberInstance.warnings.entries()),
4286
+ : Array.from(componentLogsEntry.warnings.entries()),
4287
4288
// List of owners
4289
owners,
4368
hooks: null,
4369
props: props,
4370
state: null,
4481
- errors:
4482
- virtualInstance.errors === null
4483
- ? []
4484
- : Array.from(virtualInstance.errors.entries()),
4485
- warnings:
4486
- virtualInstance.warnings === null
4487
- ? []
4488
- : Array.from(virtualInstance.warnings.entries()),
4489
-
4371
+ errors: [], // TODO: Handle errors on Virtual Instances.
4372
+ warnings: [], // TODO: Handle warnings on Virtual Instances.
4373
// List of owners
4374
owners,
4375