From 0eddb1fd1044b8038dc7895ce26f0fe17a5830b3 Mon Sep 17 00:00:00 2001 From: bluwy Date: Wed, 15 Nov 2023 14:43:41 +0800 Subject: [PATCH] fix(ssr): skip esm proxy guard for namespace imports --- .../node/ssr/__tests__/ssrTransform.spec.ts | 68 +++++++++---------- packages/vite/src/node/ssr/ssrModuleLoader.ts | 31 ++++++--- packages/vite/src/node/ssr/ssrTransform.ts | 27 +++++--- 3 files changed, 76 insertions(+), 50 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 4fd41c6f6f1e1f..c4df79007ce55f 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -11,7 +11,7 @@ test('default import', async () => { expect( await ssrTransformSimpleCode(`import foo from 'vue';console.log(foo.bar)`), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\"); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"default\\"]}); console.log(__vite_ssr_import_0__.default.bar)" `) }) @@ -22,7 +22,7 @@ test('named import', async () => { `import { ref } from 'vue';function foo() { return ref(0) }`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"ref\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"ref\\"]}); function foo() { return __vite_ssr_import_0__.ref(0) }" `) }) @@ -77,7 +77,7 @@ test('export named from', async () => { expect( await ssrTransformSimpleCode(`export { ref, computed as c } from 'vue'`), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"ref\\",\\"computed\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"ref\\",\\"computed\\"]}); Object.defineProperty(__vite_ssr_exports__, \\"ref\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.ref }}); Object.defineProperty(__vite_ssr_exports__, \\"c\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.computed }});" @@ -90,7 +90,7 @@ test('named exports of imported binding', async () => { `import {createApp} from 'vue';export {createApp}`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"createApp\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"createApp\\"]}); Object.defineProperty(__vite_ssr_exports__, \\"createApp\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.createApp }});" `) @@ -132,7 +132,7 @@ test('export then import minified', async () => { `export * from 'vue';import {createApp} from 'vue';`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"createApp\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"createApp\\"]}); const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"vue\\"); __vite_ssr_exportAll__(__vite_ssr_import_1__); " @@ -145,7 +145,7 @@ test('hoist import to top', async () => { `path.resolve('server.js');import path from 'node:path';`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"node:path\\"); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"node:path\\", {\\"importedNames\\":[\\"default\\"]}); __vite_ssr_import_0__.default.resolve('server.js');" `) }) @@ -173,7 +173,7 @@ test('do not rewrite method definition', async () => { `import { fn } from 'vue';class A { fn() { fn() } }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"fn\\"]}); class A { fn() { __vite_ssr_import_0__.fn() } }" `) expect(result?.deps).toEqual(['vue']) @@ -184,7 +184,7 @@ test('do not rewrite when variable is in scope', async () => { `import { fn } from 'vue';function A(){ const fn = () => {}; return { fn }; }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"fn\\"]}); function A(){ const fn = () => {}; return { fn }; }" `) expect(result?.deps).toEqual(['vue']) @@ -196,7 +196,7 @@ test('do not rewrite when variable is in scope with object destructuring', async `import { fn } from 'vue';function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"fn\\"]}); function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }" `) expect(result?.deps).toEqual(['vue']) @@ -208,7 +208,7 @@ test('do not rewrite when variable is in scope with array destructuring', async `import { fn } from 'vue';function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"fn\\"]}); function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }" `) expect(result?.deps).toEqual(['vue']) @@ -220,7 +220,7 @@ test('rewrite variable in string interpolation in function nested arguments', as `import { fn } from 'vue';function A({foo = \`test\${fn}\`} = {}){ return {}; }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"fn\\"]}); function A({foo = \`test\${__vite_ssr_import_0__.fn}\`} = {}){ return {}; }" `) expect(result?.deps).toEqual(['vue']) @@ -232,7 +232,7 @@ test('rewrite variables in default value of destructuring params', async () => { `import { fn } from 'vue';function A({foo = fn}){ return {}; }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"fn\\"]}); function A({foo = __vite_ssr_import_0__.fn}){ return {}; }" `) expect(result?.deps).toEqual(['vue']) @@ -243,7 +243,7 @@ test('do not rewrite when function declaration is in scope', async () => { `import { fn } from 'vue';function A(){ function fn() {}; return { fn }; }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"fn\\"]}); function A(){ function fn() {}; return { fn }; }" `) expect(result?.deps).toEqual(['vue']) @@ -254,7 +254,7 @@ test('do not rewrite catch clause', async () => { `import {error} from './dependency';try {} catch(error) {}`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"namedImportSpecifiers\\":[\\"error\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"importedNames\\":[\\"error\\"]}); try {} catch(error) {}" `) expect(result?.deps).toEqual(['./dependency']) @@ -267,7 +267,7 @@ test('should declare variable for imported super class', async () => { `import { Foo } from './dependency';` + `class A extends Foo {}`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"namedImportSpecifiers\\":[\\"Foo\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"importedNames\\":[\\"Foo\\"]}); const Foo = __vite_ssr_import_0__.Foo; class A extends Foo {}" `) @@ -281,7 +281,7 @@ test('should declare variable for imported super class', async () => { `export class B extends Foo {}`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"namedImportSpecifiers\\":[\\"Foo\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"importedNames\\":[\\"Foo\\"]}); const Foo = __vite_ssr_import_0__.Foo; class A extends Foo {} class B extends Foo {} @@ -354,7 +354,7 @@ test('overwrite bindings', async () => { `function g() { const f = () => { const inject = true }; console.log(inject) }\n`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"inject\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"inject\\"]}); const a = { inject: __vite_ssr_import_0__.inject } const b = { test: __vite_ssr_import_0__.inject } function c() { const { test: inject } = { test: true }; console.log(inject) } @@ -383,7 +383,7 @@ function c({ _ = bar() + foo() }) {} `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"importedNames\\":[\\"foo\\",\\"bar\\"]}); const a = ({ _ = __vite_ssr_import_0__.foo() }) => {} @@ -405,7 +405,7 @@ const a = () => { `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"n\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"importedNames\\":[\\"n\\"]}); const a = () => { @@ -428,7 +428,7 @@ const foo = {} `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"n\\",\\"m\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"importedNames\\":[\\"n\\",\\"m\\"]}); const foo = {} @@ -471,7 +471,7 @@ objRest() `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"remove\\",\\"add\\",\\"get\\",\\"set\\",\\"rest\\",\\"objRest\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"remove\\",\\"add\\",\\"get\\",\\"set\\",\\"rest\\",\\"objRest\\"]}); @@ -521,7 +521,7 @@ const obj = { `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\"); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"importedNames\\":[\\"default\\"]}); @@ -553,7 +553,7 @@ class A { `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"remove\\",\\"add\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"remove\\",\\"add\\"]}); @@ -585,7 +585,7 @@ class A { `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\"); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"importedNames\\":[\\"default\\"]}); @@ -631,7 +631,7 @@ bbb() `, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"aaa\\",\\"bbb\\",\\"ccc\\",\\"ddd\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"importedNames\\":[\\"aaa\\",\\"bbb\\",\\"ccc\\",\\"ddd\\"]}); @@ -676,8 +676,8 @@ test('jsx', async () => { const result = await transformWithEsbuild(code, id) expect(await ssrTransformSimpleCode(result.code, '/foo.jsx')) .toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"react\\"); - const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"Foo\\",\\"Slot\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"react\\", {\\"importedNames\\":[\\"default\\"]}); + const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"foo\\", {\\"importedNames\\":[\\"Foo\\",\\"Slot\\"]}); function Bar({ Slot: Slot2 = /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_1__.Foo, null) }) { @@ -752,7 +752,7 @@ import foo from "foo"`, ), ).toMatchInlineSnapshot(` "#!/usr/bin/env node - const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\"); + const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"importedNames\\":[\\"default\\"]}); console.log(__vite_ssr_import_0__.default); " `) @@ -788,7 +788,7 @@ export class Test { };`.trim() expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"importedNames\\":[\\"foo\\",\\"bar\\"]}); if (false) { const foo = 'foo' @@ -830,7 +830,7 @@ function test() { return [foo, bar] }`), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"importedNames\\":[\\"foo\\",\\"bar\\"]}); function test() { @@ -857,7 +857,7 @@ function test() { return bar; }`), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\",\\"baz\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"importedNames\\":[\\"foo\\",\\"bar\\",\\"baz\\"]}); function test() { @@ -889,7 +889,7 @@ for (const test in tests) { console.log(test) }`), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./test.js\\", {\\"namedImportSpecifiers\\":[\\"test\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./test.js\\", {\\"importedNames\\":[\\"test\\"]}); @@ -921,7 +921,7 @@ const Baz = class extends Foo {} `, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\", {\\"namedImportSpecifiers\\":[\\"Bar\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\", {\\"importedNames\\":[\\"default\\",\\"Bar\\"]}); @@ -963,7 +963,7 @@ export * from './b' console.log(foo + 2) `), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\", {\\"namedImportSpecifiers\\":[\\"foo\\"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\", {\\"importedNames\\":[\\"foo\\"]}); const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"./a\\"); __vite_ssr_exportAll__(__vite_ssr_import_1__); const __vite_ssr_import_2__ = await __vite_ssr_import__(\\"./b\\"); diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 6ad10fe85d0eb1..c48d0751df60bf 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -31,7 +31,16 @@ interface NodeImportResolveOptions interface SSRImportMetadata { isDynamicImport?: boolean - namedImportSpecifiers?: string[] + /** + * Imported names before being transformed to `ssrImportKey` + * + * import foo, { bar as baz, qux } from 'hello' + * => ['default', 'bar', 'qux'] + * + * import * as namespace from 'world + * => undefined + */ + importedNames?: string[] } // eslint-disable-next-line @typescript-eslint/no-empty-function @@ -367,15 +376,13 @@ function analyzeImportedModDifference( // For non-ESM, named imports is done via static analysis with cjs-module-lexer in Node.js. // If the user named imports a specifier that can't be analyzed, error. - if (metadata?.namedImportSpecifiers?.length) { - const missingBindings = metadata.namedImportSpecifiers.filter( - (s) => !(s in mod), - ) + if (metadata?.importedNames?.length) { + const missingBindings = metadata.importedNames.filter((s) => !(s in mod)) if (missingBindings.length) { const lastBinding = missingBindings[missingBindings.length - 1] // Copied from Node.js throw new SyntaxError(`\ -Named export '${lastBinding}' not found. The requested module '${rawId}' is a CommonJS module, which may not support all module.exports as named exports. +[vite] Named export '${lastBinding}' not found. The requested module '${rawId}' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using: import pkg from '${rawId}'; @@ -389,12 +396,20 @@ const {${missingBindings.join(', ')}} = pkg; * Guard invalid named exports only, similar to how Node.js errors for top-level imports. * But since we transform as dynamic imports, we need to emulate the error manually. */ -function proxyGuardOnlyEsm(mod: any, rawId: string) { +function proxyGuardOnlyEsm( + mod: any, + rawId: string, + metadata?: SSRImportMetadata, +) { + // If the module doesn't import anything explicitly, e.g. `import 'foo'` or + // `import * as foo from 'foo'`, we can skip the proxy guard. + if (!metadata?.importedNames?.length) return mod + return new Proxy(mod, { get(mod, prop) { if (prop !== 'then' && !(prop in mod)) { throw new SyntaxError( - `The requested module '${rawId}' does not provide an export named '${prop.toString()}'`, + `[vite] The requested module '${rawId}' does not provide an export named '${prop.toString()}'`, ) } return mod[prop] diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 450890af8d0765..3668a4a525a267 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -14,7 +14,7 @@ import { walk as eswalk } from 'estree-walker' import type { RawSourceMap } from '@ampproject/remapping' import { parseAstAsync as rollupParseAstAsync } from 'rollup/parseAst' import type { TransformResult } from '../server/transformRequest' -import { combineSourcemaps } from '../utils' +import { combineSourcemaps, isDefined } from '../utils' import { isJSONRequest } from '../plugins/json' type Node = _Node & { @@ -29,7 +29,16 @@ interface TransformOptions { } interface DefineImportMetadata { - namedImportSpecifiers?: string[] + /** + * Imported names of an import statement, e.g. + * + * import foo, { bar as baz, qux } from 'hello' + * => ['default', 'bar', 'qux'] + * + * import * as namespace from 'world + * => undefined + */ + importedNames?: string[] } export const ssrModuleExportsKey = `__vite_ssr_exports__` @@ -104,8 +113,7 @@ async function ssrTransformScript( // Reduce metadata to undefined if it's all default values if ( metadata && - (metadata.namedImportSpecifiers == null || - metadata.namedImportSpecifiers.length === 0) + (metadata.importedNames == null || metadata.importedNames.length === 0) ) { metadata = undefined } @@ -137,9 +145,12 @@ async function ssrTransformScript( // import * as ok from 'foo' --> ok -> __import_foo__ if (node.type === 'ImportDeclaration') { const importId = defineImport(node.source.value as string, { - namedImportSpecifiers: node.specifiers - .map((s) => s.type === 'ImportSpecifier' && s.imported.name) - .filter(Boolean) as string[], + importedNames: node.specifiers + .map((s) => { + if (s.type === 'ImportSpecifier') return s.imported.name + else if (s.type === 'ImportDefaultSpecifier') return 'default' + }) + .filter(isDefined), }) s.remove(node.start, node.end) for (const spec of node.specifiers) { @@ -184,7 +195,7 @@ async function ssrTransformScript( if (node.source) { // export { foo, bar } from './foo' const importId = defineImport(node.source.value as string, { - namedImportSpecifiers: node.specifiers.map((s) => s.local.name), + importedNames: node.specifiers.map((s) => s.local.name), }) // hoist re-exports near the defined import so they are immediately exported for (const spec of node.specifiers) {