11/*!
2- Turbo 8.0.20
3- Copyright © 2025 37signals LLC
2+ Turbo 8.0.23
3+ Copyright © 2026 37signals LLC
44 */
55const FrameLoadingStyle = {
66 eager : "eager" ,
@@ -313,6 +313,10 @@ function findClosestRecursively(element, selector) {
313313 }
314314}
315315
316+ function elementIsStylesheet ( element ) {
317+ return element . localName === "style" || element . localName === "link" && element . relList . contains ( "stylesheet" ) ;
318+ }
319+
316320function elementIsFocusable ( element ) {
317321 const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])" ;
318322 return ! ! element && element . closest ( inertDisabledOrHidden ) == null && typeof element . focus == "function" ;
@@ -2589,11 +2593,6 @@ function elementIsNoscript(element) {
25892593 return tagName == "noscript" ;
25902594}
25912595
2592- function elementIsStylesheet ( element ) {
2593- const tagName = element . localName ;
2594- return tagName == "style" || tagName == "link" && element . getAttribute ( "rel" ) == "stylesheet" ;
2595- }
2596-
25972596function elementIsMetaElementWithName ( element , name ) {
25982597 const tagName = element . localName ;
25992598 return tagName == "meta" && element . getAttribute ( "name" ) == name ;
@@ -2634,7 +2633,11 @@ class PageSnapshot extends Snapshot {
26342633 clonedPasswordInput . value = "" ;
26352634 }
26362635 for ( const clonedNoscriptElement of clonedElement . querySelectorAll ( "noscript" ) ) {
2637- clonedNoscriptElement . remove ( ) ;
2636+ for ( const child of [ ...clonedNoscriptElement . children ] ) {
2637+ if ( elementIsStylesheet ( child ) ) {
2638+ child . remove ( ) ;
2639+ }
2640+ }
26382641 }
26392642 return new PageSnapshot ( this . documentElement , clonedElement , this . headSnapshot ) ;
26402643 }
@@ -3985,12 +3988,16 @@ class PageRenderer extends Renderer {
39853988 }
39863989 activateNewBody ( ) {
39873990 document . adoptNode ( this . newElement ) ;
3988- this . removeNoscriptElements ( ) ;
3991+ this . deactivateNoscriptStylesheetElements ( ) ;
39893992 this . activateNewBodyScriptElements ( ) ;
39903993 }
3991- removeNoscriptElements ( ) {
3994+ deactivateNoscriptStylesheetElements ( ) {
39923995 for ( const noscriptElement of this . newElement . querySelectorAll ( "noscript" ) ) {
3993- noscriptElement . remove ( ) ;
3996+ for ( const child of [ ...noscriptElement . children ] ) {
3997+ if ( elementIsStylesheet ( child ) ) {
3998+ child . remove ( ) ;
3999+ }
4000+ }
39944001 }
39954002 }
39964003 activateNewBodyScriptElements ( ) {
@@ -4572,13 +4579,14 @@ const deprecatedLocationPropertyDescriptors = {
45724579
45734580class Offline {
45744581 serviceWorker ;
4575- async start ( url = "/service-worker.js" , { scope : scope = "/" , type : type = "classic" , native : native = true } = { } ) {
4582+ async start ( url = "/service-worker.js" , { scope : scope = "/" , type : type = "classic" , native : native = true , preload : preload } = { } ) {
45764583 if ( ! ( "serviceWorker" in navigator ) ) {
45774584 console . warn ( "Service Worker not available." ) ;
45784585 return ;
45794586 }
45804587 if ( native ) this . #setUserAgentCookie( ) ;
45814588 await this . #domReady( ) ;
4589+ const needsPreloading = preload && ! navigator . serviceWorker . controller ;
45824590 this . #checkExistingController( navigator . serviceWorker . controller , url ) ;
45834591 try {
45844592 const registration = await navigator . serviceWorker . register ( url , {
@@ -4588,6 +4596,9 @@ class Offline {
45884596 const registered = registration . active || registration . waiting || registration . installing ;
45894597 this . #checkExistingController( registered , url ) ;
45904598 this . serviceWorker = registered ;
4599+ if ( needsPreloading ) {
4600+ this . #preloadWhenReady( preload ) ;
4601+ }
45914602 return registration ;
45924603 } catch ( error ) {
45934604 console . error ( error ) ;
@@ -4602,6 +4613,28 @@ class Offline {
46024613 console . warn ( `Expected service worker script ${ url } but found ${ controller . scriptURL } . ` + `This may indicate multiple service workers or a cached version.` ) ;
46034614 }
46044615 }
4616+ async clearCache ( ) {
4617+ const registration = await ( navigator . serviceWorker ?. ready ) ;
4618+ registration ?. active ?. postMessage ( {
4619+ action : "clearCache"
4620+ } ) ;
4621+ }
4622+ #preloadWhenReady( pattern ) {
4623+ navigator . serviceWorker . addEventListener ( "controllerchange" , ( ( ) => {
4624+ this . #preloadResources( pattern ) ;
4625+ } ) , {
4626+ once : true
4627+ } ) ;
4628+ }
4629+ #preloadResources( pattern ) {
4630+ const urls = performance . getEntriesByType ( "resource" ) . map ( ( entry => entry . name ) ) . filter ( ( url => pattern . test ( url ) ) ) ;
4631+ navigator . serviceWorker . controller . postMessage ( {
4632+ action : "preloadResources" ,
4633+ params : {
4634+ urls : urls
4635+ }
4636+ } ) ;
4637+ }
46054638 #domReady( ) {
46064639 return new Promise ( ( resolve => {
46074640 if ( document . readyState !== "complete" ) {
@@ -4617,7 +4650,7 @@ const offline = new Offline;
46174650
46184651const session = new Session ( recentRequests ) ;
46194652
4620- const { cache : cache , navigator : navigator } = session ;
4653+ const { cache : cache , navigator : sessionNavigator } = session ;
46214654
46224655function start ( ) {
46234656 session . start ( ) ;
@@ -4668,15 +4701,15 @@ function morphTurboFrameElements(currentFrame, newFrame) {
46684701
46694702var Turbo = Object . freeze ( {
46704703 __proto__ : null ,
4671- navigator : navigator ,
4672- session : session ,
4673- cache : cache ,
46744704 PageRenderer : PageRenderer ,
46754705 PageSnapshot : PageSnapshot ,
46764706 FrameRenderer : FrameRenderer ,
46774707 fetch : fetchWithTurboHeaders ,
46784708 config : config ,
46794709 offline : offline ,
4710+ session : session ,
4711+ cache : cache ,
4712+ navigator : sessionNavigator ,
46804713 start : start ,
46814714 registerAdapter : registerAdapter ,
46824715 visit : visit ,
@@ -5418,7 +5451,7 @@ var Turbo$1 = Object.freeze({
54185451 morphChildren : morphChildren ,
54195452 morphElements : morphElements ,
54205453 morphTurboFrameElements : morphTurboFrameElements ,
5421- navigator : navigator$1 ,
5454+ navigator : sessionNavigator ,
54225455 offline : offline ,
54235456 registerAdapter : registerAdapter ,
54245457 renderStreamMessage : renderStreamMessage ,
0 commit comments