@@ -92,68 +92,85 @@ export interface Render {
9292 count : number ;
9393 forget : boolean ;
9494 changes : Array < Change > | null ;
95- unnecessary : boolean ;
95+ unnecessary : boolean | null ;
9696 didCommit : boolean ;
9797 fps : number ;
9898}
9999
100100const unstableTypes = [ 'function' , 'object' ] ;
101101
102- export const fastSerialize = ( value : unknown , depth = 0 ) => {
102+ const cache = new WeakMap < object , string > ( ) ;
103+
104+ export function fastSerialize ( value : unknown , depth = 0 ) : string {
103105 if ( depth < 0 ) return '…' ;
106+
104107 switch ( typeof value ) {
105108 case 'function' :
106109 return value . toString ( ) ;
107110 case 'string' :
108111 return value ;
112+ case 'number' :
113+ case 'boolean' :
114+ case 'undefined' :
115+ return String ( value ) ;
109116 case 'object' :
110- if ( value === null ) {
111- return 'null' ;
112- }
113- if ( Array . isArray ( value ) ) {
114- return value . length > 0 ? `[${ value . length } ]` : '[]' ;
115- }
116- if ( isValidElement ( value ) ) {
117- // attempt to extract some name from the component
118- return `<${ getDisplayName ( value . type ) ?? '' } ${
119- Object . keys ( value . props || { } ) . length
120- } >`;
121- }
122- if (
123- typeof value === 'object' &&
124- value !== null &&
125- value . constructor === Object
126- ) {
127- for ( const key in value ) {
128- if ( Object . prototype . hasOwnProperty . call ( value , key ) ) {
129- return `{${ Object . keys ( value ) . length } }` ;
130- }
131- }
132- return '{}' ;
133- }
134- // eslint-disable-next-line no-case-declarations
135- const tagString = Object . prototype . toString . call ( value ) . slice ( 8 , - 1 ) ;
136- if ( tagString === 'Object' ) {
137- const proto = Object . getPrototypeOf ( value ) ;
138- const constructor = proto ?. constructor ;
139- if ( typeof constructor === 'function' ) {
140- return `${ constructor . displayName || constructor . name || '' } {…}` ;
141- }
142- }
143- return `${ tagString } {…}` ;
117+ break ;
144118 default :
145119 return String ( value ) ;
146120 }
147- } ;
121+
122+ if ( value === null ) return 'null' ;
123+
124+ if ( cache . has ( value ) ) {
125+ return cache . get ( value ) ! ;
126+ }
127+
128+ if ( Array . isArray ( value ) ) {
129+ const str = value . length ? `[${ value . length } ]` : '[]' ;
130+ cache . set ( value , str ) ;
131+ return str ;
132+ }
133+
134+ if ( isValidElement ( value ) ) {
135+ const type = getDisplayName ( value . type ) ?? '' ;
136+ const propCount = value . props ? Object . keys ( value . props ) . length : 0 ;
137+ const str = `<${ type } ${ propCount } >` ;
138+ cache . set ( value , str ) ;
139+ return str ;
140+ }
141+
142+ if ( Object . getPrototypeOf ( value ) === Object . prototype ) {
143+ const keys = Object . keys ( value ) ;
144+ const str = keys . length ? `{${ keys . length } }` : '{}' ;
145+ cache . set ( value , str ) ;
146+ return str ;
147+ }
148+
149+ const ctor = ( value as any ) . constructor ;
150+ if ( ctor && typeof ctor === 'function' && ctor . name ) {
151+ const str = `${ ctor . name } {…}` ;
152+ cache . set ( value , str ) ;
153+ return str ;
154+ }
155+
156+ const tagString = Object . prototype . toString . call ( value ) . slice ( 8 , - 1 ) ;
157+ const str = `${ tagString } {…}` ;
158+ cache . set ( value , str ) ;
159+ return str ;
160+ }
148161
149162export const getPropsChanges = ( fiber : Fiber ) => {
150163 const changes : Array < Change > = [ ] ;
151164
152165 const prevProps = fiber . alternate ?. memoizedProps || { } ;
153166 const nextProps = fiber . memoizedProps || { } ;
154167
155- // eslint-disable-next-line prefer-object-spread
156- for ( const propName in Object . assign ( { } , prevProps , nextProps ) ) {
168+
169+ const allKeys = new Set ( [
170+ ...Object . keys ( prevProps ) ,
171+ ...Object . keys ( nextProps ) ,
172+ ] ) ;
173+ for ( const propName in allKeys ) {
157174 const prevValue = prevProps ?. [ propName ] ;
158175 const nextValue = nextProps ?. [ propName ] ;
159176
@@ -199,7 +216,6 @@ export const getStateChanges = (fiber: Fiber) => {
199216 return changes ;
200217} ;
201218
202-
203219export const getContextChanges = ( fiber : Fiber ) => {
204220 const changes : Array < Change > = [ ] ;
205221
@@ -343,7 +359,8 @@ export const createInstrumentation = (
343359 changes,
344360 time : selfTime ,
345361 forget : hasMemoCache ( fiber ) ,
346- unnecessary : isRenderUnnecessary ( fiber ) ,
362+ // only collect if the render was unnecessary 5% of the time since is isRenderUnnecessary is expensive
363+ unnecessary : Math . random ( ) < 0.05 ? isRenderUnnecessary ( fiber ) : null ,
347364 didCommit : didFiberCommit ( fiber ) ,
348365 fps,
349366 } ;
0 commit comments