From d5d9a3155cda835bd9e8b7c53a879e26e1c6497a Mon Sep 17 00:00:00 2001
From: Jonas Kaltenbach
Date: Tue, 16 May 2023 16:34:48 +0200
Subject: [PATCH] fix(assetImportMetaUrl): allow ternary operator in template
literal urls (#13121)
---
.../src/node/plugins/assetImportMetaUrl.ts | 27 +++++++++++++++----
playground/assets/__tests__/assets.spec.ts | 11 ++++++++
playground/assets/index.html | 21 +++++++++++++++
3 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts
index c20abbdc953406..369e8a5e12026f 100644
--- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts
+++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts
@@ -68,11 +68,14 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
// potential dynamic template string
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
- let [pureUrl, queryString = ''] = rawUrl.split('?')
- if (queryString) {
- pureUrl += '`'
- queryString = '?' + queryString.slice(0, -1)
- }
+ const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
+ const hasQueryDelimiter = queryDelimiterIndex !== -1
+ const pureUrl = hasQueryDelimiter
+ ? rawUrl.slice(0, queryDelimiterIndex) + '`'
+ : rawUrl
+ const queryString = hasQueryDelimiter
+ ? rawUrl.slice(queryDelimiterIndex, -1)
+ : ''
const ast = this.parse(pureUrl)
const templateLiteral = (ast as any).body[0].expression
if (templateLiteral.expressions.length) {
@@ -180,3 +183,17 @@ function buildGlobPattern(ast: any) {
}
return pattern
}
+
+function getQueryDelimiterIndex(rawUrl: string): number {
+ let bracketsStack = 0
+ for (let i = 0; i < rawUrl.length; i++) {
+ if (rawUrl[i] === '{') {
+ bracketsStack++
+ } else if (rawUrl[i] === '}') {
+ bracketsStack--
+ } else if (rawUrl[i] === '?' && bracketsStack === 0) {
+ return i
+ }
+ }
+ return -1
+}
diff --git a/playground/assets/__tests__/assets.spec.ts b/playground/assets/__tests__/assets.spec.ts
index d4a16dafde7404..5325f873ea6600 100644
--- a/playground/assets/__tests__/assets.spec.ts
+++ b/playground/assets/__tests__/assets.spec.ts
@@ -344,6 +344,17 @@ test('new URL(`./${dynamic}?abc`, import.meta.url)', async () => {
)
})
+test('new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)', async () => {
+ expect(await page.textContent('.dynamic-import-meta-url-1-ternary')).toMatch(
+ isBuild ? 'data:image/png;base64' : '/foo/nested/icon.png?abc',
+ )
+ expect(await page.textContent('.dynamic-import-meta-url-2-ternary')).toMatch(
+ isBuild
+ ? /\/foo\/assets\/asset-\w{8}\.png\?abc/
+ : '/foo/nested/asset.png?abc',
+ )
+})
+
test('new URL(`non-existent`, import.meta.url)', async () => {
expect(await page.textContent('.non-existent-import-meta-url')).toMatch(
new URL('non-existent', page.url()).pathname,
diff --git a/playground/assets/index.html b/playground/assets/index.html
index f8c1f5a515a140..5b30b733c2f9c9 100644
--- a/playground/assets/index.html
+++ b/playground/assets/index.html
@@ -239,6 +239,16 @@ new URL(`./${dynamic}?abc`, import.meta.url)
+new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)
+
+
+
+
+
+
+
+
+
new URL(`non-existent`, import.meta.url)
@@ -468,6 +478,17 @@
assets in noscript
testDynamicImportMetaUrlWithQuery('icon', 1)
testDynamicImportMetaUrlWithQuery('asset', 2)
+ function testDynamicImportMetaUrlWithTernaryOperator(name, i) {
+ // prettier-ignore
+ const metaUrl = new URL(`./nested/${1 === 0 ? 'failed' : name}.png?abc`, import.meta.url,)
+ text(`.dynamic-import-meta-url-${i}-ternary`, metaUrl)
+ document.querySelector(`.dynamic-import-meta-url-img-${i}-ternary`).src =
+ metaUrl
+ }
+
+ testDynamicImportMetaUrlWithTernaryOperator('icon', 1)
+ testDynamicImportMetaUrlWithTernaryOperator('asset', 2)
+
{
const name = 'test'
const js = new URL(`./nested/${name}.js`, import.meta.url).href