fix(cli): allow configurations files to also be json modules (#15444)

Closes #15440
This commit is contained in:
Nayeem Rahman 2022-08-10 22:33:42 +01:00 committed by David Sherret
parent 71cefe1ed8
commit ae7b6a4ca3
6 changed files with 77 additions and 57 deletions

View File

@ -9,6 +9,7 @@ use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::ModuleSpecifier;
use deno_graph::Dependency;
use deno_graph::GraphImport;
use deno_graph::MediaType;
use deno_graph::ModuleGraph;
use deno_graph::ModuleGraphError;
@ -49,9 +50,6 @@ pub enum ModuleEntry {
checked_libs: HashSet<TsTypeLib>,
maybe_types: Option<Resolved>,
},
Configuration {
dependencies: BTreeMap<String, Resolved>,
},
Error(ModuleGraphError),
Redirect(ModuleSpecifier),
}
@ -63,7 +61,7 @@ pub struct GraphData {
/// Map of first known referrer locations for each module. Used to enhance
/// error messages.
referrer_map: HashMap<ModuleSpecifier, Range>,
configurations: HashSet<ModuleSpecifier>,
graph_imports: Vec<GraphImport>,
cjs_esm_translations: HashMap<ModuleSpecifier, String>,
}
@ -71,24 +69,22 @@ impl GraphData {
/// Store data from `graph` into `self`.
pub fn add_graph(&mut self, graph: &ModuleGraph, reload: bool) {
for graph_import in &graph.imports {
let mut dependencies = BTreeMap::new();
for (specifier, dependency) in &graph_import.dependencies {
if !matches!(dependency.maybe_type, Resolved::None) {
dependencies.insert(specifier.clone(), dependency.maybe_type.clone());
for dep in graph_import.dependencies.values() {
for resolved in [&dep.maybe_code, &dep.maybe_type] {
if let Resolved::Ok {
specifier, range, ..
} = &dependency.maybe_type
} = resolved
{
let entry = self.referrer_map.entry(specifier.clone());
entry.or_insert_with(|| range.clone());
}
}
}
self.modules.insert(
graph_import.referrer.clone(),
ModuleEntry::Configuration { dependencies },
);
self.configurations.insert(graph_import.referrer.clone());
// TODO(nayeemrmn): Implement `Clone` on `GraphImport`.
self.graph_imports.push(GraphImport {
referrer: graph_import.referrer.clone(),
dependencies: graph_import.dependencies.clone(),
});
}
for (specifier, result) in graph.specifiers() {
@ -187,9 +183,20 @@ impl GraphData {
seen.insert(root);
visiting.push_back(root);
}
for root in &self.configurations {
seen.insert(root);
visiting.push_back(root);
for (_, dep) in self.graph_imports.iter().flat_map(|i| &i.dependencies) {
let mut resolutions = vec![&dep.maybe_code];
if follow_type_only {
resolutions.push(&dep.maybe_type);
}
#[allow(clippy::manual_flatten)]
for resolved in resolutions {
if let Resolved::Ok { specifier, .. } = resolved {
if !seen.contains(specifier) {
seen.insert(specifier);
visiting.push_front(specifier);
}
}
}
}
while let Some(specifier) = visiting.pop_front() {
let (specifier, entry) = match self.modules.get_key_value(specifier) {
@ -239,16 +246,6 @@ impl GraphData {
}
}
}
ModuleEntry::Configuration { dependencies } => {
for resolved in dependencies.values() {
if let Resolved::Ok { specifier, .. } = resolved {
if !seen.contains(specifier) {
seen.insert(specifier);
visiting.push_front(specifier);
}
}
}
}
ModuleEntry::Error(_) => {}
ModuleEntry::Redirect(specifier) => {
if !seen.contains(specifier) {
@ -282,7 +279,15 @@ impl GraphData {
Some(Self {
modules,
referrer_map,
configurations: self.configurations.clone(),
// TODO(nayeemrmn): Implement `Clone` on `GraphImport`.
graph_imports: self
.graph_imports
.iter()
.map(|i| GraphImport {
referrer: i.referrer.clone(),
dependencies: i.dependencies.clone(),
})
.collect(),
cjs_esm_translations: Default::default(),
})
}
@ -352,20 +357,6 @@ impl GraphData {
}
}
}
ModuleEntry::Configuration { dependencies } => {
for resolved_result in dependencies.values() {
if let Resolved::Err(error) = resolved_result {
let range = error.range();
if !range.specifier.as_str().contains("$deno") {
return Some(Err(custom_error(
get_error_class_name(&error.clone().into()),
format!("{}\n at {}", error, range),
)));
}
return Some(Err(error.clone().into()));
}
}
}
ModuleEntry::Error(error) => {
if !contains_specifier(roots, specifier) {
if let Some(range) = self.referrer_map.get(specifier) {
@ -443,6 +434,24 @@ impl GraphData {
self.modules.get(specifier)
}
/// Get the dependencies of a module or graph import.
pub fn get_dependencies<'a>(
&'a self,
specifier: &ModuleSpecifier,
) -> Option<&'a BTreeMap<String, Dependency>> {
let specifier = self.follow_redirect(specifier);
if let Some(ModuleEntry::Module { dependencies, .. }) = self.get(&specifier)
{
return Some(dependencies);
}
if let Some(graph_import) =
self.graph_imports.iter().find(|i| i.referrer == specifier)
{
return Some(&graph_import.dependencies);
}
None
}
// TODO(bartlomieju): after saving translated source
// it's never removed, potentially leading to excessive
// memory consumption

View File

@ -2754,6 +2754,12 @@ itest!(custom_inspect_url {
output: "custom_inspect_url.js.out",
});
itest!(config_json_import {
args: "run --quiet -c jsx/deno-jsx.json config_json_import.ts",
output: "config_json_import.ts.out",
http_server: true,
});
#[test]
fn running_declaration_files() {
let temp_dir = TempDir::new();

View File

@ -0,0 +1,2 @@
import config from "./jsx/deno-jsx.json" assert { type: "json" };
console.log(config);

View File

@ -0,0 +1,3 @@
{
compilerOptions: { jsx: "react-jsx", jsxImportSource: "http://localhost:4545/jsx" }
}

6
cli/tests/testdata/jsx/deno-jsx.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "http://localhost:4545/jsx"
}
}

View File

@ -490,21 +490,15 @@ fn op_resolve(
));
} else {
let graph_data = state.graph_data.read();
let referrer = graph_data.follow_redirect(&referrer);
let resolved_dep = match graph_data.get(&referrer) {
Some(ModuleEntry::Module { dependencies, .. }) => {
dependencies.get(specifier).map(|d| {
if matches!(d.maybe_type, Resolved::Ok { .. }) {
&d.maybe_type
} else {
&d.maybe_code
}
})
}
Some(ModuleEntry::Configuration { dependencies }) => {
dependencies.get(specifier)
}
_ => None,
let resolved_dep = match graph_data.get_dependencies(&referrer) {
Some(dependencies) => dependencies.get(specifier).map(|d| {
if matches!(d.maybe_type, Resolved::Ok { .. }) {
&d.maybe_type
} else {
&d.maybe_code
}
}),
None => None,
};
let maybe_result = match resolved_dep {
Some(Resolved::Ok { specifier, .. }) => {