From a40890d2c452bb6626564f98aed5ae54c976e2b4 Mon Sep 17 00:00:00 2001 From: Cory Streiff Date: Fri, 31 Jan 2025 14:26:14 +0100 Subject: [PATCH 1/6] Fix missing badge for Turbo Drive page loads Git bisect pointed to turbo-rails repo commit d18b2ee being the cause of this bug. Previously Turbo Drive requests were displayed via the callback added to the `window.fetch`. That turbo-rails commit however change it so that a reference to `window.fetch` was stored when Turbo JS is loaded (before rack-mini-profiler has added the then callback) meaning that the callback to display those profiling request results never executes. Adding a callback to `window.Turbo.fetch` is difficult as `window.Turbo` is a frozen object, so instead a turbo event listener is used. --- lib/html/includes.js | 94 +++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 41 deletions(-) diff --git a/lib/html/includes.js b/lib/html/includes.js index 4b57ad9f..1c7438d7 100644 --- a/lib/html/includes.js +++ b/lib/html/includes.js @@ -172,6 +172,50 @@ var _MiniProfiler = (function() { } }; + var fetchResultsFromAsyncResponse = function fetchResultsFromAsyncResponse(response) { + try { + // look for x-mini-profile-ids + var entries = response.headers.entries(); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for ( + var _iterator = entries[Symbol.iterator](), _step; + !(_iteratorNormalCompletion = (_step = _iterator.next()) + .done); + _iteratorNormalCompletion = true + ) { + var pair = _step.value; + + if ( + pair[0] && + pair[0].toLowerCase() == "x-miniprofiler-ids" + ) { + var ids = pair[1].split(","); + fetchResults(ids); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } catch (e) { + console.error(e); + } + } + var toQueryString = function toQueryString(data, parentKey) { var result = []; for (var key in data) { @@ -496,6 +540,11 @@ var _MiniProfiler = (function() { }, 3000); }; + var onTurboBeforeFetchResponse = function onTurboBeforeFetchResponse(e) { + var response = e.detail.fetchResponse.response; + fetchResultsFromAsyncResponse(response); + } + var onTurboBeforeVisit = function onTurboBeforeVisit(e) { if(!e.defaultPrevented) { window.MiniProfilerContainer = document.querySelector('body > .profiler-results') @@ -670,6 +719,7 @@ var _MiniProfiler = (function() { if (options.hotwireTurboDriveSupport) { document.addEventListener("turbo:before-visit", onTurboBeforeVisit) document.addEventListener("turbo:load", onTurboLoad) + document.addEventListener("turbo:before-fetch-response", onTurboBeforeFetchResponse); } }; @@ -685,6 +735,7 @@ var _MiniProfiler = (function() { ); document.removeEventListener("turbo:before-visit", onTurboBeforeVisit); document.removeEventListener("turbo:load", onTurboLoad); + document.removeEventListener("turbo:before-fetch-response", onTurboBeforeFetchResponse); }; var initFullView = function initFullView() { @@ -963,48 +1014,9 @@ var _MiniProfiler = (function() { var originalFetchRun = __originalFetch(input, init); originalFetchRun.then(function(response) { - try { - // look for x-mini-profile-ids - var entries = response.headers.entries(); - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for ( - var _iterator = entries[Symbol.iterator](), _step; - !(_iteratorNormalCompletion = (_step = _iterator.next()) - .done); - _iteratorNormalCompletion = true - ) { - var pair = _step.value; - - if ( - pair[0] && - pair[0].toLowerCase() == "x-miniprofiler-ids" - ) { - var ids = pair[1].split(","); - fetchResults(ids); - } - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - } catch (e) { - console.error(e); - } + fetchResultsFromAsyncResponse(response) }); + return originalFetchRun; }; } From 38f15f2cfc65fa0e2f52d52f0520ca953ad737ba Mon Sep 17 00:00:00 2001 From: Cory Streiff Date: Tue, 4 Feb 2025 11:30:12 +0100 Subject: [PATCH 2/6] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d272e368..cff86954 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - [BREAKING CHANGE] Ruby version 3.1.0 or later is required. [#632](https://github.com/MiniProfiler/rack-mini-profiler/pull/632) - [FIX] Truncate long profiler name in profiler popup. [#634](https://github.com/MiniProfiler/rack-mini-profiler/pull/634) - [FIX] `flamegraph_mode` query param having no effect. [#635](https://github.com/MiniProfiler/rack-mini-profiler/pull/635) +- [FIX] missing badge for Turbo Drive page loads. [#631](https://github.com/MiniProfiler/rack-mini-profiler/pull/631) ## 3.3.1 - 2024-02-15 - [FEATURE] Support dynamic `config.content_security_policy_nonce` [#609](https://github.com/MiniProfiler/rack-mini-profiler/pull/609) From 6f7f37d0821b8ad0b913ca03e3814bf15312ca4a Mon Sep 17 00:00:00 2001 From: Cory Streiff Date: Thu, 6 Feb 2025 13:53:53 +0100 Subject: [PATCH 3/6] Preserve prefetched profiling results in badge after Turbo renders --- lib/html/includes.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/html/includes.js b/lib/html/includes.js index 1c7438d7..68565c80 100644 --- a/lib/html/includes.js +++ b/lib/html/includes.js @@ -11,6 +11,8 @@ var _MiniProfiler = (function() { // so we never pull down a profiler twice ajaxStartTime, totalsControl, + lastTurboRequestUrl, + lastTurboProfilingResult, reqs = 0, expandedResults = false, totalTime = 0, @@ -153,6 +155,8 @@ var _MiniProfiler = (function() { fetchedIds.push(id); if (json != "hidden" && MiniProfiler.templates) { + if (options.hotwireTurboDriveSupport) lastTurboProfilingResult = json; + buttonShow(json); } } @@ -541,6 +545,8 @@ var _MiniProfiler = (function() { }; var onTurboBeforeFetchResponse = function onTurboBeforeFetchResponse(e) { + lastTurboRequestUrl = e.detail.fetchResponse.response.url; + var response = e.detail.fetchResponse.response; fetchResultsFromAsyncResponse(response); } @@ -548,7 +554,9 @@ var _MiniProfiler = (function() { var onTurboBeforeVisit = function onTurboBeforeVisit(e) { if(!e.defaultPrevented) { window.MiniProfilerContainer = document.querySelector('body > .profiler-results') - window.MiniProfiler.pageTransition() + + var visitingUrl = e.detail.url + window.MiniProfiler.pageTransition(visitingUrl) } } @@ -1181,7 +1189,7 @@ var _MiniProfiler = (function() { cleanUp: function cleanUp() { unbindDocumentEvents(); }, - pageTransition: function pageTransition() { + pageTransition: function pageTransition(visitingUrl) { if (totalsControl) { if (totalsControl.parentElement) { totalsControl.parentElement.removeChild(totalsControl); @@ -1197,6 +1205,13 @@ var _MiniProfiler = (function() { ).forEach(function(el) { return el.parentElement.removeChild(el); }); + + // Preserve the last prefetched profiling result so badge doesn't disappear when Turbo replaces page HTML + if (visitingUrl === lastTurboRequestUrl && visitingUrl !== Turbo.session.view.lastRenderedLocation.href && lastTurboProfilingResult) { + buttonShow(lastTurboProfilingResult) + } + lastTurboProfilingResult = null; + lastTurboRequestUrl = null; }, getClientTimingByName: function getClientTimingByName(clientTiming, name) { for (var i = 0; i < clientTiming.timings.length; i++) { From 1600b257f5442164be87ef5748e4b7ffc7e14003 Mon Sep 17 00:00:00 2001 From: Cory Streiff Date: Fri, 7 Feb 2025 15:14:41 +0100 Subject: [PATCH 4/6] Add guard clause for turbo drive support in pageTransition pageTransition() is part of RMP's public API and is used by SPAs. --- lib/html/includes.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/html/includes.js b/lib/html/includes.js index 5751b742..8cb99bef 100644 --- a/lib/html/includes.js +++ b/lib/html/includes.js @@ -1207,11 +1207,16 @@ var _MiniProfiler = (function() { }); // Preserve the last prefetched profiling result so badge doesn't disappear when Turbo replaces page HTML - if (visitingUrl === lastTurboRequestUrl && visitingUrl !== Turbo.session.view.lastRenderedLocation.href && lastTurboProfilingResult) { - buttonShow(lastTurboProfilingResult) + if ( + options.hotwireTurboDriveSupport && + visitingUrl === lastTurboRequestUrl && + visitingUrl !== Turbo.session.view.lastRenderedLocation.href && + lastTurboProfilingResult + ) { + buttonShow(lastTurboProfilingResult); + lastTurboProfilingResult = null; + lastTurboRequestUrl = null; } - lastTurboProfilingResult = null; - lastTurboRequestUrl = null; }, getClientTimingByName: function getClientTimingByName(clientTiming, name) { for (var i = 0; i < clientTiming.timings.length; i++) { From c75a8c799fd5b378ef89d654701c3194c72ef64f Mon Sep 17 00:00:00 2001 From: Cory Streiff Date: Sat, 8 Feb 2025 13:53:51 +0100 Subject: [PATCH 5/6] Move turbo-related logic out of pageTransition --- lib/html/includes.js | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/html/includes.js b/lib/html/includes.js index 8cb99bef..6c50bd7f 100644 --- a/lib/html/includes.js +++ b/lib/html/includes.js @@ -554,9 +554,20 @@ var _MiniProfiler = (function() { var onTurboBeforeVisit = function onTurboBeforeVisit(e) { if(!e.defaultPrevented) { window.MiniProfilerContainer = document.querySelector('body > .profiler-results') + window.MiniProfiler.pageTransition() var visitingUrl = e.detail.url - window.MiniProfiler.pageTransition(visitingUrl) + + // To preserve the last prefetched profiling result so badge doesn't disappear when Turbo replaces page HTML + if ( + visitingUrl === lastTurboRequestUrl && + visitingUrl !== Turbo.session.view.lastRenderedLocation.href && + lastTurboProfilingResult + ) { + buttonShow(lastTurboProfilingResult); + lastTurboProfilingResult = null; + lastTurboRequestUrl = null; + } } } @@ -1189,7 +1200,7 @@ var _MiniProfiler = (function() { cleanUp: function cleanUp() { unbindDocumentEvents(); }, - pageTransition: function pageTransition(visitingUrl) { + pageTransition: function pageTransition() { if (totalsControl) { if (totalsControl.parentElement) { totalsControl.parentElement.removeChild(totalsControl); @@ -1205,18 +1216,6 @@ var _MiniProfiler = (function() { ).forEach(function(el) { return el.parentElement.removeChild(el); }); - - // Preserve the last prefetched profiling result so badge doesn't disappear when Turbo replaces page HTML - if ( - options.hotwireTurboDriveSupport && - visitingUrl === lastTurboRequestUrl && - visitingUrl !== Turbo.session.view.lastRenderedLocation.href && - lastTurboProfilingResult - ) { - buttonShow(lastTurboProfilingResult); - lastTurboProfilingResult = null; - lastTurboRequestUrl = null; - } }, getClientTimingByName: function getClientTimingByName(clientTiming, name) { for (var i = 0; i < clientTiming.timings.length; i++) { From c7ec597822824af15fa4946f44a7015758b40b46 Mon Sep 17 00:00:00 2001 From: Cory Streiff Date: Sat, 1 Nov 2025 18:40:30 +0100 Subject: [PATCH 6/6] Appease rubocop --- lib/mini_profiler_rails/railtie.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mini_profiler_rails/railtie.rb b/lib/mini_profiler_rails/railtie.rb index b3f2c8cb..4404d41e 100644 --- a/lib/mini_profiler_rails/railtie.rb +++ b/lib/mini_profiler_rails/railtie.rb @@ -34,7 +34,7 @@ def self.initialize!(app) c.skip_paths << wp_assets_path if wp_assets_path end - unless Rails.env.development? || Rails.env.test? + unless Rails.env.local? c.authorization_mode = :allow_authorized end @@ -55,7 +55,7 @@ def self.initialize!(app) # Quiet the SQL stack traces c.backtrace_remove = Rails.root.to_s + "/" c.backtrace_includes = [/^\/?(app|config|lib|test)/] - c.skip_schema_queries = (Rails.env.development? || Rails.env.test?) + c.skip_schema_queries = Rails.env.local? # Install the Middleware app.middleware.insert(0, Rack::MiniProfiler)