Skip to content
29 changes: 15 additions & 14 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,32 +155,25 @@ export default defineConfig(
'@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/prefer-for-of': 'off',
'@typescript-eslint/prefer-function-type': 'off',
// disable typecheck-specific rules (but worth revisiting again)
'@typescript-eslint/await-thenable': 'off',
'@typescript-eslint/dot-notation': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/no-duplicate-type-constituents': 'off',
'@typescript-eslint/no-implied-eval': 'off',
// disable typecheck-specific rules
'@typescript-eslint/await-thenable': 'off', // does not handle `void | Promise<void>` well
'@typescript-eslint/no-base-to-string': 'off', // does not matter for us
'@typescript-eslint/no-implied-eval': 'off', // we intentionally use `Function()`
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/no-redundant-type-constituents': 'off',
'@typescript-eslint/no-redundant-type-constituents': 'off', // hard to handle some cases
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-enum-comparison': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/non-nullable-type-assertion-style': 'off',
'@typescript-eslint/only-throw-error': 'off',
'@typescript-eslint/prefer-includes': 'off',
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'@typescript-eslint/prefer-optional-chain': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'off',
'@typescript-eslint/prefer-string-starts-ends-with': 'off',
'@typescript-eslint/prefer-string-starts-ends-with': 'off', // prefer indexed access for better performance
'@typescript-eslint/require-await': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/restrict-template-expressions': 'off', // does not matter for us
'@typescript-eslint/unbound-method': 'off',

'import-x/no-duplicates': 'error',
Expand Down Expand Up @@ -376,6 +369,14 @@ export default defineConfig(
'@typescript-eslint/ban-ts-comment': 'off',
},
},
{
name: 'disables/test-dts',
files: ['**/__tests_dts__/**/*.?([cm])[jt]s?(x)'],
rules: {
// disable typecheck-specific rules
'@typescript-eslint/no-duplicate-type-constituents': 'off',
},
},
{
name: 'disables/typechecking',
files: [
Expand Down
7 changes: 5 additions & 2 deletions packages/vite/rolldown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'node:path'
import MagicString from 'magic-string'
import type { Plugin } from 'rolldown'
import { defineConfig } from 'rolldown'
import { init, parse } from 'es-module-lexer'
import { ImportType, init, parse } from 'es-module-lexer'
import licensePlugin from './rollupLicensePlugin'

// eslint-disable-next-line n/no-unsupported-features/node-builtins
Expand Down Expand Up @@ -321,7 +321,10 @@ function buildTimeImportMetaUrlPlugin(): Plugin {
const s = new MagicString(code)
const [imports] = parse(code)
for (const { t, ss, se } of imports) {
if (t === 3 && code.slice(se, se + 4) === '.url') {
if (
t === ImportType.ImportMeta &&
code.slice(se, se + 4) === '.url'
) {
// ignore import.meta.url with /** #__KEEP__ */ comment
if (keepCommentRE.test(code.slice(0, ss))) {
keepCommentRE.lastIndex = 0
Expand Down
1 change: 1 addition & 0 deletions packages/vite/rollupLicensePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function licensePlugin(
// MIT Licensed https://github.com/rollup/rollup/blob/master/LICENSE-CORE.md
const coreLicense = fs.readFileSync(
new URL('../../LICENSE', import.meta.url),
'utf-8',
)

const deps = sortDependencies(dependencies)
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ function waitForSuccessfulPing(socketUrl: string) {
document.removeEventListener('visibilitychange', onVisibilityChange)
sharedWorker.port.close()

const data: { type: 'success' } | { type: 'error'; error: unknown } =
const data: { type: 'success' } | { type: 'error'; error: Error } =
event.data
if (data.type === 'error') {
reject(data.error)
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/module-runner/evaluatedModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class EvaluatedModuleNode {
public evaluated = false
public meta: ResolvedResult | undefined
public promise: Promise<any> | undefined
public exports: any | undefined
public exports: any
public file: string
public map: DecodedMap | undefined

Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/module-runner/sourcemap/interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ function CallSiteToString(this: CallSite) {
} else {
fileName = this.getScriptNameOrSourceURL()
if (!fileName && this.isEval()) {
fileLocation = this.getEvalOrigin() as string
fileLocation = this.getEvalOrigin()!
fileLocation += ', ' // Expecting source position to follow.
}

Expand Down Expand Up @@ -388,7 +388,7 @@ function wrapCallSite(frame: CallSite, state: State) {
return position.column + 1
}
frame.getScriptNameOrSourceURL = function () {
return position.source as string
return position.source!
}
return frame
}
Expand Down
19 changes: 7 additions & 12 deletions packages/vite/src/module-runner/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,14 @@ const questionRegex = /\?/g
const hashRegex = /#/g

function encodePathChars(filepath: string) {
if (filepath.indexOf('%') !== -1)
filepath = filepath.replace(percentRegEx, '%25')
if (filepath.includes('%')) filepath = filepath.replace(percentRegEx, '%25')
// In posix, backslash is a valid character in paths:
if (!isWindows && filepath.indexOf('\\') !== -1)
if (!isWindows && filepath.includes('\\'))
filepath = filepath.replace(backslashRegEx, '%5C')
if (filepath.indexOf('\n') !== -1)
filepath = filepath.replace(newlineRegEx, '%0A')
if (filepath.indexOf('\r') !== -1)
if (filepath.includes('\n')) filepath = filepath.replace(newlineRegEx, '%0A')
if (filepath.includes('\r'))
filepath = filepath.replace(carriageReturnRegEx, '%0D')
if (filepath.indexOf('\t') !== -1)
filepath = filepath.replace(tabRegEx, '%09')
if (filepath.includes('\t')) filepath = filepath.replace(tabRegEx, '%09')
return filepath
}

Expand All @@ -59,10 +56,8 @@ export function posixPathToFileHref(posixPath: string): string {
// Therefore, encoding is required to eliminate parsing them in different states.
// This is done as an optimization to not creating a URL instance and
// later triggering pathname setter, which impacts performance
if (resolved.indexOf('?') !== -1)
resolved = resolved.replace(questionRegex, '%3F')
if (resolved.indexOf('#') !== -1)
resolved = resolved.replace(hashRegex, '%23')
if (resolved.includes('?')) resolved = resolved.replace(questionRegex, '%3F')
if (resolved.includes('#')) resolved = resolved.replace(hashRegex, '%23')
return new URL(`file://${resolved}`).href
}

Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const stopProfiler = (
): void | Promise<void> => {
if (!profileSession) return
return new Promise((res, rej) => {
profileSession!.post('Profiler.stop', (err: any, { profile }: any) => {
profileSession!.post('Profiler.stop', (err, { profile }) => {
// Write profile to disk, upload, etc.
if (!err) {
const outPath = path.resolve(
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export function loadEnv(
// these are typically provided inline and should be prioritized
for (const key in process.env) {
if (prefixes.some((prefix) => key.startsWith(prefix))) {
env[key] = process.env[key] as string
env[key] = process.env[key]!
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/vite/src/node/plugins/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ export function registerCustomMime(): void {
// https://github.com/lukeed/mrmime/issues/3
// instead of `image/vnd.microsoft.icon` which is registered on IANA Media Types DB
// image/x-icon should be used instead for better compatibility (https://github.com/h5bp/html5-boilerplate/issues/219)
mrmime.mimes['ico'] = 'image/x-icon'
mrmime.mimes.ico = 'image/x-icon'
// https://mimesniff.spec.whatwg.org/#matching-an-image-type-pattern
mrmime.mimes['cur'] = 'image/x-icon'
mrmime.mimes.cur = 'image/x-icon'
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#flac
mrmime.mimes['flac'] = 'audio/flac'
mrmime.mimes.flac = 'audio/flac'
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
mrmime.mimes['eot'] = 'application/vnd.ms-fontobject'
mrmime.mimes.eot = 'application/vnd.ms-fontobject'
}

export function renderAssetUrlInJS(
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2467,7 +2467,7 @@ async function loadSss(root: string): Promise<PostCSS.Syntax> {
return cachedSss
}

declare const window: unknown | undefined
declare const window: unknown
declare const location: { href: string } | undefined

// in unix, scss might append `location.href` in environments that shim `location`
Expand Down
19 changes: 10 additions & 9 deletions packages/vite/src/node/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,13 @@ export async function traverseHtml(
visitor: (node: DefaultTreeAdapterMap['node']) => void,
): Promise<void> {
// lazy load compiler
const { parse } = await import('parse5')
const { parse, ErrorCodes } = await import('parse5')
const warnings: ParseWarnings = {}
const ast = parse(html, {
scriptingEnabled: false, // parse inside <noscript>
sourceCodeLocationInfo: true,
onParseError: (e: ParserError) => {
handleParseError(e, html, filePath, warnings)
handleParseError(e, ErrorCodes, html, filePath, warnings)
},
})
traverseNodes(ast, visitor)
Expand All @@ -239,7 +239,7 @@ export function getScriptInfo(node: DefaultTreeAdapterMap['element']): {
if (p.name === 'src') {
if (!src) {
src = p
srcSourceCodeLocation = node.sourceCodeLocation?.attrs!['src']
srcSourceCodeLocation = node.sourceCodeLocation?.attrs!.src
}
} else if (p.name === 'type' && p.value === 'module') {
isModule = true
Expand Down Expand Up @@ -316,25 +316,26 @@ function formatParseError(parserError: ParserError, id: string, html: string) {

function handleParseError(
parserError: ParserError,
errorCodes: typeof ErrorCodes,
html: string,
filePath: string,
warnings: ParseWarnings,
) {
switch (parserError.code) {
case 'missing-doctype':
case errorCodes.missingDoctype:
// ignore missing DOCTYPE
return
case 'abandoned-head-element-child':
case errorCodes.abandonedHeadElementChild:
// Accept elements without closing tag in <head>
return
case 'duplicate-attribute':
case errorCodes.duplicateAttribute:
// Accept duplicate attributes #5966
// The first attribute is used, browsers silently ignore duplicates
return
case 'non-void-html-element-start-tag-with-trailing-solidus':
case errorCodes.nonVoidHtmlElementStartTagWithTrailingSolidus:
// Allow self closing on non-void elements #10439
return
case 'unexpected-question-mark-instead-of-tag-name':
case errorCodes.unexpectedQuestionMarkInsteadOfTagName:
// Allow <?xml> declaration and <?> empty elements
// lit generates <?>: https://github.com/lit/lit/issues/2470
return
Expand Down Expand Up @@ -1085,7 +1086,7 @@ export function findNeedTransformStyleAttribute(
(prop.value.includes('url(') || prop.value.includes('image-set(')),
)
if (!attr) return undefined
const location = node.sourceCodeLocation?.attrs?.['style']
const location = node.sourceCodeLocation?.attrs?.style
return { attr, location }
}

Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin[] {

renderChunk(code, _, { format }) {
// make sure we only perform the preload logic in modern builds.
if (code.indexOf(isModernFlag) > -1) {
if (code.includes(isModernFlag)) {
const re = new RegExp(isModernFlag, 'g')
const isModern = String(format === 'es')
const isModernWithPadding =
Expand Down Expand Up @@ -299,7 +299,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin[] {
const chunk = bundle[file]
// can't use chunk.dynamicImports.length here since some modules e.g.
// dynamic import to constant json may get inlined.
if (chunk.type === 'chunk' && chunk.code.indexOf(preloadMarker) > -1) {
if (chunk.type === 'chunk' && chunk.code.includes(preloadMarker)) {
const code = chunk.code
let imports!: ImportSpecifier[]
try {
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ export function getSortedPluginsByHotUpdateHook(
normal = 0,
post = 0
for (const plugin of plugins) {
const hook = plugin['hotUpdate'] ?? plugin['handleHotUpdate']
const hook = plugin.hotUpdate ?? plugin.handleHotUpdate
if (hook) {
if (typeof hook === 'object') {
if (hook.order === 'pre') {
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ export async function _createServer(
// ping request handler
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
middlewares.use(function viteHMRPingMiddleware(req, res, next) {
if (req.headers['accept'] === 'text/x-vite-ping') {
if (req.headers.accept === 'text/x-vite-ping') {
res.writeHead(204).end()
} else {
next()
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/middlewares/static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export function servePublicMiddleware(

const toFilePath = (url: string) => {
let filePath = cleanUrl(url)
if (filePath.indexOf('%') !== -1) {
if (filePath.includes('%')) {
try {
filePath = decodeURI(filePath)
} catch {
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/pluginContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@ class PluginContext

private _formatLog<E extends RollupLog>(
e: string | E,
position?: number | { column: number; line: number } | undefined,
position?: number | { column: number; line: number },
): E {
const err = (typeof e === 'string' ? new Error(e) : e) as E
if (err.pluginCode) {
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const createFilter = _createFilter as (
include?: FilterPattern,
exclude?: FilterPattern,
options?: { resolve?: string | false | null },
) => (id: string | unknown) => boolean
) => (id: unknown) => boolean

export { withFilter } from 'rolldown/filter'

Expand Down
Loading