2024-01-05 12:14:38 +00:00
import '@vite/env' ;
class HMRContext {
2026-02-11 16:20:26 +00:00
constructor ( hmrClient , ownerPath ) {
this . hmrClient = hmrClient ;
this . ownerPath = ownerPath ;
if ( ! hmrClient . dataMap . has ( ownerPath ) ) {
hmrClient . dataMap . set ( ownerPath , { } ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
const mod = hmrClient . hotModulesMap . get ( ownerPath ) ;
if ( mod ) {
mod . callbacks = [ ] ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
const staleListeners = hmrClient . ctxToListenersMap . get ( ownerPath ) ;
if ( staleListeners ) {
for ( const [ event , staleFns ] of staleListeners ) {
const listeners = hmrClient . customListenersMap . get ( event ) ;
if ( listeners ) {
hmrClient . customListenersMap . set (
event ,
listeners . filter ( ( l ) => ! staleFns . includes ( l ) )
) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
this . newListeners = /* @__PURE__ */ new Map ( ) ;
hmrClient . ctxToListenersMap . set ( ownerPath , this . newListeners ) ;
}
get data ( ) {
return this . hmrClient . dataMap . get ( this . ownerPath ) ;
}
accept ( deps , callback ) {
if ( typeof deps === "function" || ! deps ) {
this . acceptDeps ( [ this . ownerPath ] , ( [ mod ] ) => deps ? . ( mod ) ) ;
} else if ( typeof deps === "string" ) {
this . acceptDeps ( [ deps ] , ( [ mod ] ) => callback ? . ( mod ) ) ;
} else if ( Array . isArray ( deps ) ) {
this . acceptDeps ( deps , callback ) ;
} else {
throw new Error ( ` invalid hot.accept() usage. ` ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
// export names (first arg) are irrelevant on the client side, they're
// extracted in the server for propagation
acceptExports ( _ , callback ) {
this . acceptDeps ( [ this . ownerPath ] , ( [ mod ] ) => callback ? . ( mod ) ) ;
}
dispose ( cb ) {
this . hmrClient . disposeMap . set ( this . ownerPath , cb ) ;
}
prune ( cb ) {
this . hmrClient . pruneMap . set ( this . ownerPath , cb ) ;
}
// Kept for backward compatibility (#11036)
// eslint-disable-next-line @typescript-eslint/no-empty-function
decline ( ) {
}
invalidate ( message ) {
this . hmrClient . notifyListeners ( "vite:invalidate" , {
path : this . ownerPath ,
message
} ) ;
this . send ( "vite:invalidate" , { path : this . ownerPath , message } ) ;
this . hmrClient . logger . debug (
` [vite] invalidate ${ this . ownerPath } ${ message ? ` : ${ message } ` : "" } `
) ;
}
on ( event , cb ) {
const addToMap = ( map ) => {
const existing = map . get ( event ) || [ ] ;
existing . push ( cb ) ;
map . set ( event , existing ) ;
} ;
addToMap ( this . hmrClient . customListenersMap ) ;
addToMap ( this . newListeners ) ;
}
off ( event , cb ) {
const removeFromMap = ( map ) => {
const existing = map . get ( event ) ;
if ( existing === void 0 ) {
return ;
}
const pruned = existing . filter ( ( l ) => l !== cb ) ;
if ( pruned . length === 0 ) {
map . delete ( event ) ;
return ;
}
map . set ( event , pruned ) ;
} ;
removeFromMap ( this . hmrClient . customListenersMap ) ;
removeFromMap ( this . newListeners ) ;
}
send ( event , data ) {
this . hmrClient . messenger . send (
JSON . stringify ( { type : "custom" , event , data } )
) ;
}
acceptDeps ( deps , callback = ( ) => {
} ) {
const mod = this . hmrClient . hotModulesMap . get ( this . ownerPath ) || {
id : this . ownerPath ,
callbacks : [ ]
} ;
mod . callbacks . push ( {
deps ,
fn : callback
} ) ;
this . hmrClient . hotModulesMap . set ( this . ownerPath , mod ) ;
}
}
class HMRMessenger {
constructor ( connection ) {
this . connection = connection ;
this . queue = [ ] ;
}
send ( message ) {
this . queue . push ( message ) ;
this . flush ( ) ;
}
flush ( ) {
if ( this . connection . isReady ( ) ) {
this . queue . forEach ( ( msg ) => this . connection . send ( msg ) ) ;
this . queue = [ ] ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
2024-01-05 12:14:38 +00:00
}
class HMRClient {
2026-02-11 16:20:26 +00:00
constructor ( logger , connection , importUpdatedModule ) {
this . logger = logger ;
this . importUpdatedModule = importUpdatedModule ;
this . hotModulesMap = /* @__PURE__ */ new Map ( ) ;
this . disposeMap = /* @__PURE__ */ new Map ( ) ;
this . pruneMap = /* @__PURE__ */ new Map ( ) ;
this . dataMap = /* @__PURE__ */ new Map ( ) ;
this . customListenersMap = /* @__PURE__ */ new Map ( ) ;
this . ctxToListenersMap = /* @__PURE__ */ new Map ( ) ;
this . updateQueue = [ ] ;
this . pendingUpdateQueue = false ;
this . messenger = new HMRMessenger ( connection ) ;
}
async notifyListeners ( event , data ) {
const cbs = this . customListenersMap . get ( event ) ;
if ( cbs ) {
await Promise . allSettled ( cbs . map ( ( cb ) => cb ( data ) ) ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
clear ( ) {
this . hotModulesMap . clear ( ) ;
this . disposeMap . clear ( ) ;
this . pruneMap . clear ( ) ;
this . dataMap . clear ( ) ;
this . customListenersMap . clear ( ) ;
this . ctxToListenersMap . clear ( ) ;
}
// After an HMR update, some modules are no longer imported on the page
// but they may have left behind side effects that need to be cleaned up
// (.e.g style injections)
async prunePaths ( paths ) {
await Promise . all (
paths . map ( ( path ) => {
const disposer = this . disposeMap . get ( path ) ;
if ( disposer ) return disposer ( this . dataMap . get ( path ) ) ;
} )
) ;
paths . forEach ( ( path ) => {
const fn = this . pruneMap . get ( path ) ;
if ( fn ) {
fn ( this . dataMap . get ( path ) ) ;
}
} ) ;
}
warnFailedUpdate ( err , path ) {
if ( ! err . message . includes ( "fetch" ) ) {
this . logger . error ( err ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
this . logger . error (
` [hmr] Failed to reload ${ path } . This could be due to syntax errors or importing non-existent modules. (see errors above) `
) ;
}
/ * *
* buffer multiple hot updates triggered by the same src change
* so that they are invoked in the same order they were sent .
* ( otherwise the order may be inconsistent because of the http request round trip )
* /
async queueUpdate ( payload ) {
this . updateQueue . push ( this . fetchUpdate ( payload ) ) ;
if ( ! this . pendingUpdateQueue ) {
this . pendingUpdateQueue = true ;
await Promise . resolve ( ) ;
this . pendingUpdateQueue = false ;
const loading = [ ... this . updateQueue ] ;
this . updateQueue = [ ] ;
( await Promise . all ( loading ) ) . forEach ( ( fn ) => fn && fn ( ) ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
async fetchUpdate ( update ) {
const { path , acceptedPath } = update ;
const mod = this . hotModulesMap . get ( path ) ;
if ( ! mod ) {
return ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
let fetchedModule ;
const isSelfUpdate = path === acceptedPath ;
const qualifiedCallbacks = mod . callbacks . filter (
( { deps } ) => deps . includes ( acceptedPath )
) ;
if ( isSelfUpdate || qualifiedCallbacks . length > 0 ) {
const disposer = this . disposeMap . get ( acceptedPath ) ;
if ( disposer ) await disposer ( this . dataMap . get ( acceptedPath ) ) ;
try {
fetchedModule = await this . importUpdatedModule ( update ) ;
} catch ( e ) {
this . warnFailedUpdate ( e , acceptedPath ) ;
}
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
return ( ) => {
for ( const { deps , fn } of qualifiedCallbacks ) {
fn (
deps . map ( ( dep ) => dep === acceptedPath ? fetchedModule : void 0 )
) ;
}
const loggedPath = isSelfUpdate ? path : ` ${ acceptedPath } via ${ path } ` ;
this . logger . debug ( ` [vite] hot updated: ${ loggedPath } ` ) ;
} ;
}
2024-01-05 12:14:38 +00:00
}
const hmrConfigName = _ _HMR _CONFIG _NAME _ _ ;
2026-02-11 16:20:26 +00:00
const base$1 = _ _BASE _ _ || "/" ;
function h ( e , attrs = { } , ... children ) {
const elem = document . createElement ( e ) ;
for ( const [ k , v ] of Object . entries ( attrs ) ) {
elem . setAttribute ( k , v ) ;
}
elem . append ( ... children ) ;
return elem ;
}
const templateStyle = (
/*css*/
`
2024-01-05 12:14:38 +00:00
: host {
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 % ;
height : 100 % ;
z - index : 99999 ;
-- monospace : 'SFMono-Regular' , Consolas ,
'Liberation Mono' , Menlo , Courier , monospace ;
-- red : # ff5555 ;
-- yellow : # e2aa53 ;
-- purple : # cfa4ff ;
-- cyan : # 2 dd9da ;
-- dim : # c9c9c9 ;
-- window - background : # 181818 ;
-- window - color : # d8d8d8 ;
}
. backdrop {
position : fixed ;
z - index : 99999 ;
top : 0 ;
left : 0 ;
width : 100 % ;
height : 100 % ;
overflow - y : scroll ;
margin : 0 ;
background : rgba ( 0 , 0 , 0 , 0.66 ) ;
}
. window {
font - family : var ( -- monospace ) ;
line - height : 1.5 ;
2026-02-11 16:20:26 +00:00
max - width : 80 vw ;
2024-01-05 12:14:38 +00:00
color : var ( -- window - color ) ;
2026-02-11 16:20:26 +00:00
box - sizing : border - box ;
2024-01-05 12:14:38 +00:00
margin : 30 px auto ;
2026-02-11 16:20:26 +00:00
padding : 2.5 vh 4 vw ;
2024-01-05 12:14:38 +00:00
position : relative ;
background : var ( -- window - background ) ;
border - radius : 6 px 6 px 8 px 8 px ;
box - shadow : 0 19 px 38 px rgba ( 0 , 0 , 0 , 0.30 ) , 0 15 px 12 px rgba ( 0 , 0 , 0 , 0.22 ) ;
overflow : hidden ;
border - top : 8 px solid var ( -- red ) ;
direction : ltr ;
text - align : left ;
}
pre {
font - family : var ( -- monospace ) ;
font - size : 16 px ;
margin - top : 0 ;
margin - bottom : 1 em ;
overflow - x : scroll ;
scrollbar - width : none ;
}
pre : : - webkit - scrollbar {
display : none ;
}
pre . frame : : - webkit - scrollbar {
display : block ;
height : 5 px ;
}
pre . frame : : - webkit - scrollbar - thumb {
background : # 999 ;
border - radius : 5 px ;
}
pre . frame {
scrollbar - width : thin ;
}
. message {
line - height : 1.3 ;
font - weight : 600 ;
white - space : pre - wrap ;
}
. message - body {
color : var ( -- red ) ;
}
. plugin {
color : var ( -- purple ) ;
}
. file {
color : var ( -- cyan ) ;
margin - bottom : 0 ;
white - space : pre - wrap ;
word - break : break - all ;
}
. frame {
color : var ( -- yellow ) ;
}
. stack {
font - size : 13 px ;
color : var ( -- dim ) ;
}
. tip {
font - size : 13 px ;
color : # 999 ;
border - top : 1 px dotted # 999 ;
padding - top : 13 px ;
line - height : 1.8 ;
}
code {
font - size : 13 px ;
font - family : var ( -- monospace ) ;
color : var ( -- yellow ) ;
}
. file - link {
text - decoration : underline ;
cursor : pointer ;
}
kbd {
line - height : 1.5 ;
font - family : ui - monospace , Menlo , Monaco , Consolas , "Liberation Mono" , "Courier New" , monospace ;
font - size : 0.75 rem ;
font - weight : 700 ;
background - color : rgb ( 38 , 40 , 44 ) ;
color : rgb ( 166 , 167 , 171 ) ;
padding : 0.15 rem 0.3 rem ;
border - radius : 0.25 rem ;
border - width : 0.0625 rem 0.0625 rem 0.1875 rem ;
border - style : solid ;
border - color : rgb ( 54 , 57 , 64 ) ;
border - image : initial ;
}
2026-02-11 16:20:26 +00:00
`
) ;
const createTemplate = ( ) => h (
"div" ,
{ class : "backdrop" , part : "backdrop" } ,
h (
"div" ,
{ class : "window" , part : "window" } ,
h (
"pre" ,
{ class : "message" , part : "message" } ,
h ( "span" , { class : "plugin" , part : "plugin" } ) ,
h ( "span" , { class : "message-body" , part : "message-body" } )
) ,
h ( "pre" , { class : "file" , part : "file" } ) ,
h ( "pre" , { class : "frame" , part : "frame" } ) ,
h ( "pre" , { class : "stack" , part : "stack" } ) ,
h (
"div" ,
{ class : "tip" , part : "tip" } ,
"Click outside, press " ,
h ( "kbd" , { } , "Esc" ) ,
" key, or fix the code to dismiss." ,
h ( "br" ) ,
"You can also disable this overlay by setting " ,
h ( "code" , { part : "config-option-name" } , "server.hmr.overlay" ) ,
" to " ,
h ( "code" , { part : "config-option-value" } , "false" ) ,
" in " ,
h ( "code" , { part : "config-file-name" } , hmrConfigName ) ,
"."
)
) ,
h ( "style" , { } , templateStyle )
) ;
2024-01-05 12:14:38 +00:00
const fileRE = /(?:[a-zA-Z]:\\|\/).*?:\d+:\d+/g ;
const codeframeRE = /^(?:>?\s*\d+\s+\|.*|\s+\|\s*\^.*)\r?\n/gm ;
const { HTMLElement = class {
} } = globalThis ;
class ErrorOverlay extends HTMLElement {
2026-02-11 16:20:26 +00:00
constructor ( err , links = true ) {
super ( ) ;
this . root = this . attachShadow ( { mode : "open" } ) ;
this . root . appendChild ( createTemplate ( ) ) ;
codeframeRE . lastIndex = 0 ;
const hasFrame = err . frame && codeframeRE . test ( err . frame ) ;
const message = hasFrame ? err . message . replace ( codeframeRE , "" ) : err . message ;
if ( err . plugin ) {
this . text ( ".plugin" , ` [plugin: ${ err . plugin } ] ` ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
this . text ( ".message-body" , message . trim ( ) ) ;
const [ file ] = ( err . loc ? . file || err . id || "unknown file" ) . split ( ` ? ` ) ;
if ( err . loc ) {
this . text ( ".file" , ` ${ file } : ${ err . loc . line } : ${ err . loc . column } ` , links ) ;
} else if ( err . id ) {
this . text ( ".file" , file ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
if ( hasFrame ) {
this . text ( ".frame" , err . frame . trim ( ) ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
this . text ( ".stack" , err . stack , links ) ;
this . root . querySelector ( ".window" ) . addEventListener ( "click" , ( e ) => {
e . stopPropagation ( ) ;
} ) ;
this . addEventListener ( "click" , ( ) => {
this . close ( ) ;
} ) ;
this . closeOnEsc = ( e ) => {
if ( e . key === "Escape" || e . code === "Escape" ) {
this . close ( ) ;
}
} ;
document . addEventListener ( "keydown" , this . closeOnEsc ) ;
}
text ( selector , text , linkFiles = false ) {
const el = this . root . querySelector ( selector ) ;
if ( ! linkFiles ) {
el . textContent = text ;
} else {
let curIndex = 0 ;
let match ;
fileRE . lastIndex = 0 ;
while ( match = fileRE . exec ( text ) ) {
const { 0 : file , index } = match ;
if ( index != null ) {
const frag = text . slice ( curIndex , index ) ;
el . appendChild ( document . createTextNode ( frag ) ) ;
const link = document . createElement ( "a" ) ;
link . textContent = file ;
link . className = "file-link" ;
link . onclick = ( ) => {
fetch (
new URL (
` ${ base$1 } __open-in-editor?file= ${ encodeURIComponent ( file ) } ` ,
import . meta . url
)
) ;
} ;
el . appendChild ( link ) ;
curIndex += frag . length + file . length ;
}
}
}
}
close ( ) {
this . parentNode ? . removeChild ( this ) ;
document . removeEventListener ( "keydown" , this . closeOnEsc ) ;
}
}
const overlayId = "vite-error-overlay" ;
const { customElements } = globalThis ;
2024-01-05 12:14:38 +00:00
if ( customElements && ! customElements . get ( overlayId ) ) {
2026-02-11 16:20:26 +00:00
customElements . define ( overlayId , ErrorOverlay ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
console . debug ( "[vite] connecting..." ) ;
2024-01-05 12:14:38 +00:00
const importMetaUrl = new URL ( import . meta . url ) ;
const serverHost = _ _SERVER _HOST _ _ ;
2026-02-11 16:20:26 +00:00
const socketProtocol = _ _HMR _PROTOCOL _ _ || ( importMetaUrl . protocol === "https:" ? "wss" : "ws" ) ;
2024-01-05 12:14:38 +00:00
const hmrPort = _ _HMR _PORT _ _ ;
const socketHost = ` ${ _ _HMR _HOSTNAME _ _ || importMetaUrl . hostname } : ${ hmrPort || importMetaUrl . port } ${ _ _HMR _BASE _ _ } ` ;
const directSocketHost = _ _HMR _DIRECT _TARGET _ _ ;
2026-02-11 16:20:26 +00:00
const base = _ _BASE _ _ || "/" ;
const wsToken = _ _WS _TOKEN _ _ ;
2024-01-05 12:14:38 +00:00
let socket ;
try {
2026-02-11 16:20:26 +00:00
let fallback ;
if ( ! hmrPort ) {
fallback = ( ) => {
socket = setupWebSocket ( socketProtocol , directSocketHost , ( ) => {
const currentScriptHostURL = new URL ( import . meta . url ) ;
const currentScriptHost = currentScriptHostURL . host + currentScriptHostURL . pathname . replace ( /@vite\/client$/ , "" ) ;
console . error (
` [vite] failed to connect to websocket.
your current setup :
( browser ) $ { currentScriptHost } < -- [ HTTP ] -- > $ { serverHost } ( server )
( browser ) $ { socketHost } < -- [ WebSocket ( failing ) ] -- > $ { directSocketHost } ( server )
Check out your Vite / network configuration and https : //vite.dev/config/server-options.html#server-hmr .`
) ;
} ) ;
socket . addEventListener (
"open" ,
( ) => {
console . info (
"[vite] Direct websocket connection fallback. Check out https://vite.dev/config/server-options.html#server-hmr to remove the previous connection error."
) ;
} ,
{ once : true }
) ;
} ;
}
socket = setupWebSocket ( socketProtocol , socketHost , fallback ) ;
} catch ( error ) {
console . error ( ` [vite] failed to connect to websocket ( ${ error } ). ` ) ;
2024-01-05 12:14:38 +00:00
}
function setupWebSocket ( protocol , hostAndPath , onCloseWithoutOpen ) {
2026-02-11 16:20:26 +00:00
const socket2 = new WebSocket (
` ${ protocol } :// ${ hostAndPath } ?token= ${ wsToken } ` ,
"vite-hmr"
) ;
let isOpened = false ;
socket2 . addEventListener (
"open" ,
( ) => {
isOpened = true ;
notifyListeners ( "vite:ws:connect" , { webSocket : socket2 } ) ;
} ,
{ once : true }
) ;
socket2 . addEventListener ( "message" , async ( { data } ) => {
handleMessage ( JSON . parse ( data ) ) ;
} ) ;
socket2 . addEventListener ( "close" , async ( { wasClean } ) => {
if ( wasClean ) return ;
if ( ! isOpened && onCloseWithoutOpen ) {
onCloseWithoutOpen ( ) ;
return ;
}
notifyListeners ( "vite:ws:disconnect" , { webSocket : socket2 } ) ;
if ( hasDocument ) {
console . log ( ` [vite] server connection lost. Polling for restart... ` ) ;
await waitForSuccessfulPing ( protocol , hostAndPath ) ;
location . reload ( ) ;
}
} ) ;
return socket2 ;
2024-01-05 12:14:38 +00:00
}
function cleanUrl ( pathname ) {
2026-02-11 16:20:26 +00:00
const url = new URL ( pathname , "http://vite.dev" ) ;
url . searchParams . delete ( "direct" ) ;
return url . pathname + url . search ;
2024-01-05 12:14:38 +00:00
}
let isFirstUpdate = true ;
2026-02-11 16:20:26 +00:00
const outdatedLinkTags = /* @__PURE__ */ new WeakSet ( ) ;
2024-01-05 12:14:38 +00:00
const debounceReload = ( time ) => {
2026-02-11 16:20:26 +00:00
let timer ;
return ( ) => {
if ( timer ) {
clearTimeout ( timer ) ;
timer = null ;
}
timer = setTimeout ( ( ) => {
location . reload ( ) ;
} , time ) ;
} ;
2024-01-05 12:14:38 +00:00
} ;
const pageReload = debounceReload ( 50 ) ;
2026-02-11 16:20:26 +00:00
const hmrClient = new HMRClient (
console ,
{
isReady : ( ) => socket && socket . readyState === 1 ,
send : ( message ) => socket . send ( message )
} ,
async function importUpdatedModule ( {
acceptedPath ,
timestamp ,
explicitImportRequired ,
isWithinCircularImport
} ) {
2024-01-05 12:14:38 +00:00
const [ acceptedPathWithoutQuery , query ] = acceptedPath . split ( ` ? ` ) ;
2026-02-11 16:20:26 +00:00
const importPromise = import (
/* @vite-ignore */
base + acceptedPathWithoutQuery . slice ( 1 ) + ` ? ${ explicitImportRequired ? "import&" : "" } t= ${ timestamp } ${ query ? ` & ${ query } ` : "" } `
) ;
if ( isWithinCircularImport ) {
importPromise . catch ( ( ) => {
console . info (
` [hmr] ${ acceptedPath } failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. To debug and break the circular import, you can run \` vite --debug hmr \` to log the circular dependency path if a file change triggered it. `
) ;
pageReload ( ) ;
} ) ;
}
return await importPromise ;
}
) ;
2024-01-05 12:14:38 +00:00
async function handleMessage ( payload ) {
2026-02-11 16:20:26 +00:00
switch ( payload . type ) {
case "connected" :
console . debug ( ` [vite] connected. ` ) ;
hmrClient . messenger . flush ( ) ;
setInterval ( ( ) => {
if ( socket . readyState === socket . OPEN ) {
socket . send ( '{"type":"ping"}' ) ;
}
} , _ _HMR _TIMEOUT _ _ ) ;
break ;
case "update" :
notifyListeners ( "vite:beforeUpdate" , payload ) ;
if ( hasDocument ) {
if ( isFirstUpdate && hasErrorOverlay ( ) ) {
location . reload ( ) ;
return ;
} else {
if ( enableOverlay ) {
clearErrorOverlay ( ) ;
}
isFirstUpdate = false ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
await Promise . all (
payload . updates . map ( async ( update ) => {
if ( update . type === "js-update" ) {
return hmrClient . queueUpdate ( update ) ;
}
const { path , timestamp } = update ;
const searchUrl = cleanUrl ( path ) ;
const el = Array . from (
document . querySelectorAll ( "link" )
) . find (
( e ) => ! outdatedLinkTags . has ( e ) && cleanUrl ( e . href ) . includes ( searchUrl )
) ;
if ( ! el ) {
return ;
}
const newPath = ` ${ base } ${ searchUrl . slice ( 1 ) } ${ searchUrl . includes ( "?" ) ? "&" : "?" } t= ${ timestamp } ` ;
return new Promise ( ( resolve ) => {
const newLinkTag = el . cloneNode ( ) ;
newLinkTag . href = new URL ( newPath , el . href ) . href ;
const removeOldEl = ( ) => {
el . remove ( ) ;
console . debug ( ` [vite] css hot updated: ${ searchUrl } ` ) ;
resolve ( ) ;
} ;
newLinkTag . addEventListener ( "load" , removeOldEl ) ;
newLinkTag . addEventListener ( "error" , removeOldEl ) ;
outdatedLinkTags . add ( el ) ;
el . after ( newLinkTag ) ;
} ) ;
} )
) ;
notifyListeners ( "vite:afterUpdate" , payload ) ;
break ;
case "custom" : {
notifyListeners ( payload . event , payload . data ) ;
break ;
}
case "full-reload" :
notifyListeners ( "vite:beforeFullReload" , payload ) ;
if ( hasDocument ) {
if ( payload . path && payload . path . endsWith ( ".html" ) ) {
const pagePath = decodeURI ( location . pathname ) ;
const payloadPath = base + payload . path . slice ( 1 ) ;
if ( pagePath === payloadPath || payload . path === "/index.html" || pagePath . endsWith ( "/" ) && pagePath + "index.html" === payloadPath ) {
pageReload ( ) ;
}
return ;
} else {
pageReload ( ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
break ;
case "prune" :
notifyListeners ( "vite:beforePrune" , payload ) ;
await hmrClient . prunePaths ( payload . paths ) ;
break ;
case "error" : {
notifyListeners ( "vite:error" , payload ) ;
if ( hasDocument ) {
const err = payload . err ;
if ( enableOverlay ) {
createErrorOverlay ( err ) ;
} else {
console . error (
` [vite] Internal Server Error
$ { err . message }
$ { err . stack } `
) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
break ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
default : {
const check = payload ;
return check ;
}
}
2024-01-05 12:14:38 +00:00
}
function notifyListeners ( event , data ) {
2026-02-11 16:20:26 +00:00
hmrClient . notifyListeners ( event , data ) ;
2024-01-05 12:14:38 +00:00
}
const enableOverlay = _ _HMR _ENABLE _OVERLAY _ _ ;
2026-02-11 16:20:26 +00:00
const hasDocument = "document" in globalThis ;
2024-01-05 12:14:38 +00:00
function createErrorOverlay ( err ) {
2026-02-11 16:20:26 +00:00
clearErrorOverlay ( ) ;
document . body . appendChild ( new ErrorOverlay ( err ) ) ;
2024-01-05 12:14:38 +00:00
}
function clearErrorOverlay ( ) {
2026-02-11 16:20:26 +00:00
document . querySelectorAll ( overlayId ) . forEach ( ( n ) => n . close ( ) ) ;
2024-01-05 12:14:38 +00:00
}
function hasErrorOverlay ( ) {
2026-02-11 16:20:26 +00:00
return document . querySelectorAll ( overlayId ) . length ;
}
async function waitForSuccessfulPing ( socketProtocol2 , hostAndPath , ms = 1e3 ) {
const pingHostProtocol = socketProtocol2 === "wss" ? "https" : "http" ;
const ping = async ( ) => {
try {
await fetch ( ` ${ pingHostProtocol } :// ${ hostAndPath } ` , {
mode : "no-cors" ,
headers : {
// Custom headers won't be included in a request with no-cors so (ab)use one of the
// safelisted headers to identify the ping request
Accept : "text/x-vite-ping"
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
} ) ;
return true ;
} catch {
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
return false ;
} ;
if ( await ping ( ) ) {
return ;
}
await wait ( ms ) ;
while ( true ) {
if ( document . visibilityState === "visible" ) {
if ( await ping ( ) ) {
break ;
}
await wait ( ms ) ;
} else {
await waitForWindowShow ( ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
}
2024-01-05 12:14:38 +00:00
}
function wait ( ms ) {
2026-02-11 16:20:26 +00:00
return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
2024-01-05 12:14:38 +00:00
}
function waitForWindowShow ( ) {
2026-02-11 16:20:26 +00:00
return new Promise ( ( resolve ) => {
const onChange = async ( ) => {
if ( document . visibilityState === "visible" ) {
resolve ( ) ;
document . removeEventListener ( "visibilitychange" , onChange ) ;
}
} ;
document . addEventListener ( "visibilitychange" , onChange ) ;
} ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
const sheetsMap = /* @__PURE__ */ new Map ( ) ;
if ( "document" in globalThis ) {
document . querySelectorAll ( "style[data-vite-dev-id]" ) . forEach ( ( el ) => {
sheetsMap . set ( el . getAttribute ( "data-vite-dev-id" ) , el ) ;
} ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
const cspNonce = "document" in globalThis ? document . querySelector ( "meta[property=csp-nonce]" ) ? . nonce : void 0 ;
2024-01-05 12:14:38 +00:00
let lastInsertedStyle ;
function updateStyle ( id , content ) {
2026-02-11 16:20:26 +00:00
let style = sheetsMap . get ( id ) ;
if ( ! style ) {
style = document . createElement ( "style" ) ;
style . setAttribute ( "type" , "text/css" ) ;
style . setAttribute ( "data-vite-dev-id" , id ) ;
style . textContent = content ;
if ( cspNonce ) {
style . setAttribute ( "nonce" , cspNonce ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
if ( ! lastInsertedStyle ) {
document . head . appendChild ( style ) ;
setTimeout ( ( ) => {
lastInsertedStyle = void 0 ;
} , 0 ) ;
} else {
lastInsertedStyle . insertAdjacentElement ( "afterend" , style ) ;
2024-01-05 12:14:38 +00:00
}
2026-02-11 16:20:26 +00:00
lastInsertedStyle = style ;
} else {
style . textContent = content ;
}
sheetsMap . set ( id , style ) ;
2024-01-05 12:14:38 +00:00
}
function removeStyle ( id ) {
2026-02-11 16:20:26 +00:00
const style = sheetsMap . get ( id ) ;
if ( style ) {
document . head . removeChild ( style ) ;
sheetsMap . delete ( id ) ;
}
2024-01-05 12:14:38 +00:00
}
function createHotContext ( ownerPath ) {
2026-02-11 16:20:26 +00:00
return new HMRContext ( hmrClient , ownerPath ) ;
2024-01-05 12:14:38 +00:00
}
function injectQuery ( url , queryToInject ) {
2026-02-11 16:20:26 +00:00
if ( url [ 0 ] !== "." && url [ 0 ] !== "/" ) {
return url ;
}
const pathname = url . replace ( /[?#].*$/ , "" ) ;
const { search , hash } = new URL ( url , "http://vite.dev" ) ;
return ` ${ pathname } ? ${ queryToInject } ${ search ? ` & ` + search . slice ( 1 ) : "" } ${ hash || "" } ` ;
2024-01-05 12:14:38 +00:00
}
export { ErrorOverlay , createHotContext , injectQuery , removeStyle , updateStyle } ;