Skip to content

Commit 1d468c8

Browse files
authored
fix: escape character in string regexp match (#7834)
1 parent 0b2d307 commit 1d468c8

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

packages/vite/src/node/__tests__/cleanString.spec.ts

+19
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,25 @@ test('strings', () => {
3232
expect(clean).toMatch('const b = "\0\0\0\0"')
3333
})
3434

35+
test('escape character', () => {
36+
const clean = emptyString(`
37+
'1\\'1'
38+
"1\\"1"
39+
"1\\"1\\"1"
40+
"1\\'1'\\"1"
41+
"1'1'"
42+
"1'\\'1\\''\\"1\\"\\""
43+
'1"\\"1\\""\\"1\\"\\"'
44+
'""1""'
45+
'"""1"""'
46+
'""""1""""'
47+
"''1''"
48+
"'''1'''"
49+
"''''1''''"
50+
`)
51+
expect(clean).not.toMatch('1')
52+
})
53+
3554
test('strings comment nested', () => {
3655
expect(
3756
emptyString(`

packages/vite/src/node/cleanString.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import type { RollupError } from 'rollup'
22
// bank on the non-overlapping nature of regex matches and combine all filters into one giant regex
33
// /`([^`\$\{\}]|\$\{(`|\g<1>)*\})*`/g can match nested string template
44
// but js not support match expression(\g<0>). so clean string template(`...`) in other ways.
5-
const cleanerRE = /"[^"]*"|'[^']*'|\/\*(.|[\r\n])*?\*\/|\/\/.*/g
5+
const cleanerRE =
6+
/"([^"]|(?<=\\)")*"|'([^']|(?<=\\)')*'|\/\*(.|[\r\n])*?\*\/|\/\/.*/g
67

78
const blankReplacer = (s: string) => ' '.repeat(s.length)
89
const stringBlankReplacer = (s: string) =>
@@ -25,9 +26,16 @@ export function emptyString(raw: string): string {
2526
}
2627

2728
const enum LexerState {
29+
// template string
2830
inTemplateString,
2931
inInterpolationExpression,
30-
inObjectExpression
32+
inObjectExpression,
33+
// strings
34+
inSingleQuoteString,
35+
inDoubleQuoteString,
36+
// comments
37+
inMultilineCommentsRE,
38+
inSinglelineCommentsRE
3139
}
3240

3341
function replaceAt(

packages/vite/src/node/plugins/css.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@ export async function hoistAtRules(css: string) {
11221122
// to top when multiple files are concatenated.
11231123
// match until semicolon that's not in quotes
11241124
s.replace(
1125-
/@import\s*(?:url\([^\)]*\)|"[^"]*"|'[^']*'|[^;]*).*?;/gm,
1125+
/@import\s*(?:url\([^\)]*\)|"([^"]|(?<=\\)")*"|'([^']|(?<=\\)')*'|[^;]*).*?;/gm,
11261126
(match) => {
11271127
s.appendLeft(0, match)
11281128
return ''
@@ -1131,13 +1131,16 @@ export async function hoistAtRules(css: string) {
11311131
// #6333
11321132
// CSS @charset must be the top-first in the file, hoist the first to top
11331133
let foundCharset = false
1134-
s.replace(/@charset\s*(?:"[^"]*"|'[^']*'|[^;]*).*?;/gm, (match) => {
1135-
if (!foundCharset) {
1136-
s.prepend(match)
1137-
foundCharset = true
1134+
s.replace(
1135+
/@charset\s*(?:"([^"]|(?<=\\)")*"|'([^']|(?<=\\)')*'|[^;]*).*?;/gm,
1136+
(match) => {
1137+
if (!foundCharset) {
1138+
s.prepend(match)
1139+
foundCharset = true
1140+
}
1141+
return ''
11381142
}
1139-
return ''
1140-
})
1143+
)
11411144
return s.toString()
11421145
}
11431146

packages/vite/src/node/plugins/html.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ interface ScriptAssetsUrl {
4646
const htmlProxyRE = /\?html-proxy=?[&inline\-css]*&index=(\d+)\.(js|css)$/
4747
const inlineCSSRE = /__VITE_INLINE_CSS__([^_]+_\d+)__/g
4848
// Do not allow preceding '.', but do allow preceding '...' for spread operations
49-
const inlineImportRE = /(?<!(?<!\.\.)\.)\bimport\s*\(("[^"]*"|'[^']*')\)/g
49+
const inlineImportRE =
50+
/(?<!(?<!\.\.)\.)\bimport\s*\(("([^"]|(?<=\\)")*"|'([^']|(?<=\\)')*')\)/g
5051
const htmlLangRE = /\.(html|htm)$/
5152

5253
export const isHTMLProxy = (id: string): boolean => htmlProxyRE.test(id)

0 commit comments

Comments
 (0)