diff --git a/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts b/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts index 2332c0df0ecdf0..32333059ad7381 100644 --- a/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts +++ b/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts @@ -10,6 +10,18 @@ test('should load full dynamic import from public', async () => { await untilUpdated(() => page.textContent('.view'), 'Qux view', true) }) +test('should load data URL of `blob:`', async () => { + await page.click('.issue-2658-1') + await untilUpdated(() => page.textContent('.view'), 'blob', true) +}) + +test('should load data URL of `data:`', async () => { + await page.click('.issue-2658-2') + await untilUpdated(() => page.textContent('.view'), 'data', true) +}) + +// since this test has a timeout, it should be put last so that it +// does not bleed on the last test('should load dynamic import with vars', async () => { await page.click('.foo') await untilUpdated(() => page.textContent('.view'), 'Foo view', true) diff --git a/packages/playground/dynamic-import/index.html b/packages/playground/dynamic-import/index.html index ad5e7ab57c98b7..87bb6ebdaa37e8 100644 --- a/packages/playground/dynamic-import/index.html +++ b/packages/playground/dynamic-import/index.html @@ -2,6 +2,8 @@ + +
diff --git a/packages/playground/dynamic-import/nested/index.js b/packages/playground/dynamic-import/nested/index.js index 383e51f3d5dfdd..cc6522016fc1d8 100644 --- a/packages/playground/dynamic-import/nested/index.js +++ b/packages/playground/dynamic-import/nested/index.js @@ -21,6 +21,26 @@ document.querySelector('.qux').addEventListener('click', async () => { text('.view', msg) }) +// data URLs (`blob:`) +const code1 = 'export const msg = "blob"' +const blob = new Blob([code1], { type: 'text/javascript;charset=UTF-8' }) +// eslint-disable-next-line node/no-unsupported-features/node-builtins +const blobURL = URL.createObjectURL(blob) +document.querySelector('.issue-2658-1').addEventListener('click', async () => { + const { msg } = await import(/*@vite-ignore*/ blobURL) + text('.view', msg) +}) + +// data URLs (`data:`) +const code2 = 'export const msg = "data";' +const dataURL = `data:text/javascript;charset=utf-8,${encodeURIComponent( + code2 +)}` +document.querySelector('.issue-2658-2').addEventListener('click', async () => { + const { msg } = await import(/*@vite-ignore*/ dataURL) + text('.view', msg) +}) + function text(el, text) { document.querySelector(el).textContent = text } diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 6d2d8f46c400f0..81774bbab514b9 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -429,7 +429,13 @@ export const createHotContext = (ownerPath: string) => { export function injectQuery(url: string, queryToInject: string) { // can't use pathname from URL since it may be relative like ../ const pathname = url.replace(/#.*$/, '').replace(/\?.*$/, '') - const { search, hash } = new URL(url, 'http://vitejs.dev') + const { search, hash, protocol } = new URL(url, 'http://vitejs.dev') + + // data URLs shouldn't be appended queries, #2658 + if (protocol === 'blob:' || protocol === 'data:') { + return url + } + return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${ hash || '' }`