mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix: cjs resolution cases (#25739)
Fixes cjs modules being loaded as esm.
This commit is contained in:
parent
f1ba266613
commit
a01dce3a25
11 changed files with 83 additions and 17 deletions
|
@ -572,8 +572,12 @@ impl CliFactory {
|
|||
let caches = self.caches()?;
|
||||
let node_analysis_cache =
|
||||
NodeAnalysisCache::new(caches.node_analysis_db());
|
||||
let cjs_esm_analyzer =
|
||||
CliCjsCodeAnalyzer::new(node_analysis_cache, self.fs().clone());
|
||||
let node_resolver = self.cli_node_resolver().await?.clone();
|
||||
let cjs_esm_analyzer = CliCjsCodeAnalyzer::new(
|
||||
node_analysis_cache,
|
||||
self.fs().clone(),
|
||||
node_resolver,
|
||||
);
|
||||
|
||||
Ok(Arc::new(NodeCodeTranslator::new(
|
||||
cjs_esm_analyzer,
|
||||
|
|
39
cli/node.rs
39
cli/node.rs
|
@ -16,6 +16,7 @@ use serde::Serialize;
|
|||
|
||||
use crate::cache::CacheDBHash;
|
||||
use crate::cache::NodeAnalysisCache;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||
|
||||
pub type CliNodeCodeTranslator =
|
||||
|
@ -54,11 +55,20 @@ pub enum CliCjsAnalysis {
|
|||
pub struct CliCjsCodeAnalyzer {
|
||||
cache: NodeAnalysisCache,
|
||||
fs: deno_fs::FileSystemRc,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
}
|
||||
|
||||
impl CliCjsCodeAnalyzer {
|
||||
pub fn new(cache: NodeAnalysisCache, fs: deno_fs::FileSystemRc) -> Self {
|
||||
Self { cache, fs }
|
||||
pub fn new(
|
||||
cache: NodeAnalysisCache,
|
||||
fs: deno_fs::FileSystemRc,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
) -> Self {
|
||||
Self {
|
||||
cache,
|
||||
fs,
|
||||
node_resolver,
|
||||
}
|
||||
}
|
||||
|
||||
async fn inner_cjs_analysis(
|
||||
|
@ -73,7 +83,7 @@ impl CliCjsCodeAnalyzer {
|
|||
return Ok(analysis);
|
||||
}
|
||||
|
||||
let media_type = MediaType::from_specifier(specifier);
|
||||
let mut media_type = MediaType::from_specifier(specifier);
|
||||
if media_type == MediaType::Json {
|
||||
return Ok(CliCjsAnalysis::Cjs {
|
||||
exports: vec![],
|
||||
|
@ -81,6 +91,22 @@ impl CliCjsCodeAnalyzer {
|
|||
});
|
||||
}
|
||||
|
||||
if media_type == MediaType::JavaScript {
|
||||
if let Some(package_json) =
|
||||
self.node_resolver.get_closest_package_json(specifier)?
|
||||
{
|
||||
match package_json.typ.as_str() {
|
||||
"commonjs" => {
|
||||
media_type = MediaType::Cjs;
|
||||
}
|
||||
"module" => {
|
||||
media_type = MediaType::Mjs;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let analysis = deno_core::unsync::spawn_blocking({
|
||||
let specifier = specifier.clone();
|
||||
let source: Arc<str> = source.into();
|
||||
|
@ -99,6 +125,13 @@ impl CliCjsCodeAnalyzer {
|
|||
exports: analysis.exports,
|
||||
reexports: analysis.reexports,
|
||||
})
|
||||
} else if media_type == MediaType::Cjs {
|
||||
// FIXME: `deno_ast` should internally handle MediaType::Cjs implying that
|
||||
// the result must never be Esm
|
||||
Ok(CliCjsAnalysis::Cjs {
|
||||
exports: vec![],
|
||||
reexports: vec![],
|
||||
})
|
||||
} else {
|
||||
Ok(CliCjsAnalysis::Esm)
|
||||
}
|
||||
|
|
|
@ -580,8 +580,17 @@ pub async fn run(
|
|||
let cjs_resolutions = Arc::new(CjsResolutionStore::default());
|
||||
let cache_db = Caches::new(deno_dir_provider.clone());
|
||||
let node_analysis_cache = NodeAnalysisCache::new(cache_db.node_analysis_db());
|
||||
let cjs_esm_code_analyzer =
|
||||
CliCjsCodeAnalyzer::new(node_analysis_cache, fs.clone());
|
||||
let cli_node_resolver = Arc::new(CliNodeResolver::new(
|
||||
cjs_resolutions.clone(),
|
||||
fs.clone(),
|
||||
node_resolver.clone(),
|
||||
npm_resolver.clone(),
|
||||
));
|
||||
let cjs_esm_code_analyzer = CliCjsCodeAnalyzer::new(
|
||||
node_analysis_cache,
|
||||
fs.clone(),
|
||||
cli_node_resolver.clone(),
|
||||
);
|
||||
let node_code_translator = Arc::new(NodeCodeTranslator::new(
|
||||
cjs_esm_code_analyzer,
|
||||
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||
|
@ -637,12 +646,6 @@ pub async fn run(
|
|||
metadata.workspace_resolver.pkg_json_resolution,
|
||||
)
|
||||
};
|
||||
let cli_node_resolver = Arc::new(CliNodeResolver::new(
|
||||
cjs_resolutions.clone(),
|
||||
fs.clone(),
|
||||
node_resolver.clone(),
|
||||
npm_resolver.clone(),
|
||||
));
|
||||
let module_loader_factory = StandaloneModuleLoaderFactory {
|
||||
shared: Arc::new(SharedModuleLoaderState {
|
||||
eszip: WorkspaceEszip {
|
||||
|
|
|
@ -526,7 +526,8 @@ impl CliMainWorkerFactory {
|
|||
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
||||
(node_resolution.into_url(), is_main_cjs)
|
||||
} else {
|
||||
(main_module, false)
|
||||
let is_cjs = main_module.path().ends_with(".cjs");
|
||||
(main_module, is_cjs)
|
||||
};
|
||||
|
||||
let ModuleLoaderAndSourceMapGetter { module_loader } =
|
||||
|
|
|
@ -1007,7 +1007,10 @@ Module.prototype._compile = function (content, filename, format) {
|
|||
try {
|
||||
compiledWrapper = wrapSafe(filename, content, this, format);
|
||||
} catch (err) {
|
||||
if (err instanceof SyntaxError && op_require_can_parse_as_esm(content)) {
|
||||
if (
|
||||
format !== "commonjs" && err instanceof SyntaxError &&
|
||||
op_require_can_parse_as_esm(content)
|
||||
) {
|
||||
return loadESMFromCJS(this, filename, content);
|
||||
}
|
||||
throw err;
|
||||
|
@ -1067,7 +1070,7 @@ Module._extensions[".js"] = function (module, filename) {
|
|||
let format;
|
||||
if (StringPrototypeEndsWith(filename, ".js")) {
|
||||
const pkg = op_require_read_closest_package_json(filename);
|
||||
if (pkg?.typ === "module") {
|
||||
if (pkg?.type === "module") {
|
||||
format = "module";
|
||||
} else if (pkg?.type === "commonjs") {
|
||||
format = "commonjs";
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export {};
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "@denotest/type-commonjs",
|
||||
"version": "1.0.0",
|
||||
"type": "commonjs"
|
||||
}
|
5
tests/specs/npm/require_type_commonjs/__test__.jsonc
Normal file
5
tests/specs/npm/require_type_commonjs/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"args": "run --allow-read --quiet main.ts",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
}
|
10
tests/specs/npm/require_type_commonjs/main.out
Normal file
10
tests/specs/npm/require_type_commonjs/main.out
Normal file
|
@ -0,0 +1,10 @@
|
|||
error: Uncaught (in promise) SyntaxError: Unexpected token 'export'
|
||||
at Object.evalContext (ext:core/01_core.js:[WILDCARD])
|
||||
at wrapSafe (node:module:[WILDCARD])
|
||||
at Module._compile (node:module:[WILDCARD])
|
||||
at Object.Module._extensions..js (node:module:[WILDCARD])
|
||||
at Module.load (node:module:[WILDCARD])
|
||||
at Function.Module._load (node:module:[WILDCARD])
|
||||
at Module.require (node:module:[WILDCARD])
|
||||
at require (node:module:[WILDCARD])
|
||||
at file:///[WILDCARD]/@denotest/type-commonjs/1.0.0/index.js:3:13
|
1
tests/specs/npm/require_type_commonjs/main.ts
Normal file
1
tests/specs/npm/require_type_commonjs/main.ts
Normal file
|
@ -0,0 +1 @@
|
|||
import "npm:@denotest/type-commonjs";
|
|
@ -1,6 +1,6 @@
|
|||
[Module: null prototype] { sync_js: 1 }
|
||||
[Module: null prototype] { sync_mjs: 1 }
|
||||
error: Uncaught (in promise) Error: Top-level await is not allowed in synchronous evaluation
|
||||
error: Uncaught Error: Top-level await is not allowed in synchronous evaluation
|
||||
at loadESMFromCJS (node:module:[WILDCARD])
|
||||
at Module._compile (node:module:[WILDCARD])
|
||||
at Object.Module._extensions..js (node:module:[WILDCARD])
|
||||
|
|
Loading…
Reference in a new issue