From c6870f37161f479b4306826e1e4d8e42ed01d6a8 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Wed, 17 Aug 2022 03:13:37 +0800 Subject: [PATCH] fix: dynamic import path contain ../ and its own directory (#9350) --- .../__snapshots__/parse.test.ts.snap | 4 ++++ .../plugins/dynamicImportVar/parse.test.ts | 18 +++++++++++++-- .../src/node/plugins/dynamicImportVars.ts | 23 ++++++++++++++++--- .../__tests__/dynamic-import.spec.ts | 16 +++++++++++++ playground/dynamic-import/index.html | 4 ++++ playground/dynamic-import/nested/index.js | 9 ++++++++ .../dynamic-import/nested/nested/self.js | 1 + playground/dynamic-import/nested/self.js | 1 + 8 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 playground/dynamic-import/nested/nested/self.js create mode 100644 playground/dynamic-import/nested/self.js diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap index be73ec998bc834..b5f649d6bc336b 100644 --- a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap @@ -8,6 +8,10 @@ exports[`parse positives > alias path 1`] = `"__variableDynamicImportRuntimeHelp exports[`parse positives > basic 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\")), \`./mods/\${base}.js\`)"`; +exports[`parse positives > with ../ and itself 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"../dynamicImportVar/*.js\\")), \`./\${name}.js\`)"`; + +exports[`parse positives > with multi ../ and itself 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"../../plugins/dynamicImportVar/*.js\\")), \`./\${name}.js\`)"`; + exports[`parse positives > with query raw 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\", {\\"as\\":\\"raw\\",\\"import\\":\\"*\\"})), \`./mods/\${base}.js\`)"`; exports[`parse positives > with query url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\")), \`./mods/\${base}.js\`)"`; diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts index ba619c90e509ef..422dcb59ca5b37 100644 --- a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts @@ -1,5 +1,6 @@ import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' +import { normalizePath } from 'vite' import { describe, expect, it } from 'vitest' import { transformDynamicImport } from '../../../plugins/dynamicImportVars' @@ -7,8 +8,11 @@ const __dirname = resolve(fileURLToPath(import.meta.url), '..') async function run(input: string) { const { glob, rawPattern } = - (await transformDynamicImport(input, resolve(__dirname, 'index.js'), (id) => - id.replace('@', resolve(__dirname, './mods/')) + (await transformDynamicImport( + input, + normalizePath(resolve(__dirname, 'index.js')), + (id) => id.replace('@', resolve(__dirname, './mods/')), + __dirname )) || {} return `__variableDynamicImportRuntimeHelper(${glob}, \`${rawPattern}\`)` } @@ -37,4 +41,14 @@ describe('parse positives', () => { it('? in url', async () => { expect(await run('`./mo?ds/${base ?? foo}.js?raw`')).toMatchSnapshot() }) + + it('with ../ and itself', async () => { + expect(await run('`../dynamicImportVar/${name}.js`')).toMatchSnapshot() + }) + + it('with multi ../ and itself', async () => { + expect( + await run('`../../plugins/dynamicImportVar/${name}.js`') + ).toMatchSnapshot() + }) }) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index b7d5ed5a5f8792..93250f74618316 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -14,6 +14,7 @@ import { requestQuerySplitRE, transformStableResult } from '../utils' +import { toAbsoluteGlob } from './importMetaGlob' export const dynamicImportHelperId = '/@vite/dynamic-import-helper' @@ -77,7 +78,8 @@ export async function transformDynamicImport( resolve: ( url: string, importer?: string - ) => Promise | string | undefined + ) => Promise | string | undefined, + root: string ): Promise<{ glob: string pattern: string @@ -105,10 +107,20 @@ export async function transformDynamicImport( const params = globParams ? `, ${JSON.stringify({ ...globParams, import: '*' })}` : '' + + let newRawPattern = posix.relative( + posix.dirname(importer), + await toAbsoluteGlob(rawPattern, root, importer, resolve) + ) + + if (!/^\.{1,2}\//.test(newRawPattern)) { + newRawPattern = `./${newRawPattern}` + } + const exp = `(import.meta.glob(${JSON.stringify(userPattern)}${params}))` return { - rawPattern, + rawPattern: newRawPattern, pattern: userPattern, glob: exp } @@ -183,7 +195,12 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { // parenthesis, so we manually remove them for now. // See https://github.com/guybedford/es-module-lexer/issues/118 const importSource = removeComments(source.slice(start, end)).trim() - result = await transformDynamicImport(importSource, importer, resolve) + result = await transformDynamicImport( + importSource, + importer, + resolve, + config.root + ) } catch (error) { if (warnOnError) { this.warn(error) diff --git a/playground/dynamic-import/__tests__/dynamic-import.spec.ts b/playground/dynamic-import/__tests__/dynamic-import.spec.ts index 0612cf7808410b..cec996b46a669f 100644 --- a/playground/dynamic-import/__tests__/dynamic-import.spec.ts +++ b/playground/dynamic-import/__tests__/dynamic-import.spec.ts @@ -97,3 +97,19 @@ test('should load dynamic import with css in package', async () => { await page.click('.pkg-css') await untilUpdated(() => getColor('.pkg-css'), 'blue', true) }) + +test('should work with load ../ and itself directory', async () => { + await untilUpdated( + () => page.textContent('.dynamic-import-self'), + 'dynamic-import-self-content', + true + ) +}) + +test('should work with load ../ and contain itself directory', async () => { + await untilUpdated( + () => page.textContent('.dynamic-import-nested-self'), + 'dynamic-import-nested-self-content', + true + ) +}) diff --git a/playground/dynamic-import/index.html b/playground/dynamic-import/index.html index 997ad059ad6821..8eb5e60098a15c 100644 --- a/playground/dynamic-import/index.html +++ b/playground/dynamic-import/index.html @@ -21,6 +21,10 @@
+
+ +
+