@@ -285,29 +285,79 @@ export class Views implements Disposable {
285285 ] ;
286286 }
287287
288+ private readonly _scmGroupedViewProxyCache = new Map <
289+ GroupableTreeViewTypes ,
290+ TreeViewByType [ GroupableTreeViewTypes ]
291+ > ( ) ;
292+
288293 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 ;
291296
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
293301
294302 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 ) ;
305309 }
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 ) ;
306328
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 ( ) ) ;
309357 } ,
310358 } ) ;
359+
360+ this . _scmGroupedViewProxyCache . set ( type , proxy ) ;
311361 return proxy ;
312362 }
313363
0 commit comments