From 223d153bb791eec59cbb03cfc28d2a4061f2c5e0 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 b0408e642fe06..4b56064cc2780 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 = /^(.*)[\\\/]/;