Skip to content

Commit

Permalink
fix: adjust import analysis behavior to match Node (#16738)
Browse files Browse the repository at this point in the history
  • Loading branch information
stenin-nikita committed May 29, 2024
1 parent 48edfcd commit f599ab4
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 37 deletions.
3 changes: 1 addition & 2 deletions packages/vite/src/node/ssr/ssrModuleLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
import {
type SSRImportBaseMetadata,
analyzeImportedModDifference,
proxyGuardOnlyEsm,
} from '../../shared/ssrTransform'
import { SOURCEMAPPING_URL } from '../../shared/constants'
import {
Expand Down Expand Up @@ -317,7 +316,7 @@ async function nodeImport(
: undefined,
metadata,
)
return proxyGuardOnlyEsm(mod, id)
return mod
} else {
return mod
}
Expand Down
7 changes: 2 additions & 5 deletions packages/vite/src/runtime/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import {
unwrapId,
wrapId,
} from '../shared/utils'
import {
analyzeImportedModDifference,
proxyGuardOnlyEsm,
} from '../shared/ssrTransform'
import { analyzeImportedModDifference } from '../shared/ssrTransform'
import { ModuleCacheMap } from './moduleCache'
import type {
FetchResult,
Expand Down Expand Up @@ -193,7 +190,7 @@ export class ViteRuntime {
const { id, type } = fetchResult
if (type !== 'module' && type !== 'commonjs') return exports
analyzeImportedModDifference(exports, id, type, metadata)
return proxyGuardOnlyEsm(exports, id, metadata)
return exports
}

private async cachedRequest(
Expand Down
44 changes: 14 additions & 30 deletions packages/vite/src/shared/ssrTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,48 +28,32 @@ export function analyzeImportedModDifference(
): void {
// No normalization needed if the user already dynamic imports this module
if (metadata?.isDynamicImport) return
// If file path is ESM, everything should be fine
if (moduleType === 'module') return

// 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 the module doesn't import anything explicitly, e.g. `import 'foo'` or
// `import * as foo from 'foo'`, we can skip.
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(`\

// For 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.
if (moduleType === 'module') {
throw new SyntaxError(
`[vite] The requested module '${rawId}' does not provide an export named '${lastBinding}'`,
)
} else {
// For non-ESM, named imports is done via static analysis with cjs-module-lexer in Node.js.
// Copied from Node.js
throw new SyntaxError(`\
[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}';
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.
*/
export function proxyGuardOnlyEsm(
mod: any,
rawId: string,
metadata?: SSRImportBaseMetadata,
): any {
// 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(
`[vite] The requested module '${rawId}' does not provide an export named '${prop.toString()}'`,
)
}
return mod[prop]
},
})
}

0 comments on commit f599ab4

Please sign in to comment.