Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 102 additions & 2 deletions packages/vite/src/node/__tests__/plugins/hooks.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import path from 'node:path'
import { describe, expect, onTestFinished, test } from 'vitest'
import { describe, expect, onTestFinished, test, vi } from 'vitest'
import { build } from '../../build'
import type { Plugin } from '../../plugin'
import { resolveConfig } from '../../config'
import { createServer } from '../../server'
import { preview } from '../../preview'
import { promiseWithResolvers } from '../../../shared/utils'
import { type Logger, createLogger } from '../../logger'

const resolveConfigWithPlugin = (
plugin: Plugin,
Expand Down Expand Up @@ -33,12 +34,16 @@ const resolveEntryPlugin: Plugin = {
},
}

const createServerWithPlugin = async (plugin: Plugin) => {
const createServerWithPlugin = async (
plugin: Plugin,
customLogger?: Logger,
) => {
const server = await createServer({
configFile: false,
root: import.meta.dirname,
plugins: [plugin, resolveEntryPlugin],
logLevel: 'error',
customLogger,
server: {
middlewareMode: true,
ws: false,
Expand Down Expand Up @@ -346,3 +351,98 @@ describe('supports plugin context', () => {
await server.close()
})
})

describe('watcher add/unlink error handling', () => {
test("'add' event logs error when watchChange throws", async () => {
const { promise, resolve } = promiseWithResolvers<void>()
const error = new Error('async watchChange error')

const logError = vi.fn()
const logger = createLogger('error')
logger.error = (...args) => {
logError(...args)
resolve()
}

const server = await createServerWithPlugin(
{
name: 'test',
watchChange() {
return Promise.reject(error)
},
},
logger,
)

server.watcher.emit(
'add',
path.resolve(import.meta.dirname, 'some-file.js'),
)

await promise
expect(logError).toHaveBeenCalled()
expect(logError).toHaveBeenCalledWith(error)
})

test("'change' event logs error when watchChange throws", async () => {
const { promise, resolve } = promiseWithResolvers<void>()
const error = new Error('async watchChange error')

const logError = vi.fn()
const logger = createLogger('error')
logger.error = (...args) => {
logError(...args)
resolve()
}

const server = await createServerWithPlugin(
{
name: 'test',
watchChange() {
return Promise.reject(error)
},
},
logger,
)

server.watcher.emit(
'change',
path.resolve(import.meta.dirname, 'some-file.js'),
)

await promise
expect(logError).toHaveBeenCalled()
expect(logError).toHaveBeenCalledWith(error)
})

test("'unlink' event logs error when watchChange throws", async () => {
const { promise, resolve } = promiseWithResolvers<void>()
const error = new Error('async watchChange error')

const logError = vi.fn()
const logger = createLogger('error')
logger.error = (...args) => {
logError(...args)
resolve()
}

const server = await createServerWithPlugin(
{
name: 'test',
watchChange() {
return Promise.reject(error)
},
},
logger,
)

server.watcher.emit(
'unlink',
path.resolve(import.meta.dirname, 'some-file.js'),
)

await promise
expect(logError).toHaveBeenCalled()
expect(logError).toHaveBeenCalledWith(error)
})
})
10 changes: 7 additions & 3 deletions packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ export async function _createServer(
await onHMRUpdate(isUnlink ? 'delete' : 'create', file)
}

watcher.on('change', async (file) => {
const onFileChange = async (file: string) => {
file = normalizePath(file)
reloadOnTsconfigChange(server, file)

Expand All @@ -901,13 +901,17 @@ export async function _createServer(
environment.moduleGraph.onFileChange(file)
}
await onHMRUpdate('update', file)
}

watcher.on('change', (file) => {
onFileChange(file).catch((e) => server.config.logger.error(e))
})

watcher.on('add', (file) => {
onFileAddUnlink(file, false)
onFileAddUnlink(file, false).catch((e) => server.config.logger.error(e))
})
watcher.on('unlink', (file) => {
onFileAddUnlink(file, true)
onFileAddUnlink(file, true).catch((e) => server.config.logger.error(e))
})

if (!middlewareMode && httpServer) {
Expand Down