Skip to content

Commit

Permalink
fix: handle escape sequences in import specifiers (#2162)
Browse files Browse the repository at this point in the history
fix #2083
  • Loading branch information
CHOYSEN authored Feb 24, 2021
1 parent 4c7a6bb commit bbda31e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 37 deletions.
2 changes: 1 addition & 1 deletion packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"dotenv": "^8.2.0",
"dotenv-expand": "^5.1.0",
"enquirer": "^2.3.6",
"es-module-lexer": "^0.3.26",
"es-module-lexer": "^0.4.0",
"estree-walker": "^2.0.2",
"etag": "^1.8.1",
"execa": "^5.0.0",
Expand Down
66 changes: 34 additions & 32 deletions packages/vite/src/node/plugins/importAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,17 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
e: end,
ss: expStart,
se: expEnd,
d: dynamicIndex
d: dynamicIndex,
// #2083 User may use escape path,
// so use imports[index].n to get the unescaped string
// @ts-ignore
n: specifier
} = imports[index]

const rawUrl = source.slice(start, end)
let url = rawUrl

// check import.meta usage
if (url === 'import.meta') {
if (rawUrl === 'import.meta') {
const prop = source.slice(end, end + 4)
if (prop === '.hot') {
hasHMR = true
Expand Down Expand Up @@ -301,69 +304,62 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
continue
}

// For dynamic id, check if it's a literal that we can resolve
let hasViteIgnore = false
let isLiteralDynamicId = false
if (dynamicIndex >= 0) {
// check @vite-ignore which suppresses dynamic import warning
hasViteIgnore = /\/\*\s*@vite-ignore\s*\*\//.test(url)
// #998 remove comment
url = url.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '').trim()
const literalIdMatch = url.match(/^(?:'([^']+)'|"([^"]+)")$/)
if (literalIdMatch) {
isLiteralDynamicId = true
url = literalIdMatch[1] || literalIdMatch[2]
}
}
const isDynamicImport = dynamicIndex >= 0

// static import or valid string in dynamic import
const isLiteralId = !!specifier

// If resolvable, let's resolve it
if (dynamicIndex === -1 || isLiteralDynamicId) {
if (isLiteralId) {
// skip external / data uri
if (isExternalUrl(url) || isDataUrl(url)) {
if (isExternalUrl(specifier) || isDataUrl(specifier)) {
continue
}
// skip ssr external
if (ssr) {
if (
server._ssrExternals &&
shouldExternalizeForSSR(url, server._ssrExternals)
shouldExternalizeForSSR(specifier, server._ssrExternals)
) {
continue
}
if (isBuiltin(url)) {
if (isBuiltin(specifier)) {
continue
}
}
// skip client
if (url === clientPublicPath) {
if (specifier === clientPublicPath) {
continue
}

// warn imports to non-asset /public files
if (
url.startsWith('/') &&
!config.assetsInclude(cleanUrl(url)) &&
!url.endsWith('.json') &&
checkPublicFile(url, config)
specifier.startsWith('/') &&
!config.assetsInclude(cleanUrl(specifier)) &&
!specifier.endsWith('.json') &&
checkPublicFile(specifier, config)
) {
throw new Error(
`Cannot import non-asset file ${url} which is inside /public.` +
`Cannot import non-asset file ${specifier} which is inside /public.` +
`JS/CSS files inside /public are copied as-is on build and ` +
`can only be referenced via <script src> or <link href> in html.`
)
}

// normalize
const [normalizedUrl, resolvedId] = await normalizeUrl(url, start)
url = normalizedUrl
const [normalizedUrl, resolvedId] = await normalizeUrl(
specifier,
start
)
let url = normalizedUrl

// rewrite
if (url !== rawUrl) {
if (url !== specifier) {
// for optimized cjs deps, support named imports by rewriting named
// imports to const assignments.
if (resolvedId.endsWith(`&es-interop`)) {
url = url.slice(0, -11)
if (isLiteralDynamicId) {
if (isDynamicImport) {
// rewrite `import('package')` to expose the default directly
str().overwrite(
dynamicIndex,
Expand All @@ -381,14 +377,20 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
}
}
} else {
str().overwrite(start, end, isLiteralDynamicId ? `'${url}'` : url)
str().overwrite(start, end, isDynamicImport ? `'${url}'` : url)
}
}

// record for HMR import chain analysis
// make sure to normalize away base
importedUrls.add(url.replace(base, '/'))
} else if (!importer.startsWith(clientDir) && !ssr) {
// check @vite-ignore which suppresses dynamic import warning
const hasViteIgnore = /\/\*\s*@vite-ignore\s*\*\//.test(rawUrl)

const url = rawUrl
.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '')
.trim()
if (!hasViteIgnore && !isSupportedDynamicImport(url)) {
this.warn(
`\n` +
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2751,10 +2751,10 @@ es-abstract@^1.18.0-next.1:
string.prototype.trimend "^1.0.3"
string.prototype.trimstart "^1.0.3"

es-module-lexer@^0.3.26:
version "0.3.26"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b"
integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==
es-module-lexer@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.0.tgz#21f4181cc8b7eee06855f1c59e6087c7bc4f77b0"
integrity sha512-iuEGihqqhKWFgh72Q/Jtch7V2t/ft8w8IPP2aEN8ArYKO+IWyo6hsi96hCdgyeEDQIV3InhYQ9BlwUFPGXrbEQ==

es-to-primitive@^1.2.1:
version "1.2.1"
Expand Down

0 comments on commit bbda31e

Please sign in to comment.