diff --git a/packages/vite/src/node/__tests__/plugins/import.spec.ts b/packages/vite/src/node/__tests__/plugins/import.spec.ts index fb9ae3b132325c..89fbd80d8ecdc1 100644 --- a/packages/vite/src/node/__tests__/plugins/import.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/import.spec.ts @@ -18,7 +18,7 @@ describe('transformCjsImport', () => { test('import specifier', () => { expect( transformCjsImport( - 'import { useState, Component } from "react"', + 'import { useState, Component, "👋" as fake } from "react"', url, rawUrl, 0, @@ -28,7 +28,8 @@ describe('transformCjsImport', () => { ).toBe( 'import __vite__cjsImport0_react from "./node_modules/.vite/deps/react.js"; ' + 'const useState = __vite__cjsImport0_react["useState"]; ' + - 'const Component = __vite__cjsImport0_react["Component"]', + 'const Component = __vite__cjsImport0_react["Component"]; ' + + 'const fake = __vite__cjsImport0_react["👋"]', ) }) @@ -111,7 +112,7 @@ describe('transformCjsImport', () => { test('export name specifier', () => { expect( transformCjsImport( - 'export { useState, Component } from "react"', + 'export { useState, Component, "👋" } from "react"', url, rawUrl, 0, @@ -120,14 +121,15 @@ describe('transformCjsImport', () => { ), ).toBe( 'import __vite__cjsImport0_react from "./node_modules/.vite/deps/react.js"; ' + - 'const __vite__cjsExport_useState = __vite__cjsImport0_react["useState"]; ' + - 'const __vite__cjsExport_Component = __vite__cjsImport0_react["Component"]; ' + - 'export { __vite__cjsExport_useState as useState, __vite__cjsExport_Component as Component }', + 'const __vite__cjsExportI_useState = __vite__cjsImport0_react["useState"]; ' + + 'const __vite__cjsExportI_Component = __vite__cjsImport0_react["Component"]; ' + + 'const __vite__cjsExportL_1d0452e3 = __vite__cjsImport0_react["👋"]; ' + + 'export { __vite__cjsExportI_useState as useState, __vite__cjsExportI_Component as Component, __vite__cjsExportL_1d0452e3 as "👋" }', ) expect( transformCjsImport( - 'export { useState as useStateAlias, Component as ComponentAlias } from "react"', + 'export { useState as useStateAlias, Component as ComponentAlias, "👋" as "👍" } from "react"', url, rawUrl, 0, @@ -136,9 +138,10 @@ describe('transformCjsImport', () => { ), ).toBe( 'import __vite__cjsImport0_react from "./node_modules/.vite/deps/react.js"; ' + - 'const __vite__cjsExport_useStateAlias = __vite__cjsImport0_react["useState"]; ' + - 'const __vite__cjsExport_ComponentAlias = __vite__cjsImport0_react["Component"]; ' + - 'export { __vite__cjsExport_useStateAlias as useStateAlias, __vite__cjsExport_ComponentAlias as ComponentAlias }', + 'const __vite__cjsExportI_useStateAlias = __vite__cjsImport0_react["useState"]; ' + + 'const __vite__cjsExportI_ComponentAlias = __vite__cjsImport0_react["Component"]; ' + + 'const __vite__cjsExportL_5d57d39e = __vite__cjsImport0_react["👋"]; ' + + 'export { __vite__cjsExportI_useStateAlias as useStateAlias, __vite__cjsExportI_ComponentAlias as ComponentAlias, __vite__cjsExportL_5d57d39e as "👍" }', ) }) @@ -169,8 +172,8 @@ describe('transformCjsImport', () => { ), ).toBe( 'import __vite__cjsImport0_react from "./node_modules/.vite/deps/react.js"; ' + - 'const __vite__cjsExport_React = __vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react.default : __vite__cjsImport0_react; ' + - 'export { __vite__cjsExport_React as React }', + 'const __vite__cjsExportI_React = __vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react.default : __vite__cjsImport0_react; ' + + 'export { __vite__cjsExportI_React as React }', ) expect( diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 32591fda93f2d3..7a3c6c3e92271a 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -13,7 +13,7 @@ import type { StaticImport } from 'mlly' import { ESM_STATIC_IMPORT_RE, parseStaticImport } from 'mlly' import { makeLegalIdentifier } from '@rollup/pluginutils' import type { PartialResolvedId } from 'rollup' -import type { Identifier } from 'estree' +import type { Identifier, Literal } from 'estree' import { CLIENT_DIR, CLIENT_PUBLIC_PATH, @@ -32,6 +32,7 @@ import { createDebugger, fsPathFromUrl, generateCodeFrame, + getHash, injectQuery, isBuiltin, isDataUrl, @@ -965,11 +966,10 @@ export function transformCjsImport( const exportNames: string[] = [] let defaultExports: string = '' for (const spec of node.specifiers) { - if ( - spec.type === 'ImportSpecifier' && - spec.imported.type === 'Identifier' - ) { - const importedName = spec.imported.name + if (spec.type === 'ImportSpecifier') { + const importedName = getIdentifierNameOrLiteralValue( + spec.imported, + ) as string const localName = spec.local.name importNames.push({ importedName, localName }) } else if (spec.type === 'ImportDefaultSpecifier') { @@ -979,26 +979,31 @@ export function transformCjsImport( }) } else if (spec.type === 'ImportNamespaceSpecifier') { importNames.push({ importedName: '*', localName: spec.local.name }) - } else if ( - spec.type === 'ExportSpecifier' && - spec.exported.type === 'Identifier' - ) { + } else if (spec.type === 'ExportSpecifier') { // for ExportSpecifier, local name is same as imported name // prefix the variable name to avoid clashing with other local variables - const importedName = (spec.local as Identifier).name + const importedName = getIdentifierNameOrLiteralValue( + spec.local, + ) as string // we want to specify exported name as variable and re-export it - const exportedName = spec.exported.name + const exportedName = getIdentifierNameOrLiteralValue( + spec.exported, + ) as string if (exportedName === 'default') { defaultExports = makeLegalIdentifier( `__vite__cjsExportDefault_${importIndex}`, ) importNames.push({ importedName, localName: defaultExports }) } else { - const localName = makeLegalIdentifier( - `__vite__cjsExport_${exportedName}`, - ) + const localName = `__vite__cjsExport${ + spec.exported.type === 'Literal' + ? `L_${getHash(spec.exported.value as string)}` + : 'I_' + spec.exported.name + }` importNames.push({ importedName, localName }) - exportNames.push(`${localName} as ${exportedName}`) + exportNames.push( + `${localName} as ${spec.exported.type === 'Literal' ? JSON.stringify(exportedName) : exportedName}`, + ) } } } @@ -1033,6 +1038,10 @@ export function transformCjsImport( } } +function getIdentifierNameOrLiteralValue(node: Identifier | Literal) { + return node.type === 'Identifier' ? node.name : node.value +} + // Copied from `client/client.ts`. Only needed so we can inline inject this function for classic workers. function __vite__injectQuery(url: string, queryToInject: string): string { // skip urls that won't be handled by vite diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 414fb74fc15b04..c8ccfeb052d3c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3318,9 +3318,6 @@ packages: '@types/escape-html@1.0.4': resolution: {integrity: sha512-qZ72SFTgUAZ5a7Tj6kf2SHLetiH5S6f8G5frB2SPQ3EyF02kxdyBFf4Tz4banE3xCgGnKgWLt//a6VuYHKYJTg==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -8885,8 +8882,6 @@ snapshots: '@types/escape-html@1.0.4': {} - '@types/estree@1.0.5': {} - '@types/estree@1.0.6': {} '@types/etag@1.8.3': @@ -10416,7 +10411,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 esutils@2.0.3: {} @@ -11758,7 +11753,7 @@ snapshots: periscopic@4.0.2: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 is-reference: 3.0.2 zimmerframe: 1.0.0