@@ -34,13 +34,20 @@ if (elem) {
3434 }
3535 } ;
3636
37- const onReady = ( ) => {
37+ let observer ;
38+
39+ function injectDebugKitIframe ( ) {
3840 if ( ! win . debugKitId ) {
3941 return ;
4042 }
43+
4144 const { body } = doc ;
4245
43- // Cannot use css text, because of CSP compatibility.
46+ // Remove the old iframe if it exists (in case of ajax swaps).
47+ if ( iframe && iframe . parentNode ) {
48+ iframe . parentNode . removeChild ( iframe ) ;
49+ }
50+
4451 iframe = doc . createElement ( 'iframe' ) ;
4552 iframe . style . position = 'fixed' ;
4653 iframe . style . bottom = 0 ;
@@ -51,24 +58,42 @@ if (elem) {
5158 iframe . style . zIndex = 99999 ;
5259 iframe . height = 40 ;
5360 iframe . width = 40 ;
54- iframe . src = `${ window . debugKitBaseUrl } debug-kit/toolbar/${ window . debugKitId } ` ;
55-
61+ iframe . src = `${ window . debugKitBaseUrl } debug-kit/toolbar/${ window . debugKitId } ` ; ;
5662 body . appendChild ( iframe ) ;
5763 bodyOverflow = body . style . overflow ;
64+ if ( ! win . debugKitMessageListenerApplied ) {
65+ window . addEventListener ( 'message' , onMessage , false ) ;
66+ win . debugKitMessageListenerApplied = true ;
67+ }
68+ }
5869
59- window . addEventListener ( 'message' , onMessage , false ) ;
70+ const onReady = ( ) => {
71+ injectDebugKitIframe ( ) ;
72+ if ( ! observer ) {
73+ observer = new MutationObserver ( ( ) => {
74+ if ( ! doc . body . querySelector ( 'iframe[src*="debug-kit/toolbar/"]' ) ) {
75+ injectDebugKitIframe ( ) ;
76+ }
77+ } ) ;
78+ if ( doc . body ) {
79+ observer . observe ( doc . body , { childList : true } ) ;
80+ }
81+ }
6082 } ;
6183
6284 const logAjaxRequest = ( original ) => function ajaxRequest ( ) {
6385 if ( this . readyState === 4 && this . getResponseHeader ( 'X-DEBUGKIT-ID' ) ) {
86+ const newId = this . getResponseHeader ( 'X-DEBUGKIT-ID' ) ;
87+ window . debugKitId = newId ;
6488 const params = {
65- requestId : this . getResponseHeader ( 'X-DEBUGKIT-ID' ) ,
89+ requestId : newId ,
6690 status : this . status ,
6791 date : new Date ( ) ,
6892 method : this . _arguments && this . _arguments [ 0 ] ,
6993 url : this . _arguments && this . _arguments [ 1 ] ,
7094 type : this . getResponseHeader ( 'Content-Type' ) ,
7195 } ;
96+
7297 iframe . contentWindow . postMessage ( `ajax-completed$$${ JSON . stringify ( params ) } ` , window . location . origin ) ;
7398 }
7499 if ( original ) {
@@ -78,32 +103,48 @@ if (elem) {
78103 } ;
79104
80105 const proxyAjaxOpen = ( ) => {
106+ if ( window . XMLHttpRequest . prototype . _debugKitOpenProxied ) {
107+ return ;
108+ }
81109 const proxied = window . XMLHttpRequest . prototype . open ;
82110 window . XMLHttpRequest . prototype . open = function ajaxCall ( ...args ) {
83111 this . _arguments = args ;
84112 return proxied . apply ( this , [ ] . slice . call ( args ) ) ;
85113 } ;
114+ window . XMLHttpRequest . prototype . _debugKitOpenProxied = true ;
86115 } ;
87116
88117 const proxyAjaxSend = ( ) => {
118+ if ( window . XMLHttpRequest . prototype . _debugKitSendProxied ) {
119+ return ;
120+ }
89121 const proxied = window . XMLHttpRequest . prototype . send ;
90122 window . XMLHttpRequest . prototype . send = function ajaxCall ( ...args ) {
91123 this . onreadystatechange = logAjaxRequest ( this . onreadystatechange ) ;
92124 return proxied . apply ( this , [ ] . slice . call ( args ) ) ;
93125 } ;
126+ window . XMLHttpRequest . prototype . _debugKitSendProxied = true ;
94127 } ;
95128
96129 // Bind on ready callbacks to DOMContentLoaded (native js)
97130 // Since the body is already loaded (DOMContentLoaded), the event is not triggered.
98131 if ( doc . addEventListener ) {
99132 // This ensures that all event listeners get applied only once.
100133 if ( ! win . debugKitListenersApplied ) {
101- // Add support for turbo DOMContentLoaded alternative
102- // see https://turbo.hotwired.dev/reference/events#turbo%3Aload
103- const loadedEvent = typeof Turbo !== 'undefined' && Turbo !== null ? 'turbo:load' : 'DOMContentLoaded' ;
104- doc . addEventListener ( loadedEvent , onReady , false ) ;
105- doc . addEventListener ( loadedEvent , proxyAjaxOpen , false ) ;
106- doc . addEventListener ( loadedEvent , proxyAjaxSend , false ) ;
134+ doc . addEventListener ( 'DOMContentLoaded' , onReady , false ) ;
135+ if ( ! win . debugKitAjaxProxied ) {
136+ doc . addEventListener ( 'DOMContentLoaded' , proxyAjaxOpen , false ) ;
137+ doc . addEventListener ( 'DOMContentLoaded' , proxyAjaxSend , false ) ;
138+ if ( doc . readyState === 'interactive' || doc . readyState === 'complete' ) {
139+ proxyAjaxOpen ( ) ;
140+ proxyAjaxSend ( ) ;
141+ }
142+ win . debugKitAjaxProxied = true ;
143+ }
144+ doc . addEventListener ( 'DOMContentLoaded' , onReady , false ) ;
145+ if ( doc . readyState === 'interactive' || doc . readyState === 'complete' ) {
146+ onReady ( ) ;
147+ }
107148 win . debugKitListenersApplied = true ;
108149 }
109150 } else {
0 commit comments