Skip to content

Commit

Permalink
fix: do not access document in /@vite/client when not defined (#16318)
Browse files Browse the repository at this point in the history
Co-authored-by: sapphi-red <49056869+sapphi-red@users.noreply.github.com>
  • Loading branch information
keyding and sapphi-red committed Apr 3, 2024
1 parent 445c4f2 commit 646319c
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 64 deletions.
77 changes: 44 additions & 33 deletions packages/vite/src/client/client.ts
Expand Up @@ -102,9 +102,11 @@ function setupWebSocket(

notifyListeners('vite:ws:disconnect', { webSocket: socket })

console.log(`[vite] server connection lost. polling for restart...`)
await waitForSuccessfulPing(protocol, hostAndPath)
location.reload()
if (hasDocument) {
console.log(`[vite] server connection lost. polling for restart...`)
await waitForSuccessfulPing(protocol, hostAndPath)
location.reload()
}
})

return socket
Expand Down Expand Up @@ -182,16 +184,20 @@ async function handleMessage(payload: HMRPayload) {
break
case 'update':
notifyListeners('vite:beforeUpdate', payload)
// if this is the first update and there's already an error overlay, it
// means the page opened with existing server compile error and the whole
// module script failed to load (since one of the nested imports is 500).
// in this case a normal update won't work and a full reload is needed.
if (isFirstUpdate && hasErrorOverlay()) {
window.location.reload()
return
} else {
clearErrorOverlay()
isFirstUpdate = false
if (hasDocument) {
// if this is the first update and there's already an error overlay, it
// means the page opened with existing server compile error and the whole
// module script failed to load (since one of the nested imports is 500).
// in this case a normal update won't work and a full reload is needed.
if (isFirstUpdate && hasErrorOverlay()) {
window.location.reload()
return
} else {
if (enableOverlay) {
clearErrorOverlay()
}
isFirstUpdate = false
}
}
await Promise.all(
payload.updates.map(async (update): Promise<void> => {
Expand Down Expand Up @@ -249,21 +255,23 @@ async function handleMessage(payload: HMRPayload) {
}
case 'full-reload':
notifyListeners('vite:beforeFullReload', payload)
if (payload.path && payload.path.endsWith('.html')) {
// if html file is edited, only reload the page if the browser is
// currently on that page.
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)
) {
if (hasDocument) {
if (payload.path && payload.path.endsWith('.html')) {
// if html file is edited, only reload the page if the browser is
// currently on that page.
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()
}
return
} else {
pageReload()
}
break
case 'prune':
Expand All @@ -272,13 +280,15 @@ async function handleMessage(payload: HMRPayload) {
break
case 'error': {
notifyListeners('vite:error', payload)
const err = payload.err
if (enableOverlay) {
createErrorOverlay(err)
} else {
console.error(
`[vite] Internal Server Error\n${err.message}\n${err.stack}`,
)
if (hasDocument) {
const err = payload.err
if (enableOverlay) {
createErrorOverlay(err)
} else {
console.error(
`[vite] Internal Server Error\n${err.message}\n${err.stack}`,
)
}
}
break
}
Expand All @@ -298,6 +308,7 @@ function notifyListeners(event: string, data: any): void {
}

const enableOverlay = __HMR_ENABLE_OVERLAY__
const hasDocument = 'document' in globalThis

function createErrorOverlay(err: ErrorPayload['err']) {
clearErrorOverlay()
Expand Down
59 changes: 31 additions & 28 deletions packages/vite/src/client/overlay.ts
Expand Up @@ -165,39 +165,41 @@ kbd {
`

// Error Template
const template = h(
'div',
{ class: 'backdrop', part: 'backdrop' },
let template: HTMLElement
const createTemplate = () =>
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' }),
{ class: 'backdrop', part: 'backdrop' },
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),
'.',
{ 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),
)
h('style', {}, templateStyle),
)

const fileRE = /(?:[a-zA-Z]:\\|\/).*?:\d+:\d+/g
const codeframeRE = /^(?:>?\s*\d+\s+\|.*|\s+\|\s*\^.*)\r?\n/gm
Expand All @@ -213,6 +215,7 @@ export class ErrorOverlay extends HTMLElement {
super()
this.root = this.attachShadow({ mode: 'open' })

template ??= createTemplate()
this.root.appendChild(template)

codeframeRE.lastIndex = 0
Expand Down
2 changes: 1 addition & 1 deletion playground/worker/__tests__/es/worker-es.spec.ts
Expand Up @@ -200,7 +200,7 @@ test('emit chunk', async () => {
)
await untilUpdated(
() => page.textContent('.emit-chunk-dynamic-import-worker'),
'"A string/es/"',
'"A stringmodule1/es/"',
true,
)
})
Expand Down
Expand Up @@ -141,7 +141,7 @@ test.runIf(isBuild)('emit chunk', async () => {
)
await untilUpdated(
() => page.textContent('.emit-chunk-dynamic-import-worker'),
'"A string./"',
'"A stringmodule1./"',
true,
)
})
Expand Down
6 changes: 5 additions & 1 deletion playground/worker/emit-chunk-dynamic-import-worker.js
@@ -1,5 +1,9 @@
import module1Url from './modules/module1.js?url'

import('./modules/module0').then((module) => {
self.postMessage(module.default + import.meta.env.BASE_URL)
import(/* @vite-ignore */ module1Url).then((module1) => {
self.postMessage(module.default + module1.msg1 + import.meta.env.BASE_URL)
})
})

// for sourcemap
Expand Down

0 comments on commit 646319c

Please sign in to comment.