File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -33,17 +33,30 @@ export * from './types';
3333
3434let host : PluginHost | null = null ;
3535
36+ /**
37+ * Debug: dump every scope-based plugin's live side-effect ledger. From the
38+ * page console (extension context in DevTools):
39+ * document.dispatchEvent(new Event('gv:debug:pluginScopes'))
40+ */
41+ export const PLUGIN_SCOPES_DEBUG_EVENT = 'gv:debug:pluginScopes' ;
42+
43+ const dumpScopeLedgers = ( ) : void => {
44+ logger . info ( 'Plugin scope ledgers' , host ?. getScopeLedgers ( ) ?? { } ) ;
45+ } ;
46+
3647export function startPluginHost ( ) : ( ) => void {
3748 if ( host ) return ( ) => { } ;
3849 try {
3950 host = new PluginHost ( ) ;
4051 void host . start ( ) ;
52+ document . addEventListener ( PLUGIN_SCOPES_DEBUG_EVENT , dumpScopeLedgers ) ;
4153 } catch ( error ) {
4254 if ( ! isExtensionContextInvalidatedError ( error ) ) {
4355 logger . error ( 'startPluginHost failed' , { error : String ( error ) } ) ;
4456 }
4557 }
4658 return ( ) => {
59+ document . removeEventListener ( PLUGIN_SCOPES_DEBUG_EVENT , dumpScopeLedgers ) ;
4760 host ?. stop ( ) ;
4861 host = null ;
4962 } ;
Original file line number Diff line number Diff line change @@ -83,6 +83,11 @@ export class PluginHost {
8383 return this . adapter ;
8484 }
8585
86+ /** Live side-effect ledgers of scope-based plugins, keyed by plugin id. */
87+ getScopeLedgers ( ) : Record < string , readonly string [ ] > {
88+ return this . engine ?. getScopeLedgers ( ) ?? { } ;
89+ }
90+
8691 async start ( ) : Promise < void > {
8792 if ( this . started ) return ;
8893 this . started = true ;
Original file line number Diff line number Diff line change @@ -168,6 +168,21 @@ describe('DeclarativeEngine', () => {
168168 expect ( activate ) . toHaveBeenCalledOnce ( ) ;
169169 } ) ;
170170
171+ it ( 'getScopeLedgers reports live effect labels per scope-based plugin' , ( ) => {
172+ registerNativeHandler ( 'test.scoped-ledger' , {
173+ activate : ( scope : PluginScope ) => {
174+ scope . effect ( ( ) => ( ) => { } , 'my-effect' ) ;
175+ } ,
176+ } ) ;
177+ const engine = new DeclarativeEngine ( { doc : document } ) ;
178+ engine . mount ( makeManifest ( { } , 'test.scoped-ledger' ) ) ;
179+
180+ expect ( engine . getScopeLedgers ( ) ) . toEqual ( { 'test.scoped-ledger' : [ 'my-effect' ] } ) ;
181+
182+ engine . unmount ( 'test.scoped-ledger' ) ;
183+ expect ( engine . getScopeLedgers ( ) ) . toEqual ( { } ) ;
184+ } ) ;
185+
171186 it ( 'a throwing activation rolls back what it already registered' , async ( ) => {
172187 const registered = vi . fn ( ) ;
173188 registerNativeHandler ( 'test.scoped-throw' , {
Original file line number Diff line number Diff line change @@ -97,6 +97,15 @@ export class DeclarativeEngine {
9797 return this . active . size ;
9898 }
9999
100+ /** Live side-effect ledger per scope-based plugin — debug/leak inspection. */
101+ getScopeLedgers ( ) : Record < string , readonly string [ ] > {
102+ const ledgers : Record < string , readonly string [ ] > = { } ;
103+ for ( const [ id , entry ] of this . active ) {
104+ if ( entry . scope ) ledgers [ id ] = entry . scope . getEffects ( ) ;
105+ }
106+ return ledgers ;
107+ }
108+
100109 isActive ( id : string ) : boolean {
101110 return this . active . has ( id ) ;
102111 }
You can’t perform that action at this time.
0 commit comments