@@ -131,32 +131,79 @@ port.onDisconnect.addListener(() => {
131131 destroy ( ) ;
132132} ) ;
133133
134+ /**
135+ * To avoid dropping messages on reload that may have already been
136+ * sent by us, we keep messages from the content script in memory
137+ * until the navigation event has been acknowledged. This is soley
138+ * done to work around an issue in Firefox where the `onNavigated`
139+ * event is only fired after all resources are loaded. That's too
140+ * late for us as the content script likely already sent some events.
141+ * See: https://bugzilla.mozilla.org/show_bug.cgi?id=1552686
142+ */
143+ const pending = new Map < number , any [ ] > ( ) ;
144+
145+ const IS_FIREFOX = navigator . userAgent . indexOf ( "Firefox" ) >= 0 ;
146+
134147// Subscribe to messages from content script
135148port . onMessage . addListener ( async message => {
136149 if ( ! initialized ) {
137150 debug ( "initialize devtools panel" ) ;
138151 await initDevtools ( ) ;
139152 }
140153
154+ const tabId = chrome . devtools . inspectedWindow . tabId ;
141155 if ( message . type === "init" ) {
142156 debug ( "> message" , message ) ;
157+
158+ if ( IS_FIREFOX && pending . has ( tabId ) ) {
159+ store . clear ( ) ;
160+ }
161+
162+ pending . set ( tabId , [ ] ) ;
163+
143164 port . postMessage ( {
144165 type : "init" ,
145- tabId : chrome . devtools . inspectedWindow . tabId ,
166+ tabId,
146167 source : DevtoolsPanelName ,
147168 } ) ;
148169 } else {
149170 debug ( "-> devtools" , message ) ;
150- applyEvent ( store , message . type , message . data ) ;
171+
172+ if ( IS_FIREFOX ) {
173+ const backup = pending . get ( tabId ) ;
174+ if ( backup ) {
175+ backup . push ( { ...message } ) ;
176+ }
177+
178+ applyEvent ( store , message . type , message . data ) ;
179+ } else {
180+ applyEvent ( store , message . type , message . data ) ;
181+ }
151182 }
152183} ) ;
153184
154185// Clear store when we navigate away from the current page.
155186// Only fires on "true" navigation events, not when navigation
156- // is done via the HTML5 history API
187+ // is done via the HTML5 history API.
188+ //
189+ // Workaround for Firefox: The event only fires *after* all scripts
190+ // are loaded at which point our content script will have sent
191+ // events. So for Firefox we need to keep a queue around.
192+ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1552686
157193chrome . devtools . network . onNavigated . addListener ( ( ) => {
158- debug ( "== Navigation: clear devtools state ==" ) ;
194+ const tabId = chrome . devtools . inspectedWindow . tabId ;
195+ const backup = pending . get ( tabId ) || [ ] ;
196+ debug (
197+ "== Navigation: clear devtools state == pending length: " + backup . length ,
198+ ) ;
159199 store . clear ( ) ;
200+
201+ if ( backup . length ) {
202+ backup . forEach ( message => {
203+ applyEvent ( store , message . type , message . data ) ;
204+ } ) ;
205+ pending . delete ( tabId ) ;
206+ }
160207} ) ;
161208
162209// Notify background page of the panel
0 commit comments