File tree Expand file tree Collapse file tree 3 files changed +29
-16
lines changed
packages/plugin-sqlite-database-integration/integrations/query-monitor Expand file tree Collapse file tree 3 files changed +29
-16
lines changed Original file line number Diff line number Diff line change @@ -77,11 +77,11 @@ public function output() {
7777 return ;
7878 }
7979
80- // Re-index: QM's collector may skip some $wpdb->queries entries
81- // (e.g., admin bar queries), so we need to map our indices to
82- // match the rows QM actually renders. QM iterates $wpdb->queries
83- // sequentially and skips entries containing 'wp_admin_bar' in the
84- // stack trace. We replicate that filtering here .
80+ // Re-index: QM's DB queries collector skips $wpdb->queries entries
81+ // where the stack trace contains 'wp_admin_bar'. We replicate that
82+ // filtering to align our row indices with QM's rendered rows.
83+ // See: QM_Collector_DB_Queries::process_db_object() in QM's
84+ // collectors/db_queries.php .
8585 global $ wpdb ;
8686 $ mapped = array ();
8787 $ row_index = 0 ;
@@ -97,9 +97,11 @@ public function output() {
9797 }
9898
9999 // Output JSON data for the JS module.
100+ // JSON_HEX_TAG escapes < and > to \u003C and \u003E, preventing
101+ // a literal "</script>" in query text from breaking out of the tag.
100102 printf (
101103 '<script type="application/json" id="qm-sqlite-data">%s</script> ' ,
102- wp_json_encode ( $ mapped )
104+ wp_json_encode ( $ mapped, JSON_HEX_TAG )
103105 );
104106
105107 // Output the JS module inline.
Original file line number Diff line number Diff line change 115115 injectSQLiteInfo ( shadowRoot ) ;
116116
117117 // Observe for future renders (panel switches, re-renders).
118+ // Debounce to avoid excessive work during rapid Preact re-renders.
119+ var debounceTimer ;
118120 var observer = new MutationObserver ( function ( ) {
119- injectSQLiteInfo ( shadowRoot ) ;
121+ clearTimeout ( debounceTimer ) ;
122+ debounceTimer = setTimeout ( function ( ) {
123+ injectSQLiteInfo ( shadowRoot ) ;
124+ } , 100 ) ;
120125 } ) ;
121126 observer . observe ( shadowRoot , { childList : true , subtree : true } ) ;
122127 }
128133 // detect attachShadow(), so we poll. QM's module script is deferred
129134 // and attaches the shadow root on DOMContentLoaded, which may fire
130135 // after our inline script's DOMContentLoaded handler.
136+ var pollCount = 0 ;
131137 var pollInterval = setInterval ( function ( ) {
132138 if ( container . shadowRoot ) {
133139 clearInterval ( pollInterval ) ;
134140 onShadowReady ( container . shadowRoot ) ;
141+ } else if ( ++ pollCount > 200 ) {
142+ clearInterval ( pollInterval ) ;
135143 }
136144 } , 50 ) ;
137145 }
Original file line number Diff line number Diff line change @@ -75,14 +75,17 @@ test.describe( 'Query Monitor plugin', () => {
7575 } ) . toPass ( ) ;
7676
7777 // Click the SQLite toggle button for the first query row.
78- await container . evaluate ( ( el ) => {
79- const shadow = el . shadowRoot ;
80- const toggle = shadow . querySelector ( '.qm-sqlite-toggle' ) ;
81- if ( ! toggle ) {
82- throw new Error ( 'SQLite toggle button not found' ) ;
83- }
84- toggle . click ( ) ;
85- } ) ;
78+ // The toggle is injected by a debounced MutationObserver, so retry.
79+ await expect ( async ( ) => {
80+ await container . evaluate ( ( el ) => {
81+ const shadow = el . shadowRoot ;
82+ const toggle = shadow . querySelector ( '.qm-sqlite-toggle' ) ;
83+ if ( ! toggle ) {
84+ throw new Error ( 'SQLite toggle button not found' ) ;
85+ }
86+ toggle . click ( ) ;
87+ } ) ;
88+ } ) . toPass ( ) ;
8689
8790 // Verify the SQLite query is displayed.
8891 await expect ( async ( ) => {
@@ -129,7 +132,7 @@ test.describe( 'Query Monitor plugin', () => {
129132
130133 // Check that the query is logged with SQLite information.
131134 await sqlCell . getByLabel ( 'Toggle SQLite queries' ) . click ( ) ;
132- expect (
135+ await expect (
133136 page
134137 . locator ( '.qm-sqlite-query' , {
135138 hasText :
You can’t perform that action at this time.
0 commit comments