@@ -285,29 +285,79 @@ export class Views implements Disposable {
285
285
] ;
286
286
}
287
287
288
+ private readonly _scmGroupedViewProxyCache = new Map <
289
+ GroupableTreeViewTypes ,
290
+ TreeViewByType [ GroupableTreeViewTypes ]
291
+ > ( ) ;
292
+
288
293
private getScmGroupedView < T extends GroupableTreeViewTypes > ( type : T ) : TreeViewByType [ T ] {
289
- // eslint-disable-next-line @typescript-eslint/no- this-alias
290
- const self = this ;
294
+ let proxy = this . _scmGroupedViewProxyCache . get ( type ) as TreeViewByType [ T ] | undefined ;
295
+ if ( proxy != null ) return proxy ;
291
296
292
- // Use a proxy to guard against the view not existing or having been disposed
297
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
298
+ const methodCache = new Map < string | symbol , Function | undefined > ( ) ;
299
+
300
+ // Use a proxy to lazily initialize the view (guard against the view not existing or having been disposed) and cache method bindings for performance
293
301
294
302
let view : TreeViewByType [ T ] | undefined ;
295
- const proxy = new Proxy < TreeViewByType [ T ] > ( Object . create ( null ) as TreeViewByType [ T ] , {
296
- get : function ( _target , prop ) {
297
- if ( view == null || view . disposed ) {
298
- if ( self . _scmGroupedView == null ) {
299
- // Don't bother creating the view if we are just checking visibility
300
- if ( prop === 'visible' ) return false ;
301
-
302
- self . updateScmGroupedViewsRegistration ( true ) ;
303
- }
304
- view = self . _scmGroupedView ! . setView ( type ) ;
303
+ const ensureView = ( ) => {
304
+ if ( view == null || view . disposed ) {
305
+ methodCache . clear ( ) ;
306
+
307
+ if ( this . _scmGroupedView == null ) {
308
+ this . updateScmGroupedViewsRegistration ( true ) ;
305
309
}
310
+ view = this . _scmGroupedView ! . setView ( type ) ;
311
+ if ( view == null ) {
312
+ debugger ;
313
+ throw new Error ( `Unable to initialize view: ${ type } ` ) ;
314
+ }
315
+ }
316
+ return view ;
317
+ } ;
318
+
319
+ proxy = new Proxy < TreeViewByType [ T ] > ( Object . create ( null ) as TreeViewByType [ T ] , {
320
+ get : function ( _ , prop ) {
321
+ // Fast path for visibility check
322
+ if ( prop === 'visible' ) {
323
+ return view != null && ! view . disposed && view . visible ;
324
+ }
325
+
326
+ const target = ensureView ( ) ;
327
+ const value = Reflect . get ( target , prop , target ) ;
306
328
307
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
308
- return ( view as any ) [ prop ] ;
329
+ // Fast return for non-functions
330
+ if ( typeof value !== 'function' ) return value ;
331
+
332
+ // Check method cache
333
+ let method = methodCache . get ( prop ) ;
334
+ if ( method == null ) {
335
+ method = value . bind ( target ) ;
336
+ methodCache . set ( prop , method ) ;
337
+ }
338
+ return method ;
339
+ } ,
340
+ set : function ( _target , prop , value , receiver ) {
341
+ return Reflect . set ( ensureView ( ) , prop , value , receiver ) ;
342
+ } ,
343
+ has : function ( _target , prop ) {
344
+ return Reflect . has ( ensureView ( ) , prop ) ;
345
+ } ,
346
+ getOwnPropertyDescriptor : function ( _target , prop ) {
347
+ return Reflect . getOwnPropertyDescriptor ( ensureView ( ) , prop ) ;
348
+ } ,
349
+ defineProperty : function ( _target , prop , descriptor ) {
350
+ return Reflect . defineProperty ( ensureView ( ) , prop , descriptor ) ;
351
+ } ,
352
+ deleteProperty : function ( _target , prop ) {
353
+ return Reflect . deleteProperty ( ensureView ( ) , prop ) ;
354
+ } ,
355
+ ownKeys : function ( _target ) {
356
+ return Reflect . ownKeys ( ensureView ( ) ) ;
309
357
} ,
310
358
} ) ;
359
+
360
+ this . _scmGroupedViewProxyCache . set ( type , proxy ) ;
311
361
return proxy ;
312
362
}
313
363
0 commit comments