11// @flow
22
3- import type { ReactRenderer } from './types' ;
3+ import type { Fiber , ReactRenderer } from './types' ;
44
55let disabled : boolean = false ;
66
@@ -12,24 +12,79 @@ export function enable(): void {
1212 disabled = false ;
1313}
1414
15- export function patch ( { debugCurrentFrame } : ReactRenderer ) : void {
15+ export function patch (
16+ { getCurrentFiber } : ReactRenderer ,
17+ getDisplayNameForFiber : ( fiber : Fiber ) = > string | null
18+ ) : void {
1619 for ( let method in console ) {
1720 const originalMethod = console [ method ] ;
1821 const appendComponentStack =
19- debugCurrentFrame != null &&
22+ typeof getCurrentFiber === 'function' &&
2023 ( method === 'error' || method === 'warn' || method === 'trace' ) ;
2124 try {
2225 // $FlowFixMe property error|warn is not writable.
2326 console [ method ] = ( ...args ) => {
2427 if ( disabled ) return ;
28+
2529 if ( appendComponentStack ) {
26- const componentStack = debugCurrentFrame . getStackAddendum ( ) ;
27- if ( componentStack ) {
28- args . push ( componentStack ) ;
30+ // $FlowFixMe We know getCurrentFiber() is a function if appendComponentStack is true.
31+ let current : ?Fiber = getCurrentFiber ( ) ;
32+ let ownerStack : string = '' ;
33+ while ( current != null ) {
34+ const name = getDisplayNameForFiber ( current ) ;
35+ const owner = current . _debugOwner ;
36+ const ownerName =
37+ owner != null ? getDisplayNameForFiber ( owner ) : null ;
38+
39+ ownerStack += describeComponentFrame (
40+ name ,
41+ current . _debugSource ,
42+ ownerName
43+ ) ;
44+
45+ current = owner ;
46+ }
47+
48+ if ( ownerStack !== '' ) {
49+ args . push ( ownerStack ) ;
2950 }
3051 }
3152 originalMethod ( ...args ) ;
3253 } ;
3354 } catch ( error ) { }
3455 }
3556}
57+
58+ const BEFORE_SLASH_RE = / ^ ( . * ) [ \\/ ] / ;
59+
60+ // Copied from React repo:
61+ // https://github.com/facebook/react/blob/master/packages/shared/describeComponentFrame.js
62+ function describeComponentFrame (
63+ name : null | string ,
64+ source : any ,
65+ ownerName : null | string
66+ ) {
67+ let sourceInfo = '' ;
68+ if ( source ) {
69+ let path = source . fileName ;
70+ let fileName = path . replace ( BEFORE_SLASH_RE , '' ) ;
71+ if ( __DEV__ ) {
72+ // In DEV, include code for a common special case:
73+ // prefer "folder/index.js" instead of just "index.js".
74+ if ( / ^ i n d e x \. / . test ( fileName ) ) {
75+ const match = path . match ( BEFORE_SLASH_RE ) ;
76+ if ( match ) {
77+ const pathBeforeSlash = match [ 1 ] ;
78+ if ( pathBeforeSlash ) {
79+ const folderName = pathBeforeSlash . replace ( BEFORE_SLASH_RE , '' ) ;
80+ fileName = folderName + '/' + fileName ;
81+ }
82+ }
83+ }
84+ }
85+ sourceInfo = ' (at ' + fileName + ':' + source . lineNumber + ')' ;
86+ } else if ( ownerName ) {
87+ sourceInfo = ' (created by ' + ownerName + ')' ;
88+ }
89+ return '\n in ' + ( name || 'Unknown' ) + sourceInfo ;
90+ }
0 commit comments