mirror of
https://github.com/denoland/deno.git
synced 2025-01-12 00:54:02 -05:00
fix: resolve jsxImportSource
relative to module (#15561)
Previously `jsxImportSource` was resolved relative to the config file during graph building, and relative to the emitted module during runtime. This is now fixed so that the JSX import source is resolved relative to the module both during graph building and at runtime.
This commit is contained in:
parent
6bb72a8086
commit
33c4d45328
12 changed files with 79 additions and 42 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -982,9 +982,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_doc"
|
name = "deno_doc"
|
||||||
version = "0.42.0"
|
version = "0.43.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8abb2f83fb63564ded9f9eb46c25a9c900f5a7c1beac30e4fae12009c3837b6"
|
checksum = "22162c77cbcf8da271482b0facf45e4654cdf72dc09ebc7d8d534650ceb0effe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"deno_ast",
|
"deno_ast",
|
||||||
|
@ -1000,9 +1000,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_emit"
|
name = "deno_emit"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71f7501c229a6ce6f28c8c36d5f0c67a82c2fc47fa490198bd4e5de437fca158"
|
checksum = "d98268720377863f697b8e74955c33d237f527bdecb3e4b134b43390ba0aff40"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.13.0",
|
"base64 0.13.0",
|
||||||
|
@ -1061,9 +1061,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_graph"
|
name = "deno_graph"
|
||||||
version = "0.31.0"
|
version = "0.32.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f99778595687fca36ef4c28702b7e64f45508f2af0644ad9ad99fd12fa6d6e5f"
|
checksum = "30317c100055c82f433bffb130c6dc62346f46a5d3de24d14e8913ad7c490c39"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -1601,9 +1601,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eszip"
|
name = "eszip"
|
||||||
version = "0.24.0"
|
version = "0.25.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d902a48c7edaf6b26fd9df6bdf205935162690e03848607b671ae1c66a3f0d3b"
|
checksum = "006cd7d8f0b2f0de3a5f21b770974d6f293a2104536f7060033f17b4d63f8e91"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.13.0",
|
"base64 0.13.0",
|
||||||
|
|
|
@ -48,9 +48,9 @@ winres = "=0.1.12"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deno_ast = { version = "0.17.0", features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "transpiling", "typescript", "view", "visit"] }
|
deno_ast = { version = "0.17.0", features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "transpiling", "typescript", "view", "visit"] }
|
||||||
deno_core = { version = "0.147.0", path = "../core" }
|
deno_core = { version = "0.147.0", path = "../core" }
|
||||||
deno_doc = "0.42.0"
|
deno_doc = "0.43.0"
|
||||||
deno_emit = "0.6.0"
|
deno_emit = "0.7.0"
|
||||||
deno_graph = "0.31.0"
|
deno_graph = "0.32.0"
|
||||||
deno_lint = { version = "0.32.0", features = ["docs"] }
|
deno_lint = { version = "0.32.0", features = ["docs"] }
|
||||||
deno_runtime = { version = "0.73.0", path = "../runtime" }
|
deno_runtime = { version = "0.73.0", path = "../runtime" }
|
||||||
deno_task_shell = "0.5.0"
|
deno_task_shell = "0.5.0"
|
||||||
|
@ -69,7 +69,7 @@ dprint-plugin-markdown = "=0.14.0"
|
||||||
dprint-plugin-typescript = "=0.71.2"
|
dprint-plugin-typescript = "=0.71.2"
|
||||||
encoding_rs = "=0.8.31"
|
encoding_rs = "=0.8.31"
|
||||||
env_logger = "=0.9.0"
|
env_logger = "=0.9.0"
|
||||||
eszip = "=0.24.0"
|
eszip = "=0.25.0"
|
||||||
fancy-regex = "=0.10.0"
|
fancy-regex = "=0.10.0"
|
||||||
flate2 = "=1.0.24"
|
flate2 = "=1.0.24"
|
||||||
http = "=0.2.6"
|
http = "=0.2.6"
|
||||||
|
|
|
@ -11,7 +11,6 @@ use crate::fs_util::specifier_to_file_path;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::anyhow::bail;
|
use deno_core::anyhow::bail;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::custom_error;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
use deno_core::serde::Serialize;
|
use deno_core::serde::Serialize;
|
||||||
|
@ -30,6 +29,11 @@ use std::path::PathBuf;
|
||||||
pub type MaybeImportsResult =
|
pub type MaybeImportsResult =
|
||||||
Result<Option<Vec<(ModuleSpecifier, Vec<String>)>>, AnyError>;
|
Result<Option<Vec<(ModuleSpecifier, Vec<String>)>>, AnyError>;
|
||||||
|
|
||||||
|
pub struct JsxImportSourceConfig {
|
||||||
|
pub default_specifier: Option<String>,
|
||||||
|
pub module: String,
|
||||||
|
}
|
||||||
|
|
||||||
/// The transpile options that are significant out of a user provided tsconfig
|
/// The transpile options that are significant out of a user provided tsconfig
|
||||||
/// file, that we want to deserialize out of the final config for a transpile.
|
/// file, that we want to deserialize out of the final config for a transpile.
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -680,17 +684,6 @@ impl ConfigFile {
|
||||||
if let Some(types) = compiler_options.types {
|
if let Some(types) = compiler_options.types {
|
||||||
imports.extend(types);
|
imports.extend(types);
|
||||||
}
|
}
|
||||||
if compiler_options.jsx == Some("react-jsx".to_string()) {
|
|
||||||
imports.push(format!(
|
|
||||||
"{}/jsx-runtime",
|
|
||||||
compiler_options.jsx_import_source.ok_or_else(|| custom_error("TypeError", "Compiler option 'jsx' set to 'react-jsx', but no 'jsxImportSource' defined."))?
|
|
||||||
));
|
|
||||||
} else if compiler_options.jsx == Some("react-jsxdev".to_string()) {
|
|
||||||
imports.push(format!(
|
|
||||||
"{}/jsx-dev-runtime",
|
|
||||||
compiler_options.jsx_import_source.ok_or_else(|| custom_error("TypeError", "Compiler option 'jsx' set to 'react-jsxdev', but no 'jsxImportSource' defined."))?
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if !imports.is_empty() {
|
if !imports.is_empty() {
|
||||||
let referrer = self.specifier.clone();
|
let referrer = self.specifier.clone();
|
||||||
Ok(Some(vec![(referrer, imports)]))
|
Ok(Some(vec![(referrer, imports)]))
|
||||||
|
@ -700,16 +693,22 @@ impl ConfigFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Based on the compiler options in the configuration file, return the
|
/// Based on the compiler options in the configuration file, return the
|
||||||
/// implied JSX import source module.
|
/// JSX import source configuration.
|
||||||
pub fn to_maybe_jsx_import_source_module(&self) -> Option<String> {
|
pub fn to_maybe_jsx_import_source_config(
|
||||||
|
&self,
|
||||||
|
) -> Option<JsxImportSourceConfig> {
|
||||||
let compiler_options_value = self.json.compiler_options.as_ref()?;
|
let compiler_options_value = self.json.compiler_options.as_ref()?;
|
||||||
let compiler_options: CompilerOptions =
|
let compiler_options: CompilerOptions =
|
||||||
serde_json::from_value(compiler_options_value.clone()).ok()?;
|
serde_json::from_value(compiler_options_value.clone()).ok()?;
|
||||||
match compiler_options.jsx.as_deref() {
|
let module = match compiler_options.jsx.as_deref() {
|
||||||
Some("react-jsx") => Some("jsx-runtime".to_string()),
|
Some("react-jsx") => Some("jsx-runtime".to_string()),
|
||||||
Some("react-jsxdev") => Some("jsx-dev-runtime".to_string()),
|
Some("react-jsxdev") => Some("jsx-dev-runtime".to_string()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
};
|
||||||
|
module.map(|module| JsxImportSourceConfig {
|
||||||
|
default_specifier: compiler_options.jsx_import_source,
|
||||||
|
module,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
|
pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
|
||||||
|
|
|
@ -34,6 +34,7 @@ use std::env;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::args::config_file::JsxImportSourceConfig;
|
||||||
use crate::compat;
|
use crate::compat;
|
||||||
use crate::deno_dir::DenoDir;
|
use crate::deno_dir::DenoDir;
|
||||||
use crate::emit::get_ts_config_for_emit;
|
use crate::emit::get_ts_config_for_emit;
|
||||||
|
@ -210,12 +211,14 @@ impl CliOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the implied JSX import source module.
|
/// Return the JSX import source configuration.
|
||||||
pub fn to_maybe_jsx_import_source_module(&self) -> Option<String> {
|
pub fn to_maybe_jsx_import_source_config(
|
||||||
|
&self,
|
||||||
|
) -> Option<JsxImportSourceConfig> {
|
||||||
self
|
self
|
||||||
.maybe_config_file
|
.maybe_config_file
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|c| c.to_maybe_jsx_import_source_module())
|
.and_then(|c| c.to_maybe_jsx_import_source_config())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return any imports that should be brought into the scope of the module
|
/// Return any imports that should be brought into the scope of the module
|
||||||
|
|
|
@ -998,8 +998,8 @@ impl Documents {
|
||||||
// TODO(@kitsonk) update resolved dependencies?
|
// TODO(@kitsonk) update resolved dependencies?
|
||||||
self.maybe_import_map = maybe_import_map.map(ImportMapResolver::new);
|
self.maybe_import_map = maybe_import_map.map(ImportMapResolver::new);
|
||||||
self.maybe_jsx_resolver = maybe_config_file.and_then(|cf| {
|
self.maybe_jsx_resolver = maybe_config_file.and_then(|cf| {
|
||||||
cf.to_maybe_jsx_import_source_module()
|
cf.to_maybe_jsx_import_source_config()
|
||||||
.map(|im| JsxResolver::new(im, self.maybe_import_map.clone()))
|
.map(|cfg| JsxResolver::new(cfg, self.maybe_import_map.clone()))
|
||||||
});
|
});
|
||||||
self.imports = Arc::new(
|
self.imports = Arc::new(
|
||||||
if let Some(Ok(Some(imports))) =
|
if let Some(Ok(Some(imports))) =
|
||||||
|
|
|
@ -457,8 +457,8 @@ async fn create_graph_and_maybe_check(
|
||||||
ps.maybe_import_map.clone().map(ImportMapResolver::new);
|
ps.maybe_import_map.clone().map(ImportMapResolver::new);
|
||||||
let maybe_jsx_resolver = ps
|
let maybe_jsx_resolver = ps
|
||||||
.options
|
.options
|
||||||
.to_maybe_jsx_import_source_module()
|
.to_maybe_jsx_import_source_config()
|
||||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
.map(|cfg| JsxResolver::new(cfg, maybe_import_map_resolver.clone()));
|
||||||
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
||||||
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -192,8 +192,8 @@ impl ProcState {
|
||||||
let maybe_import_map_resolver =
|
let maybe_import_map_resolver =
|
||||||
maybe_import_map.clone().map(ImportMapResolver::new);
|
maybe_import_map.clone().map(ImportMapResolver::new);
|
||||||
let maybe_jsx_resolver = cli_options
|
let maybe_jsx_resolver = cli_options
|
||||||
.to_maybe_jsx_import_source_module()
|
.to_maybe_jsx_import_source_config()
|
||||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
.map(|cfg| JsxResolver::new(cfg, maybe_import_map_resolver.clone()));
|
||||||
let maybe_resolver: Option<
|
let maybe_resolver: Option<
|
||||||
Arc<dyn deno_graph::source::Resolver + Send + Sync>,
|
Arc<dyn deno_graph::source::Resolver + Send + Sync>,
|
||||||
> = if cli_options.compat() {
|
> = if cli_options.compat() {
|
||||||
|
@ -643,8 +643,8 @@ impl ProcState {
|
||||||
let maybe_imports = self.options.to_maybe_imports()?;
|
let maybe_imports = self.options.to_maybe_imports()?;
|
||||||
let maybe_jsx_resolver = self
|
let maybe_jsx_resolver = self
|
||||||
.options
|
.options
|
||||||
.to_maybe_jsx_import_source_module()
|
.to_maybe_jsx_import_source_config()
|
||||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
.map(|cfg| JsxResolver::new(cfg, maybe_import_map_resolver.clone()));
|
||||||
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
||||||
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,6 +7,8 @@ use deno_graph::source::Resolver;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::args::config_file::JsxImportSourceConfig;
|
||||||
|
|
||||||
/// Wraps an import map to be used when building a deno_graph module graph.
|
/// Wraps an import map to be used when building a deno_graph module graph.
|
||||||
/// This is done to avoid having `import_map` be a direct dependency of
|
/// This is done to avoid having `import_map` be a direct dependency of
|
||||||
/// `deno_graph`.
|
/// `deno_graph`.
|
||||||
|
@ -38,17 +40,19 @@ impl Resolver for ImportMapResolver {
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct JsxResolver {
|
pub struct JsxResolver {
|
||||||
|
default_jsx_import_source: Option<String>,
|
||||||
jsx_import_source_module: String,
|
jsx_import_source_module: String,
|
||||||
maybe_import_map_resolver: Option<ImportMapResolver>,
|
maybe_import_map_resolver: Option<ImportMapResolver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsxResolver {
|
impl JsxResolver {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
jsx_import_source_module: String,
|
jsx_import_source_config: JsxImportSourceConfig,
|
||||||
maybe_import_map_resolver: Option<ImportMapResolver>,
|
maybe_import_map_resolver: Option<ImportMapResolver>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
jsx_import_source_module,
|
default_jsx_import_source: jsx_import_source_config.default_specifier,
|
||||||
|
jsx_import_source_module: jsx_import_source_config.module,
|
||||||
maybe_import_map_resolver,
|
maybe_import_map_resolver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +63,10 @@ impl JsxResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolver for JsxResolver {
|
impl Resolver for JsxResolver {
|
||||||
|
fn default_jsx_import_source(&self) -> Option<String> {
|
||||||
|
self.default_jsx_import_source.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn jsx_import_source_module(&self) -> &str {
|
fn jsx_import_source_module(&self) -> &str {
|
||||||
self.jsx_import_source_module.as_str()
|
self.jsx_import_source_module.as_str()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1337,6 +1337,18 @@ itest!(jsx_import_source_import_map_dev {
|
||||||
http_server: true,
|
http_server: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(jsx_import_source_import_map_scoped {
|
||||||
|
args: "run --reload --import-map jsx/import-map-scoped.json --config jsx/deno-jsx-import-map.jsonc subdir/jsx_import_source_no_pragma.tsx",
|
||||||
|
output: "jsx_import_source_import_map.out",
|
||||||
|
http_server: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(jsx_import_source_import_map_scoped_dev {
|
||||||
|
args: "run --reload --import-map jsx/import-map-scoped.json --config jsx/deno-jsxdev-import-map.jsonc subdir/jsx_import_source_no_pragma.tsx",
|
||||||
|
output: "jsx_import_source_import_map_dev.out",
|
||||||
|
http_server: true,
|
||||||
|
});
|
||||||
|
|
||||||
itest!(jsx_import_source_pragma_no_check {
|
itest!(jsx_import_source_pragma_no_check {
|
||||||
args: "run --reload --no-check jsx_import_source_pragma.tsx",
|
args: "run --reload --no-check jsx_import_source_pragma.tsx",
|
||||||
output: "jsx_import_source.out",
|
output: "jsx_import_source.out",
|
||||||
|
|
8
cli/tests/testdata/jsx/import-map-scoped.json
vendored
Normal file
8
cli/tests/testdata/jsx/import-map-scoped.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"scopes": {
|
||||||
|
"../subdir/": {
|
||||||
|
"jsx/jsx-runtime": "http://localhost:4545/jsx/jsx-runtime/index.ts",
|
||||||
|
"jsx/jsx-dev-runtime": "http://localhost:4545/jsx/jsx-dev-runtime/index.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,2 @@
|
||||||
error: Module not found "file:///[WILDCARD]/nonexistent/jsx-runtime".
|
error: Module not found "file:///[WILDCARD]/nonexistent/jsx-runtime".
|
||||||
at file:///[WILDCARD]/deno-jsx-error.jsonc:1:1
|
at file:///[WILDCARD]/jsx_import_source_no_pragma.tsx:1:1
|
||||||
|
|
7
cli/tests/testdata/subdir/jsx_import_source_no_pragma.tsx
vendored
Normal file
7
cli/tests/testdata/subdir/jsx_import_source_no_pragma.tsx
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
function A() {
|
||||||
|
return "hello";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function B() {
|
||||||
|
return <A></A>;
|
||||||
|
}
|
Loading…
Reference in a new issue