From d7a16ff2d098c62f80298f6131ff1cfdd6fd259e Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 9 Apr 2020 21:36:27 -0700 Subject: [PATCH] Cache the result in DEV In DEV it's somewhat likely that we'll see many logs that add component stacks. This could be slow so we cache the results of previous components. --- packages/shared/ReactComponentStackFrame.js | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/shared/ReactComponentStackFrame.js b/packages/shared/ReactComponentStackFrame.js index 3906504caabd..db1a309807bc 100644 --- a/packages/shared/ReactComponentStackFrame.js +++ b/packages/shared/ReactComponentStackFrame.js @@ -53,6 +53,11 @@ export function describeBuiltInComponentFrame( } let reentry = false; +let componentFrameCache; +if (__DEV__) { + const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); +} export function describeNativeComponentFrame( fn: Function, @@ -63,6 +68,13 @@ export function describeNativeComponentFrame( return ''; } + if (__DEV__) { + const frame = componentFrameCache.get(fn); + if (frame !== undefined) { + return frame; + } + } + const control = Error(); reentry = true; @@ -119,7 +131,13 @@ export function describeNativeComponentFrame( if (sampleLines[s] !== controlLines[c]) { // Return the line we found. // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. - return '\n' + sampleLines[s - 1].replace(' at new ', ' at '); + const frame = '\n' + sampleLines[s - 1].replace(' at new ', ' at '); + if (__DEV__) { + if (typeof fn === 'function') { + componentFrameCache.set(fn, frame); + } + } + return frame; } } } @@ -132,7 +150,13 @@ export function describeNativeComponentFrame( } // Fallback to just using the name if we couldn't make it throw. const name = fn ? fn.displayName || fn.name : ''; - return name ? describeBuiltInComponentFrame(name) : ''; + const syntheticFrame = name ? describeBuiltInComponentFrame(name) : ''; + if (__DEV__) { + if (typeof fn === 'function') { + componentFrameCache.set(fn, syntheticFrame); + } + } + return syntheticFrame; } const BEFORE_SLASH_RE = /^(.*)[\\\/]/;