From 70684a773377d931fe5f7965928903db6f21a06f Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Wed, 8 Sep 2021 18:09:57 -0400 Subject: [PATCH 1/7] [DevTools] RFC: Add initial APIs for logging instrumentation events under feature flag --- .../react-devtools-extensions/src/main.js | 5 + packages/react-devtools-shared/src/Logger.js | 43 ++++++ ...nceMarks.js => PerformanceLoggingUtils.js} | 39 ++++++ .../config/DevToolsFeatureFlags.core-fb.js | 2 + .../config/DevToolsFeatureFlags.core-oss.js | 2 + .../config/DevToolsFeatureFlags.default.js | 2 + .../DevToolsFeatureFlags.extension-fb.js | 2 + .../DevToolsFeatureFlags.extension-oss.js | 2 + .../src/hookNamesCache.js | 124 ++++++++++-------- .../src/hooks/astUtils.js | 2 +- .../src/hooks/parseHookNames/index.js | 2 +- .../parseHookNames/loadSourceAndMetadata.js | 2 +- .../parseHookNames/parseSourceAndMetadata.js | 2 +- 13 files changed, 172 insertions(+), 57 deletions(-) create mode 100644 packages/react-devtools-shared/src/Logger.js rename packages/react-devtools-shared/src/{PerformanceMarks.js => PerformanceLoggingUtils.js} (63%) diff --git a/packages/react-devtools-extensions/src/main.js b/packages/react-devtools-extensions/src/main.js index d77ff853d0e..7eb33cd3f66 100644 --- a/packages/react-devtools-extensions/src/main.js +++ b/packages/react-devtools-extensions/src/main.js @@ -18,6 +18,7 @@ import { localStorageRemoveItem, localStorageSetItem, } from 'react-devtools-shared/src/storage'; +import {registerEventLogger} from 'react-devtools-shared/src/Logger'; import DevTools from 'react-devtools-shared/src/devtools/views/DevTools'; import {__DEBUG__} from 'react-devtools-shared/src/constants'; @@ -87,6 +88,10 @@ function createPanelIfReactLoaded() { const tabId = chrome.devtools.inspectedWindow.tabId; + registerEventLogger((_event: LogEvent) => { + // TODO: hook up event logging + }); + function initBridgeAndStore() { const port = chrome.runtime.connect({ name: '' + tabId, diff --git a/packages/react-devtools-shared/src/Logger.js b/packages/react-devtools-shared/src/Logger.js new file mode 100644 index 00000000000..e22560e0e11 --- /dev/null +++ b/packages/react-devtools-shared/src/Logger.js @@ -0,0 +1,43 @@ +/** + * 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 strict-local + */ + +import {enableLogger} from 'react-devtools-feature-flags'; + +export type LogEvent = {| + +name: 'parseHookNames', + +displayName: string | null, + +numberOfHooks: number | null, + +durationMs: number, + +resolution: 'success' | 'error' | 'timeout', +|}; + +export type LogFunction = LogEvent => void; + +let loggers = []; +export const logEvent: LogFunction = + enableLogger === true + ? function logEvent(event: LogEvent): void { + loggers.forEach(log => { + log(event); + }); + } + : function logEvent() {}; + +export const registerEventLogger = + enableLogger === true + ? function registerEventLogger(eventLogger: LogFunction): () => void { + if (enableLogger) { + loggers.push(eventLogger); + return function unregisterEventLogger() { + loggers = loggers.filter(logger => logger !== eventLogger); + }; + } + return () => {}; + } + : function registerEventLogger() {}; diff --git a/packages/react-devtools-shared/src/PerformanceMarks.js b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js similarity index 63% rename from packages/react-devtools-shared/src/PerformanceMarks.js rename to packages/react-devtools-shared/src/PerformanceLoggingUtils.js index e702d3923f1..3b53aa9d1da 100644 --- a/packages/react-devtools-shared/src/PerformanceMarks.js +++ b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js @@ -14,6 +14,9 @@ const supportsUserTiming = typeof performance.mark === 'function' && typeof performance.clearMarks === 'function'; +const supportsPerformanceNow = + typeof performance !== 'undefined' && typeof performance.now === 'function'; + function mark(markName: string): void { if (supportsUserTiming) { performance.mark(markName + '-start'); @@ -27,6 +30,13 @@ function measure(markName: string): void { } } +function now(): number { + if (supportsPerformanceNow) { + return performance.now(); + } + return Date.now(); +} + export async function withAsyncPerformanceMark( markName: string, callback: () => Promise, @@ -66,3 +76,32 @@ export function withCallbackPerformanceMark( } return callback(() => {}); } + +export async function measureAsyncDuration( + callback: () => Promise, +): Promise<[number, TReturn]> { + const start = now(); + const result = await callback(); + const duration = now() - start; + return [duration, result]; +} + +export function measureSyncDuration( + callback: () => TReturn, +): [number, TReturn] { + const start = now(); + const result = callback(); + const duration = now() - start; + return [duration, result]; +} + +export function measureCallbackDuration( + callback: (done: () => number) => TReturn, +): TReturn { + const start = now(); + const done = () => { + const duration = now() - start; + return duration; + }; + return callback(done); +} diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js index 6c0568867ba..1dc2fb09fd6 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js @@ -16,6 +16,8 @@ export const enableProfilerChangedHookIndices = true; export const isInternalFacebookBuild = true; export const enableNamedHooksFeature = false; +export const enableLogger = false; + export const consoleManagedByDevToolsDuringStrictMode = false; /************************************************************************ diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js index 341af11e17f..18a40de7768 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js @@ -16,6 +16,8 @@ export const enableProfilerChangedHookIndices = false; export const isInternalFacebookBuild = false; export const enableNamedHooksFeature = false; +export const enableLogger = false; + export const consoleManagedByDevToolsDuringStrictMode = false; /************************************************************************ diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js index e6404254a38..d8ba0b07071 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js @@ -16,4 +16,6 @@ export const enableProfilerChangedHookIndices = false; export const isInternalFacebookBuild = false; export const enableNamedHooksFeature = true; +export const enableLogger = false; + export const consoleManagedByDevToolsDuringStrictMode = true; diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js index d4e6160b5e8..f85ec064fa1 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js @@ -16,6 +16,8 @@ export const enableProfilerChangedHookIndices = true; export const isInternalFacebookBuild = true; export const enableNamedHooksFeature = true; +export const enableLogger = false; + export const consoleManagedByDevToolsDuringStrictMode = true; /************************************************************************ diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js index 382c3fab4c3..609cc8263da 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js @@ -16,6 +16,8 @@ export const enableProfilerChangedHookIndices = true; export const isInternalFacebookBuild = false; export const enableNamedHooksFeature = true; +export const enableLogger = false; + export const consoleManagedByDevToolsDuringStrictMode = true; /************************************************************************ diff --git a/packages/react-devtools-shared/src/hookNamesCache.js b/packages/react-devtools-shared/src/hookNamesCache.js index 306b13c5252..1f5a834fd84 100644 --- a/packages/react-devtools-shared/src/hookNamesCache.js +++ b/packages/react-devtools-shared/src/hookNamesCache.js @@ -18,6 +18,8 @@ import type { } from 'react-devtools-shared/src/types'; import type {HookSource} from 'react-debug-tools/src/ReactDebugHooks'; import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext'; +import {measureCallbackDuration} from './PerformanceLoggingUtils'; +import {logEvent} from './Logger'; const TIMEOUT = 30000; @@ -92,7 +94,13 @@ export function loadHookNames( }, }; - const wake = () => { + let timeoutID; + + const wake = ( + resolution: 'success' | 'error' | 'timeout', + hookNames: HookNames | null, + durationMs: number, + ) => { if (timeoutID) { clearTimeout(timeoutID); timeoutID = null; @@ -101,6 +109,15 @@ export function loadHookNames( // This assumes they won't throw. callbacks.forEach(callback => callback()); callbacks.clear(); + + // Log duration for parsing hook names + logEvent({ + name: 'parseHookNames', + displayName: element.displayName, + numberOfHooks: hookNames?.size ?? null, + durationMs, + resolution, + }); }; const newRecord: Record = (record = { @@ -110,64 +127,65 @@ export function loadHookNames( let didTimeout = false; - loadHookNamesFunction(hooksTree, fetchFileWithCaching).then( - function onSuccess(hookNames) { - if (didTimeout) { - return; - } - + measureCallbackDuration(done => { + loadHookNamesFunction(hooksTree, fetchFileWithCaching).then( + function onSuccess(hookNames) { + if (didTimeout) { + return; + } + + if (__DEBUG__) { + console.log('[hookNamesCache] onSuccess() hookNames:', hookNames); + } + + if (hookNames) { + const resolvedRecord = ((newRecord: any): ResolvedRecord); + resolvedRecord.status = Resolved; + resolvedRecord.value = hookNames; + } else { + const notFoundRecord = ((newRecord: any): RejectedRecord); + notFoundRecord.status = Rejected; + notFoundRecord.value = null; + } + + wake('success', hookNames, done()); + }, + function onError(error) { + if (didTimeout) { + return; + } + + if (__DEBUG__) { + console.log('[hookNamesCache] onError()'); + } + + console.error(error); + + const thrownRecord = ((newRecord: any): RejectedRecord); + thrownRecord.status = Rejected; + thrownRecord.value = null; + + wake('error', null, done()); + }, + ); + + // Eventually timeout and stop trying to load names. + timeoutID = setTimeout(function onTimeout() { if (__DEBUG__) { - console.log('[hookNamesCache] onSuccess() hookNames:', hookNames); - } - - if (hookNames) { - const resolvedRecord = ((newRecord: any): ResolvedRecord); - resolvedRecord.status = Resolved; - resolvedRecord.value = hookNames; - } else { - const notFoundRecord = ((newRecord: any): RejectedRecord); - notFoundRecord.status = Rejected; - notFoundRecord.value = null; + console.log('[hookNamesCache] onTimeout()'); } - wake(); - }, - function onError(error) { - if (didTimeout) { - return; - } - - if (__DEBUG__) { - console.log('[hookNamesCache] onError()'); - } - - console.error(error); - - const thrownRecord = ((newRecord: any): RejectedRecord); - thrownRecord.status = Rejected; - thrownRecord.value = null; - - wake(); - }, - ); - - // Eventually timeout and stop trying to load names. - let timeoutID = setTimeout(function onTimeout() { - if (__DEBUG__) { - console.log('[hookNamesCache] onTimeout()'); - } - - timeoutID = null; - - didTimeout = true; + timeoutID = null; - const timedoutRecord = ((newRecord: any): RejectedRecord); - timedoutRecord.status = Rejected; - timedoutRecord.value = null; + didTimeout = true; - wake(); - }, TIMEOUT); + const timedoutRecord = ((newRecord: any): RejectedRecord); + timedoutRecord.status = Rejected; + timedoutRecord.value = null; + wake('timeout', null, done()); + }, TIMEOUT); + }); map.set(element, record); } diff --git a/packages/react-devtools-shared/src/hooks/astUtils.js b/packages/react-devtools-shared/src/hooks/astUtils.js index 05c6391941d..1c669022db2 100644 --- a/packages/react-devtools-shared/src/hooks/astUtils.js +++ b/packages/react-devtools-shared/src/hooks/astUtils.js @@ -7,7 +7,7 @@ * @flow */ -import {withSyncPerformanceMark} from 'react-devtools-shared/src/PerformanceMarks'; +import {withSyncPerformanceMark} from 'react-devtools-shared/src/PerformanceLoggingUtils'; import traverse, {NodePath, Node} from '@babel/traverse'; import {File} from '@babel/types'; diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/index.js b/packages/react-devtools-shared/src/hooks/parseHookNames/index.js index a400a021a91..f65b2562bfa 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/index.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/index.js @@ -12,7 +12,7 @@ import type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks'; import type {HookNames} from 'react-devtools-shared/src/types'; import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext'; -import {withAsyncPerformanceMark} from 'react-devtools-shared/src/PerformanceMarks'; +import {withAsyncPerformanceMark} from 'react-devtools-shared/src/PerformanceLoggingUtils'; import WorkerizedParseSourceAndMetadata from './parseSourceAndMetadata.worker'; import typeof * as ParseSourceAndMetadataModule from './parseSourceAndMetadata'; import {flattenHooksList, loadSourceAndMetadata} from './loadSourceAndMetadata'; diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js b/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js index e8f043be24c..97959517717 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js @@ -52,7 +52,7 @@ import { withAsyncPerformanceMark, withCallbackPerformanceMark, withSyncPerformanceMark, -} from 'react-devtools-shared/src/PerformanceMarks'; +} from 'react-devtools-shared/src/PerformanceLoggingUtils'; import type { HooksNode, diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js b/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js index 967576d659f..f9c477ac9ad 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js @@ -21,7 +21,7 @@ import {SourceMapMetadataConsumer} from '../SourceMapMetadataConsumer'; import { withAsyncPerformanceMark, withSyncPerformanceMark, -} from 'react-devtools-shared/src/PerformanceMarks'; +} from 'react-devtools-shared/src/PerformanceLoggingUtils'; import type { HooksList, From 7b39448d8c8dc2c00a84aac7273a97c95598d01c Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Mon, 13 Sep 2021 16:08:07 -0400 Subject: [PATCH 2/7] Rmeove underscore in name --- packages/react-devtools-extensions/src/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-devtools-extensions/src/main.js b/packages/react-devtools-extensions/src/main.js index 7eb33cd3f66..6acb35aa28b 100644 --- a/packages/react-devtools-extensions/src/main.js +++ b/packages/react-devtools-extensions/src/main.js @@ -88,7 +88,7 @@ function createPanelIfReactLoaded() { const tabId = chrome.devtools.inspectedWindow.tabId; - registerEventLogger((_event: LogEvent) => { + registerEventLogger((event: LogEvent) => { // TODO: hook up event logging }); From 3e448e101132c073ed9328f76d5fa5ff7aa5a010 Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Mon, 13 Sep 2021 17:03:28 -0400 Subject: [PATCH 3/7] Update PerformanceLoggingUtils apis as per feedback --- packages/react-devtools-shared/src/Logger.js | 2 +- .../src/PerformanceLoggingUtils.js | 80 +++++------ .../src/hookNamesCache.js | 135 ++++++++++-------- .../src/hooks/astUtils.js | 10 +- .../src/hooks/parseHookNames/index.js | 4 +- .../parseHookNames/loadSourceAndMetadata.js | 30 ++-- .../parseHookNames/parseSourceAndMetadata.js | 28 ++-- 7 files changed, 150 insertions(+), 139 deletions(-) diff --git a/packages/react-devtools-shared/src/Logger.js b/packages/react-devtools-shared/src/Logger.js index e22560e0e11..5155d5e5f4d 100644 --- a/packages/react-devtools-shared/src/Logger.js +++ b/packages/react-devtools-shared/src/Logger.js @@ -10,7 +10,7 @@ import {enableLogger} from 'react-devtools-feature-flags'; export type LogEvent = {| - +name: 'parseHookNames', + +name: 'loadHookNames', +displayName: string | null, +numberOfHooks: number | null, +durationMs: number, diff --git a/packages/react-devtools-shared/src/PerformanceLoggingUtils.js b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js index 3b53aa9d1da..f05c28240f5 100644 --- a/packages/react-devtools-shared/src/PerformanceLoggingUtils.js +++ b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js @@ -37,71 +37,71 @@ function now(): number { return Date.now(); } -export async function withAsyncPerformanceMark( +export async function withAsyncPerfMeasurements( markName: string, callback: () => Promise, + onComplete?: number => void, ): Promise { + const start = now(); if (__PERFORMANCE_PROFILE__) { mark(markName); - const result = await callback(); + } + const result = await callback(); + + if (__PERFORMANCE_PROFILE__) { measure(markName); - return result; } - return callback(); + + if (onComplete != null) { + const duration = now() - start; + onComplete(duration); + } + + return result; } -export function withSyncPerformanceMark( +export function withSyncPerfMeasurements( markName: string, callback: () => TReturn, + onComplete?: number => void, ): TReturn { + const start = now(); if (__PERFORMANCE_PROFILE__) { mark(markName); - const result = callback(); + } + const result = callback(); + + if (__PERFORMANCE_PROFILE__) { measure(markName); - return result; } - return callback(); + + if (onComplete != null) { + const duration = now() - start; + onComplete(duration); + } + + return result; } -export function withCallbackPerformanceMark( +export function withCallbackPerfMeasurements( markName: string, - callback: (done: () => void) => TReturn, + callback: (done: (...args: TArgs[]) => void) => TReturn, + onComplete?: (number, ...args: TArgs[]) => void, ): TReturn { + const start = now(); if (__PERFORMANCE_PROFILE__) { mark(markName); - const done = () => { - measure(markName); - }; - return callback(done); } - return callback(() => {}); -} - -export async function measureAsyncDuration( - callback: () => Promise, -): Promise<[number, TReturn]> { - const start = now(); - const result = await callback(); - const duration = now() - start; - return [duration, result]; -} -export function measureSyncDuration( - callback: () => TReturn, -): [number, TReturn] { - const start = now(); - const result = callback(); - const duration = now() - start; - return [duration, result]; -} + const done = (...args) => { + if (__PERFORMANCE_PROFILE__) { + measure(markName); + } -export function measureCallbackDuration( - callback: (done: () => number) => TReturn, -): TReturn { - const start = now(); - const done = () => { - const duration = now() - start; - return duration; + if (onComplete != null) { + const duration = now() - start; + onComplete(duration, ...args); + } }; return callback(done); } diff --git a/packages/react-devtools-shared/src/hookNamesCache.js b/packages/react-devtools-shared/src/hookNamesCache.js index 1f5a834fd84..9a045f853fd 100644 --- a/packages/react-devtools-shared/src/hookNamesCache.js +++ b/packages/react-devtools-shared/src/hookNamesCache.js @@ -18,7 +18,7 @@ import type { } from 'react-devtools-shared/src/types'; import type {HookSource} from 'react-debug-tools/src/ReactDebugHooks'; import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext'; -import {measureCallbackDuration} from './PerformanceLoggingUtils'; +import {withCallbackPerfMeasurements} from './PerformanceLoggingUtils'; import {logEvent} from './Logger'; const TIMEOUT = 30000; @@ -96,11 +96,7 @@ export function loadHookNames( let timeoutID; - const wake = ( - resolution: 'success' | 'error' | 'timeout', - hookNames: HookNames | null, - durationMs: number, - ) => { + const wake = () => { if (timeoutID) { clearTimeout(timeoutID); timeoutID = null; @@ -109,14 +105,22 @@ export function loadHookNames( // This assumes they won't throw. callbacks.forEach(callback => callback()); callbacks.clear(); + }; + const handleLoadComplete = ( + durationMs: number, + args: {| + resolution: 'success' | 'error' | 'timeout', + hookNames: HookNames | null, + |}, + ): void => { // Log duration for parsing hook names logEvent({ - name: 'parseHookNames', + name: 'loadHookNames', displayName: element.displayName, - numberOfHooks: hookNames?.size ?? null, + numberOfHooks: args.hookNames?.size ?? null, durationMs, - resolution, + resolution: args.resolution, }); }; @@ -127,65 +131,72 @@ export function loadHookNames( let didTimeout = false; - measureCallbackDuration(done => { - loadHookNamesFunction(hooksTree, fetchFileWithCaching).then( - function onSuccess(hookNames) { - if (didTimeout) { - return; - } - + withCallbackPerfMeasurements( + 'loadHookNames', + done => { + loadHookNamesFunction(hooksTree, fetchFileWithCaching).then( + function onSuccess(hookNames) { + if (didTimeout) { + return; + } + + if (__DEBUG__) { + console.log('[hookNamesCache] onSuccess() hookNames:', hookNames); + } + + if (hookNames) { + const resolvedRecord = ((newRecord: any): ResolvedRecord); + resolvedRecord.status = Resolved; + resolvedRecord.value = hookNames; + } else { + const notFoundRecord = ((newRecord: any): RejectedRecord); + notFoundRecord.status = Rejected; + notFoundRecord.value = null; + } + + done({resolution: 'success', hookNames}); + wake(); + }, + function onError(error) { + if (didTimeout) { + return; + } + + if (__DEBUG__) { + console.log('[hookNamesCache] onError()'); + } + + console.error(error); + + const thrownRecord = ((newRecord: any): RejectedRecord); + thrownRecord.status = Rejected; + thrownRecord.value = null; + + done({resolution: 'error', hookNames: null}); + wake(); + }, + ); + + // Eventually timeout and stop trying to load names. + timeoutID = setTimeout(function onTimeout() { if (__DEBUG__) { - console.log('[hookNamesCache] onSuccess() hookNames:', hookNames); + console.log('[hookNamesCache] onTimeout()'); } - if (hookNames) { - const resolvedRecord = ((newRecord: any): ResolvedRecord); - resolvedRecord.status = Resolved; - resolvedRecord.value = hookNames; - } else { - const notFoundRecord = ((newRecord: any): RejectedRecord); - notFoundRecord.status = Rejected; - notFoundRecord.value = null; - } - - wake('success', hookNames, done()); - }, - function onError(error) { - if (didTimeout) { - return; - } + timeoutID = null; - if (__DEBUG__) { - console.log('[hookNamesCache] onError()'); - } + didTimeout = true; - console.error(error); + const timedoutRecord = ((newRecord: any): RejectedRecord); + timedoutRecord.status = Rejected; + timedoutRecord.value = null; - const thrownRecord = ((newRecord: any): RejectedRecord); - thrownRecord.status = Rejected; - thrownRecord.value = null; - - wake('error', null, done()); - }, - ); - - // Eventually timeout and stop trying to load names. - timeoutID = setTimeout(function onTimeout() { - if (__DEBUG__) { - console.log('[hookNamesCache] onTimeout()'); - } - - timeoutID = null; - - didTimeout = true; - - const timedoutRecord = ((newRecord: any): RejectedRecord); - timedoutRecord.status = Rejected; - timedoutRecord.value = null; - - wake('timeout', null, done()); - }, TIMEOUT); - }); + done({resolution: 'timeout', hookNames: null}); + wake(); + }, TIMEOUT); + }, + handleLoadComplete, + ); map.set(element, record); } diff --git a/packages/react-devtools-shared/src/hooks/astUtils.js b/packages/react-devtools-shared/src/hooks/astUtils.js index 1c669022db2..9a240592056 100644 --- a/packages/react-devtools-shared/src/hooks/astUtils.js +++ b/packages/react-devtools-shared/src/hooks/astUtils.js @@ -7,7 +7,7 @@ * @flow */ -import {withSyncPerformanceMark} from 'react-devtools-shared/src/PerformanceLoggingUtils'; +import {withSyncPerfMeasurements} from 'react-devtools-shared/src/PerformanceLoggingUtils'; import traverse, {NodePath, Node} from '@babel/traverse'; import {File} from '@babel/types'; @@ -132,7 +132,7 @@ export function getHookName( originalSourceLineNumber: number, originalSourceColumnNumber: number, ): string | null { - const hooksFromAST = withSyncPerformanceMark( + const hooksFromAST = withSyncPerfMeasurements( 'getPotentialHookDeclarationsFromAST(originalSourceAST)', () => getPotentialHookDeclarationsFromAST(originalSourceAST), ); @@ -176,7 +176,7 @@ export function getHookName( // nodesAssociatedWithReactHookASTNode could directly be used to obtain the hook variable name // depending on the type of potentialReactHookASTNode try { - const nodesAssociatedWithReactHookASTNode = withSyncPerformanceMark( + const nodesAssociatedWithReactHookASTNode = withSyncPerfMeasurements( 'getFilteredHookASTNodes()', () => getFilteredHookASTNodes( @@ -186,7 +186,7 @@ export function getHookName( ), ); - const name = withSyncPerformanceMark('getHookNameFromNode()', () => + const name = withSyncPerfMeasurements('getHookNameFromNode()', () => getHookNameFromNode( hook, nodesAssociatedWithReactHookASTNode, @@ -297,7 +297,7 @@ function getHookVariableName( function getPotentialHookDeclarationsFromAST(sourceAST: File): NodePath[] { const potentialHooksFound: NodePath[] = []; - withSyncPerformanceMark('traverse(sourceAST)', () => + withSyncPerfMeasurements('traverse(sourceAST)', () => traverse(sourceAST, { enter(path) { if (path.isVariableDeclarator() && isPotentialHookDeclaration(path)) { diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/index.js b/packages/react-devtools-shared/src/hooks/parseHookNames/index.js index f65b2562bfa..0b5595268b6 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/index.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/index.js @@ -12,7 +12,7 @@ import type {HooksNode, HooksTree} from 'react-debug-tools/src/ReactDebugHooks'; import type {HookNames} from 'react-devtools-shared/src/types'; import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/views/Components/FetchFileWithCachingContext'; -import {withAsyncPerformanceMark} from 'react-devtools-shared/src/PerformanceLoggingUtils'; +import {withAsyncPerfMeasurements} from 'react-devtools-shared/src/PerformanceLoggingUtils'; import WorkerizedParseSourceAndMetadata from './parseSourceAndMetadata.worker'; import typeof * as ParseSourceAndMetadataModule from './parseSourceAndMetadata'; import {flattenHooksList, loadSourceAndMetadata} from './loadSourceAndMetadata'; @@ -37,7 +37,7 @@ export async function parseHookNames( hooksTree: HooksTree, fetchFileWithCaching: FetchFileWithCaching | null, ): Promise { - return withAsyncPerformanceMark('parseHookNames', async () => { + return withAsyncPerfMeasurements('parseHookNames', async () => { const hooksList = flattenHooksList(hooksTree); if (hooksList.length === 0) { // This component tree contains no named hooks. diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js b/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js index 97959517717..640e916a09f 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js @@ -49,9 +49,9 @@ import {__DEBUG__} from 'react-devtools-shared/src/constants'; import {getHookSourceLocationKey} from 'react-devtools-shared/src/hookNamesCache'; import {sourceMapIncludesSource} from '../SourceMapUtils'; import { - withAsyncPerformanceMark, - withCallbackPerformanceMark, - withSyncPerformanceMark, + withAsyncPerfMeasurements, + withCallbackPerfMeasurements, + withSyncPerfMeasurements, } from 'react-devtools-shared/src/PerformanceLoggingUtils'; import type { @@ -98,17 +98,17 @@ export async function loadSourceAndMetadata( hooksList: HooksList, fetchFileWithCaching: FetchFileWithCaching | null, ): Promise { - return withAsyncPerformanceMark('loadSourceAndMetadata()', async () => { - const locationKeyToHookSourceAndMetadata = withSyncPerformanceMark( + return withAsyncPerfMeasurements('loadSourceAndMetadata()', async () => { + const locationKeyToHookSourceAndMetadata = withSyncPerfMeasurements( 'initializeHookSourceAndMetadata', () => initializeHookSourceAndMetadata(hooksList), ); - await withAsyncPerformanceMark('loadSourceFiles()', () => + await withAsyncPerfMeasurements('loadSourceFiles()', () => loadSourceFiles(locationKeyToHookSourceAndMetadata, fetchFileWithCaching), ); - await withAsyncPerformanceMark('extractAndLoadSourceMapJSON()', () => + await withAsyncPerfMeasurements('extractAndLoadSourceMapJSON()', () => extractAndLoadSourceMapJSON(locationKeyToHookSourceAndMetadata), ); @@ -157,7 +157,7 @@ function extractAndLoadSourceMapJSON( // TODO (named hooks) If this RegExp search is slow, we could try breaking it up // first using an indexOf(' sourceMappingURL=') to find the start of the comment // (probably at the end of the file) and then running the RegExp on the remaining substring. - let sourceMappingURLMatch = withSyncPerformanceMark( + let sourceMappingURLMatch = withSyncPerfMeasurements( 'sourceMapRegex.exec(runtimeSourceCode)', () => sourceMapRegex.exec(runtimeSourceCode), ); @@ -185,12 +185,12 @@ function extractAndLoadSourceMapJSON( const trimmed = ((sourceMappingURL.match( /base64,([a-zA-Z0-9+\/=]+)/, ): any): Array)[1]; - const decoded = withSyncPerformanceMark( + const decoded = withSyncPerfMeasurements( 'decodeBase64String()', () => decodeBase64String(trimmed), ); - const sourceMapJSON = withSyncPerformanceMark( + const sourceMapJSON = withSyncPerfMeasurements( 'JSON.parse(decoded)', () => JSON.parse(decoded), ); @@ -227,7 +227,7 @@ function extractAndLoadSourceMapJSON( } // If the first source map we found wasn't a match, check for more. - sourceMappingURLMatch = withSyncPerformanceMark( + sourceMappingURLMatch = withSyncPerfMeasurements( 'sourceMapRegex.exec(runtimeSourceCode)', () => sourceMapRegex.exec(runtimeSourceCode), ); @@ -266,7 +266,7 @@ function extractAndLoadSourceMapJSON( dedupedFetchPromises.get(url) || fetchFile(url).then( sourceMapContents => { - const sourceMapJSON = withSyncPerformanceMark( + const sourceMapJSON = withSyncPerfMeasurements( 'JSON.parse(sourceMapContents)', () => JSON.parse(sourceMapContents), ); @@ -316,7 +316,7 @@ function fetchFile( url: string, markName?: string = 'fetchFile', ): Promise { - return withCallbackPerformanceMark(`${markName}("${url}")`, done => { + return withCallbackPerfMeasurements(`${markName}("${url}")`, done => { return new Promise((resolve, reject) => { fetch(url, FETCH_OPTIONS).then( response => { @@ -376,7 +376,7 @@ export function hasNamedHooks(hooksTree: HooksTree): boolean { export function flattenHooksList(hooksTree: HooksTree): HooksList { const hooksList: HooksList = []; - withSyncPerformanceMark('flattenHooksList()', () => { + withSyncPerfMeasurements('flattenHooksList()', () => { flattenHooksListImpl(hooksTree, hooksList); }); @@ -472,7 +472,7 @@ function loadSourceFiles( // If a helper function has been injected to fetch with caching, // use it to fetch the (already loaded) source file. fetchFileFunction = url => { - return withAsyncPerformanceMark( + return withAsyncPerfMeasurements( `fetchFileWithCaching("${url}")`, () => { return ((fetchFileWithCaching: any): FetchFileWithCaching)(url); diff --git a/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js b/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js index f9c477ac9ad..b6c069d0dcd 100644 --- a/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js +++ b/packages/react-devtools-shared/src/hooks/parseHookNames/parseSourceAndMetadata.js @@ -19,8 +19,8 @@ import {__DEBUG__} from 'react-devtools-shared/src/constants'; import {getHookSourceLocationKey} from 'react-devtools-shared/src/hookNamesCache'; import {SourceMapMetadataConsumer} from '../SourceMapMetadataConsumer'; import { - withAsyncPerformanceMark, - withSyncPerformanceMark, + withAsyncPerfMeasurements, + withSyncPerfMeasurements, } from 'react-devtools-shared/src/PerformanceLoggingUtils'; import type { @@ -106,27 +106,27 @@ export async function parseSourceAndMetadata( hooksList: HooksList, locationKeyToHookSourceAndMetadata: LocationKeyToHookSourceAndMetadata, ): Promise { - return withAsyncPerformanceMark('parseSourceAndMetadata()', async () => { - const locationKeyToHookParsedMetadata = withSyncPerformanceMark( + return withAsyncPerfMeasurements('parseSourceAndMetadata()', async () => { + const locationKeyToHookParsedMetadata = withSyncPerfMeasurements( 'initializeHookParsedMetadata', () => initializeHookParsedMetadata(locationKeyToHookSourceAndMetadata), ); - withSyncPerformanceMark('parseSourceMaps', () => + withSyncPerfMeasurements('parseSourceMaps', () => parseSourceMaps( locationKeyToHookSourceAndMetadata, locationKeyToHookParsedMetadata, ), ); - withSyncPerformanceMark('parseSourceAST()', () => + withSyncPerfMeasurements('parseSourceAST()', () => parseSourceAST( locationKeyToHookSourceAndMetadata, locationKeyToHookParsedMetadata, ), ); - return withSyncPerformanceMark('findHookNames()', () => + return withSyncPerfMeasurements('findHookNames()', () => findHookNames(hooksList, locationKeyToHookParsedMetadata), ); }); @@ -174,7 +174,7 @@ function findHookNames( let name; const {metadataConsumer} = hookParsedMetadata; if (metadataConsumer != null) { - name = withSyncPerformanceMark('metadataConsumer.hookNameFor()', () => + name = withSyncPerfMeasurements('metadataConsumer.hookNameFor()', () => metadataConsumer.hookNameFor({ line: originalSourceLineNumber, column: originalSourceColumnNumber, @@ -184,7 +184,7 @@ function findHookNames( } if (name == null) { - name = withSyncPerformanceMark('getHookName()', () => + name = withSyncPerfMeasurements('getHookName()', () => getHookName( hook, hookParsedMetadata.originalSourceAST, @@ -303,7 +303,7 @@ function parseSourceAST( // Now that the source map has been loaded, // extract the original source for later. // TODO (named hooks) Refactor this read, github.com/facebook/react/pull/22181 - const {column, line, source} = withSyncPerformanceMark( + const {column, line, source} = withSyncPerfMeasurements( 'sourceConsumer.originalPositionFor()', () => sourceConsumer.originalPositionFor({ @@ -329,7 +329,7 @@ function parseSourceAST( // It can be relative if the source map specifies it that way, // but we use it as a cache key across different source maps and there can be collisions. originalSourceURL = (source: string); - originalSourceCode = withSyncPerformanceMark( + originalSourceCode = withSyncPerfMeasurements( 'sourceConsumer.sourceContentFor()', () => (sourceConsumer.sourceContentFor(source, true): string), ); @@ -401,7 +401,7 @@ function parseSourceAST( // TODO (named hooks) This is probably where we should check max source length, // rather than in loadSourceAndMetatada -> loadSourceFiles(). - const originalSourceAST = withSyncPerformanceMark( + const originalSourceAST = withSyncPerfMeasurements( '[@babel/parser] parse(originalSourceCode)', () => parse(originalSourceCode, { @@ -441,11 +441,11 @@ function parseSourceMaps( const sourceMapJSON = hookSourceAndMetadata.sourceMapJSON; if (sourceMapJSON != null) { - hookParsedMetadata.metadataConsumer = withSyncPerformanceMark( + hookParsedMetadata.metadataConsumer = withSyncPerfMeasurements( 'new SourceMapMetadataConsumer(sourceMapJSON)', () => new SourceMapMetadataConsumer(sourceMapJSON), ); - hookParsedMetadata.sourceConsumer = withSyncPerformanceMark( + hookParsedMetadata.sourceConsumer = withSyncPerfMeasurements( 'new SourceMapConsumer(sourceMapJSON)', () => new SourceMapConsumer(sourceMapJSON), ); From c667cb6dce30832302cdc5dd8cfb4cf915ee4445 Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Mon, 13 Sep 2021 17:04:37 -0400 Subject: [PATCH 4/7] Missed update --- .../react-devtools-shared/src/PerformanceLoggingUtils.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-devtools-shared/src/PerformanceLoggingUtils.js b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js index f05c28240f5..7eabdd1bcc4 100644 --- a/packages/react-devtools-shared/src/PerformanceLoggingUtils.js +++ b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js @@ -85,22 +85,22 @@ export function withSyncPerfMeasurements( export function withCallbackPerfMeasurements( markName: string, - callback: (done: (...args: TArgs[]) => void) => TReturn, - onComplete?: (number, ...args: TArgs[]) => void, + callback: (done: (args: TArgs) => void) => TReturn, + onComplete?: (number, args: TArgs) => void, ): TReturn { const start = now(); if (__PERFORMANCE_PROFILE__) { mark(markName); } - const done = (...args) => { + const done = args => { if (__PERFORMANCE_PROFILE__) { measure(markName); } if (onComplete != null) { const duration = now() - start; - onComplete(duration, ...args); + onComplete(duration, args); } }; return callback(done); From 7e60e50dcaa1850c72381467dbd054f2f9bb24ed Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Mon, 13 Sep 2021 17:06:20 -0400 Subject: [PATCH 5/7] Make it clearer that LogEvent should be a union of event types --- packages/react-devtools-shared/src/Logger.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/Logger.js b/packages/react-devtools-shared/src/Logger.js index 5155d5e5f4d..d3fca1a025a 100644 --- a/packages/react-devtools-shared/src/Logger.js +++ b/packages/react-devtools-shared/src/Logger.js @@ -9,7 +9,7 @@ import {enableLogger} from 'react-devtools-feature-flags'; -export type LogEvent = {| +type LoadHookNamesEvent = {| +name: 'loadHookNames', +displayName: string | null, +numberOfHooks: number | null, @@ -17,6 +17,10 @@ export type LogEvent = {| +resolution: 'success' | 'error' | 'timeout', |}; +// prettier-ignore +export type LogEvent = + | LoadHookNamesEvent; + export type LogFunction = LogEvent => void; let loggers = []; From eb46d6f259eac4d1a68cca4089707bc743891655 Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Mon, 13 Sep 2021 17:07:38 -0400 Subject: [PATCH 6/7] Add type annotation for loggers array --- packages/react-devtools-shared/src/Logger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/Logger.js b/packages/react-devtools-shared/src/Logger.js index d3fca1a025a..57e1164a8cd 100644 --- a/packages/react-devtools-shared/src/Logger.js +++ b/packages/react-devtools-shared/src/Logger.js @@ -23,7 +23,7 @@ export type LogEvent = export type LogFunction = LogEvent => void; -let loggers = []; +let loggers: Array = []; export const logEvent: LogFunction = enableLogger === true ? function logEvent(event: LogEvent): void { From 665af1fff51707e219932840bf4e9213b6d70c7f Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Tue, 14 Sep 2021 10:27:59 -0400 Subject: [PATCH 7/7] Remove args to done + other comments --- packages/react-devtools-shared/src/Logger.js | 2 +- .../src/PerformanceLoggingUtils.js | 10 +++---- .../config/DevToolsFeatureFlags.core-fb.js | 1 - .../config/DevToolsFeatureFlags.core-oss.js | 1 - .../config/DevToolsFeatureFlags.default.js | 1 - .../DevToolsFeatureFlags.extension-fb.js | 1 - .../DevToolsFeatureFlags.extension-oss.js | 1 - .../src/hookNamesCache.js | 27 +++++++++---------- 8 files changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/react-devtools-shared/src/Logger.js b/packages/react-devtools-shared/src/Logger.js index 57e1164a8cd..0ce2afb3b3c 100644 --- a/packages/react-devtools-shared/src/Logger.js +++ b/packages/react-devtools-shared/src/Logger.js @@ -14,7 +14,7 @@ type LoadHookNamesEvent = {| +displayName: string | null, +numberOfHooks: number | null, +durationMs: number, - +resolution: 'success' | 'error' | 'timeout', + +resolution: 'success' | 'error' | 'timeout' | 'unknown', |}; // prettier-ignore diff --git a/packages/react-devtools-shared/src/PerformanceLoggingUtils.js b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js index 7eabdd1bcc4..29d81bba911 100644 --- a/packages/react-devtools-shared/src/PerformanceLoggingUtils.js +++ b/packages/react-devtools-shared/src/PerformanceLoggingUtils.js @@ -83,24 +83,24 @@ export function withSyncPerfMeasurements( return result; } -export function withCallbackPerfMeasurements( +export function withCallbackPerfMeasurements( markName: string, - callback: (done: (args: TArgs) => void) => TReturn, - onComplete?: (number, args: TArgs) => void, + callback: (done: () => void) => TReturn, + onComplete?: number => void, ): TReturn { const start = now(); if (__PERFORMANCE_PROFILE__) { mark(markName); } - const done = args => { + const done = () => { if (__PERFORMANCE_PROFILE__) { measure(markName); } if (onComplete != null) { const duration = now() - start; - onComplete(duration, args); + onComplete(duration); } }; return callback(done); diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js index 1dc2fb09fd6..b6b7a1d0cd3 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-fb.js @@ -17,7 +17,6 @@ export const enableProfilerChangedHookIndices = true; export const isInternalFacebookBuild = true; export const enableNamedHooksFeature = false; export const enableLogger = false; - export const consoleManagedByDevToolsDuringStrictMode = false; /************************************************************************ diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js index 18a40de7768..6eb0f71ef9f 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.core-oss.js @@ -17,7 +17,6 @@ export const enableProfilerChangedHookIndices = false; export const isInternalFacebookBuild = false; export const enableNamedHooksFeature = false; export const enableLogger = false; - export const consoleManagedByDevToolsDuringStrictMode = false; /************************************************************************ diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js index d8ba0b07071..bc495619cf6 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.default.js @@ -17,5 +17,4 @@ export const enableProfilerChangedHookIndices = false; export const isInternalFacebookBuild = false; export const enableNamedHooksFeature = true; export const enableLogger = false; - export const consoleManagedByDevToolsDuringStrictMode = true; diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js index f85ec064fa1..51fe2ed6abc 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-fb.js @@ -17,7 +17,6 @@ export const enableProfilerChangedHookIndices = true; export const isInternalFacebookBuild = true; export const enableNamedHooksFeature = true; export const enableLogger = false; - export const consoleManagedByDevToolsDuringStrictMode = true; /************************************************************************ diff --git a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js index 609cc8263da..53466bf84bb 100644 --- a/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js +++ b/packages/react-devtools-shared/src/config/DevToolsFeatureFlags.extension-oss.js @@ -17,7 +17,6 @@ export const enableProfilerChangedHookIndices = true; export const isInternalFacebookBuild = false; export const enableNamedHooksFeature = true; export const enableLogger = false; - export const consoleManagedByDevToolsDuringStrictMode = true; /************************************************************************ diff --git a/packages/react-devtools-shared/src/hookNamesCache.js b/packages/react-devtools-shared/src/hookNamesCache.js index 9a045f853fd..32179f9de1c 100644 --- a/packages/react-devtools-shared/src/hookNamesCache.js +++ b/packages/react-devtools-shared/src/hookNamesCache.js @@ -95,6 +95,9 @@ export function loadHookNames( }; let timeoutID; + let didTimeout = false; + let resolution = 'unknown'; + let resolvedHookNames: HookNames | null = null; const wake = () => { if (timeoutID) { @@ -107,20 +110,14 @@ export function loadHookNames( callbacks.clear(); }; - const handleLoadComplete = ( - durationMs: number, - args: {| - resolution: 'success' | 'error' | 'timeout', - hookNames: HookNames | null, - |}, - ): void => { + const handleLoadComplete = (durationMs: number): void => { // Log duration for parsing hook names logEvent({ name: 'loadHookNames', displayName: element.displayName, - numberOfHooks: args.hookNames?.size ?? null, + numberOfHooks: resolvedHookNames?.size ?? null, durationMs, - resolution: args.resolution, + resolution, }); }; @@ -129,8 +126,6 @@ export function loadHookNames( value: wakeable, }); - let didTimeout = false; - withCallbackPerfMeasurements( 'loadHookNames', done => { @@ -154,7 +149,9 @@ export function loadHookNames( notFoundRecord.value = null; } - done({resolution: 'success', hookNames}); + resolution = 'success'; + resolvedHookNames = hookNames; + done(); wake(); }, function onError(error) { @@ -172,7 +169,8 @@ export function loadHookNames( thrownRecord.status = Rejected; thrownRecord.value = null; - done({resolution: 'error', hookNames: null}); + resolution = 'error'; + done(); wake(); }, ); @@ -191,7 +189,8 @@ export function loadHookNames( timedoutRecord.status = Rejected; timedoutRecord.value = null; - done({resolution: 'timeout', hookNames: null}); + resolution = 'timeout'; + done(); wake(); }, TIMEOUT); },