1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-26 00:59:24 -05:00

refactor: make resolver required (#17783)

Makes the resolver required and prints a warning when vendoring and a
dynamic import can't be resolved.

Closes #16522
This commit is contained in:
David Sherret 2023-02-15 11:30:54 -05:00 committed by GitHub
parent c7535950b6
commit b34e751a5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 197 additions and 146 deletions

6
Cargo.lock generated
View file

@ -1092,19 +1092,21 @@ dependencies = [
[[package]]
name = "deno_graph"
version = "0.43.0"
version = "0.43.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71bb48b14950d62552aee1d05d0b90c203319b293b36358021ec77e05eaf9a4"
checksum = "9bfe0ba0ce8e54d198821714439a46b97c97de112d8a53a9a53d87c400da578c"
dependencies = [
"anyhow",
"data-url",
"deno_ast",
"futures",
"monch",
"once_cell",
"parking_lot 0.12.1",
"regex",
"serde",
"serde_json",
"thiserror",
"url",
]

View file

@ -46,7 +46,7 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_gra
deno_core.workspace = true
deno_doc = "0.55.0"
deno_emit = "0.15.0"
deno_graph = "0.43.0"
deno_graph = "0.43.1"
deno_lint = { version = "0.38.0", features = ["docs"] }
deno_lockfile.workspace = true
deno_runtime.workspace = true

View file

@ -35,7 +35,8 @@ fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str {
ModuleGraphError::ResolutionError(err) => get_resolution_error_class(err),
ModuleGraphError::UnsupportedMediaType { .. }
| ModuleGraphError::UnsupportedImportAssertionType { .. } => "TypeError",
ModuleGraphError::Missing(_, _) => "NotFound",
ModuleGraphError::Missing(_, _)
| ModuleGraphError::MissingDynamic(_, _) => "NotFound",
}
}

View file

@ -10,7 +10,7 @@ use crate::colors;
use crate::errors::get_error_class_name;
use crate::npm::resolve_graph_npm_info;
use crate::proc_state::ProcState;
use crate::resolver::CliResolver;
use crate::resolver::CliGraphResolver;
use crate::tools::check;
use deno_core::anyhow::bail;
@ -25,6 +25,13 @@ use deno_runtime::permissions::PermissionsContainer;
use import_map::ImportMapError;
use std::sync::Arc;
#[derive(Clone, Copy)]
pub struct GraphValidOptions {
pub check_js: bool,
pub follow_type_only: bool,
pub is_vendoring: bool,
}
/// Check if `roots` and their deps are available. Returns `Ok(())` if
/// so. Returns `Err(_)` if there is a known module graph or resolution
/// error statically reachable from `roots` and not a dynamic import.
@ -36,8 +43,8 @@ pub fn graph_valid_with_cli_options(
graph_valid(
graph,
roots,
deno_graph::WalkOptions {
follow_dynamic: false,
GraphValidOptions {
is_vendoring: false,
follow_type_only: options.type_check_mode() != TypeCheckMode::None,
check_js: options.check_js(),
},
@ -54,27 +61,61 @@ pub fn graph_valid_with_cli_options(
pub fn graph_valid(
graph: &ModuleGraph,
roots: &[ModuleSpecifier],
walk_options: deno_graph::WalkOptions,
options: GraphValidOptions,
) -> Result<(), AnyError> {
graph.walk(roots, walk_options).validate().map_err(|error| {
let is_root = match &error {
ModuleGraphError::ResolutionError(_) => false,
_ => roots.contains(error.specifier()),
};
let mut message = if let ModuleGraphError::ResolutionError(err) = &error {
enhanced_resolution_error_message(err)
} else {
format!("{error}")
};
let mut errors = graph
.walk(
roots,
deno_graph::WalkOptions {
check_js: options.check_js,
follow_type_only: options.follow_type_only,
follow_dynamic: options.is_vendoring,
},
)
.errors()
.flat_map(|error| {
let is_root = match &error {
ModuleGraphError::ResolutionError(_) => false,
_ => roots.contains(error.specifier()),
};
let mut message = if let ModuleGraphError::ResolutionError(err) = &error {
enhanced_resolution_error_message(err)
} else {
format!("{error}")
};
if let Some(range) = error.maybe_range() {
if !is_root && !range.specifier.as_str().contains("/$deno$eval") {
message.push_str(&format!("\n at {range}"));
if let Some(range) = error.maybe_range() {
if !is_root && !range.specifier.as_str().contains("/$deno$eval") {
message.push_str(&format!("\n at {range}"));
}
}
}
custom_error(get_error_class_name(&error.into()), message)
})
if options.is_vendoring {
// warn about failing dynamic imports when vendoring, but don't fail completely
if matches!(error, ModuleGraphError::MissingDynamic(_, _)) {
log::warn!("Ignoring: {:#}", message);
return None;
}
// ignore invalid downgrades and invalid local imports when vendoring
if let ModuleGraphError::ResolutionError(err) = &error {
if matches!(
err,
ResolutionError::InvalidDowngrade { .. }
| ResolutionError::InvalidLocalImport { .. }
) {
return None;
}
}
}
Some(custom_error(get_error_class_name(&error.into()), message))
});
if let Some(error) = errors.next() {
Err(error)
} else {
Ok(())
}
}
/// Checks the lockfile against the graph and and exits on errors.
@ -109,12 +150,11 @@ pub async fn create_graph_and_maybe_check(
PermissionsContainer::allow_all(),
);
let maybe_imports = ps.options.to_maybe_imports()?;
let maybe_cli_resolver = CliResolver::maybe_new(
let cli_resolver = CliGraphResolver::new(
ps.options.to_maybe_jsx_import_source_config(),
ps.maybe_import_map.clone(),
);
let maybe_graph_resolver =
maybe_cli_resolver.as_ref().map(|r| r.as_graph_resolver());
let graph_resolver = cli_resolver.as_graph_resolver();
let analyzer = ps.parsed_source_cache.as_analyzer();
let mut graph = ModuleGraph::default();
graph
@ -124,7 +164,7 @@ pub async fn create_graph_and_maybe_check(
deno_graph::BuildOptions {
is_dynamic: false,
imports: maybe_imports,
resolver: maybe_graph_resolver,
resolver: Some(graph_resolver),
module_analyzer: Some(&*analyzer),
reporter: None,
},

View file

@ -19,7 +19,7 @@ use crate::node::NodeResolution;
use crate::npm::NpmPackageReference;
use crate::npm::NpmPackageReq;
use crate::npm::NpmPackageResolver;
use crate::resolver::CliResolver;
use crate::resolver::CliGraphResolver;
use crate::util::path::specifier_to_file_path;
use crate::util::text_encoding;
@ -293,7 +293,7 @@ impl Document {
fs_version: String,
maybe_headers: Option<HashMap<String, String>>,
text_info: SourceTextInfo,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
) -> Self {
// we only ever do `Document::new` on on disk resources that are supposed to
// be diagnosable, unlike `Document::open`, so it is safe to unconditionally
@ -302,7 +302,7 @@ impl Document {
&specifier,
text_info.clone(),
maybe_headers.as_ref(),
maybe_resolver,
resolver,
);
let dependencies =
Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
@ -324,7 +324,7 @@ impl Document {
fn maybe_with_new_resolver(
&self,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
) -> Option<Self> {
let parsed_source_result = match &self.0.maybe_parsed_source {
Some(parsed_source_result) => parsed_source_result.clone(),
@ -334,7 +334,7 @@ impl Document {
&self.0.specifier,
&parsed_source_result,
self.0.maybe_headers.as_ref(),
maybe_resolver,
resolver,
));
let dependencies =
Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
@ -360,7 +360,7 @@ impl Document {
version: i32,
language_id: LanguageId,
content: Arc<str>,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
) -> Self {
let maybe_headers = language_id.as_headers();
let text_info = SourceTextInfo::new(content);
@ -369,7 +369,7 @@ impl Document {
&specifier,
text_info.clone(),
maybe_headers,
maybe_resolver,
resolver,
)
} else {
(None, None)
@ -396,7 +396,7 @@ impl Document {
&self,
version: i32,
changes: Vec<lsp::TextDocumentContentChangeEvent>,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
) -> Result<Document, AnyError> {
let mut content = self.0.text_info.text_str().to_string();
let mut line_index = self.0.line_index.clone();
@ -431,7 +431,7 @@ impl Document {
&self.0.specifier,
text_info.clone(),
maybe_headers,
maybe_resolver,
resolver,
)
} else {
(None, None)
@ -715,7 +715,7 @@ impl FileSystemDocuments {
pub fn get(
&mut self,
cache: &HttpCache,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
specifier: &ModuleSpecifier,
) -> Option<Document> {
let fs_version = get_document_path(cache, specifier)
@ -723,7 +723,7 @@ impl FileSystemDocuments {
let file_system_doc = self.docs.get(specifier);
if file_system_doc.map(|d| d.fs_version().to_string()) != fs_version {
// attempt to update the file on the file system
self.refresh_document(cache, maybe_resolver, specifier)
self.refresh_document(cache, resolver, specifier)
} else {
file_system_doc.cloned()
}
@ -734,7 +734,7 @@ impl FileSystemDocuments {
fn refresh_document(
&mut self,
cache: &HttpCache,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
specifier: &ModuleSpecifier,
) -> Option<Document> {
let path = get_document_path(cache, specifier)?;
@ -749,7 +749,7 @@ impl FileSystemDocuments {
fs_version,
None,
SourceTextInfo::from_string(content),
maybe_resolver,
resolver,
)
} else {
let cache_filename = cache.get_cache_filename(specifier)?;
@ -763,7 +763,7 @@ impl FileSystemDocuments {
fs_version,
maybe_headers,
SourceTextInfo::from_string(content),
maybe_resolver,
resolver,
)
};
self.dirty = true;
@ -773,10 +773,10 @@ impl FileSystemDocuments {
pub fn refresh_dependencies(
&mut self,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
) {
for doc in self.docs.values_mut() {
if let Some(new_doc) = doc.maybe_with_new_resolver(maybe_resolver) {
if let Some(new_doc) = doc.maybe_with_new_resolver(resolver) {
*doc = new_doc;
}
}
@ -817,7 +817,7 @@ pub struct Documents {
imports: Arc<HashMap<ModuleSpecifier, GraphImport>>,
/// A resolver that takes into account currently loaded import map and JSX
/// settings.
maybe_resolver: Option<CliResolver>,
resolver: CliGraphResolver,
/// The npm package requirements.
npm_reqs: Arc<HashSet<NpmPackageReq>>,
/// Gets if any document had a node: specifier such that a @types/node package
@ -837,7 +837,7 @@ impl Documents {
file_system_docs: Default::default(),
resolver_config_hash: 0,
imports: Default::default(),
maybe_resolver: None,
resolver: CliGraphResolver::default(),
npm_reqs: Default::default(),
has_injected_types_node_package: false,
specifier_resolver: Arc::new(SpecifierResolver::new(location)),
@ -855,13 +855,13 @@ impl Documents {
language_id: LanguageId,
content: Arc<str>,
) -> Document {
let maybe_resolver = self.get_maybe_resolver();
let resolver = self.get_resolver();
let document = Document::open(
specifier.clone(),
version,
language_id,
content,
maybe_resolver,
resolver,
);
let mut file_system_docs = self.file_system_docs.lock();
file_system_docs.docs.remove(&specifier);
@ -896,7 +896,7 @@ impl Documents {
Ok,
)?;
self.dirty = true;
let doc = doc.with_change(version, changes, self.get_maybe_resolver())?;
let doc = doc.with_change(version, changes, self.get_resolver())?;
self.open_docs.insert(doc.specifier().clone(), doc.clone());
Ok(doc)
}
@ -929,12 +929,7 @@ impl Documents {
specifier: &str,
referrer: &ModuleSpecifier,
) -> bool {
let maybe_resolver = self.get_maybe_resolver();
let maybe_specifier = if let Some(resolver) = maybe_resolver {
resolver.resolve(specifier, referrer).ok()
} else {
deno_core::resolve_import(specifier, referrer.as_str()).ok()
};
let maybe_specifier = self.get_resolver().resolve(specifier, referrer).ok();
if let Some(import_specifier) = maybe_specifier {
self.exists(&import_specifier)
} else {
@ -993,7 +988,7 @@ impl Documents {
Some(document.clone())
} else {
let mut file_system_docs = self.file_system_docs.lock();
file_system_docs.get(&self.cache, self.get_maybe_resolver(), &specifier)
file_system_docs.get(&self.cache, self.get_resolver(), &specifier)
}
}
@ -1186,8 +1181,7 @@ impl Documents {
maybe_import_map.as_deref(),
maybe_jsx_config.as_ref(),
);
self.maybe_resolver =
CliResolver::maybe_new(maybe_jsx_config, maybe_import_map);
self.resolver = CliGraphResolver::new(maybe_jsx_config, maybe_import_map);
self.imports = Arc::new(
if let Some(Ok(imports)) =
maybe_config_file.map(|cf| cf.to_maybe_imports())
@ -1198,7 +1192,7 @@ impl Documents {
let graph_import = GraphImport::new(
&import.referrer,
import.imports,
self.get_maybe_resolver(),
Some(self.get_resolver()),
);
(import.referrer, graph_import)
})
@ -1218,17 +1212,13 @@ impl Documents {
}
fn refresh_dependencies(&mut self) {
let maybe_resolver =
self.maybe_resolver.as_ref().map(|r| r.as_graph_resolver());
let resolver = self.resolver.as_graph_resolver();
for doc in self.open_docs.values_mut() {
if let Some(new_doc) = doc.maybe_with_new_resolver(maybe_resolver) {
if let Some(new_doc) = doc.maybe_with_new_resolver(resolver) {
*doc = new_doc;
}
}
self
.file_system_docs
.lock()
.refresh_dependencies(maybe_resolver);
self.file_system_docs.lock().refresh_dependencies(resolver);
}
/// Iterate through the documents, building a map where the key is a unique
@ -1295,10 +1285,9 @@ impl Documents {
doc_analyzer.analyze_doc(specifier, doc);
}
let maybe_resolver = self.get_maybe_resolver();
let resolver = self.get_resolver();
while let Some(specifier) = doc_analyzer.pending_specifiers.pop_front() {
if let Some(doc) =
file_system_docs.get(&self.cache, maybe_resolver, &specifier)
if let Some(doc) = file_system_docs.get(&self.cache, resolver, &specifier)
{
doc_analyzer.analyze_doc(&specifier, &doc);
}
@ -1321,8 +1310,8 @@ impl Documents {
file_system_docs.dirty = false;
}
fn get_maybe_resolver(&self) -> Option<&dyn deno_graph::source::Resolver> {
self.maybe_resolver.as_ref().map(|r| r.as_graph_resolver())
fn get_resolver(&self) -> &dyn deno_graph::source::Resolver {
self.resolver.as_graph_resolver()
}
fn resolve_dependency(
@ -1403,15 +1392,11 @@ fn parse_and_analyze_module(
specifier: &ModuleSpecifier,
text_info: SourceTextInfo,
maybe_headers: Option<&HashMap<String, String>>,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
) -> (Option<ParsedSourceResult>, Option<ModuleResult>) {
let parsed_source_result = parse_source(specifier, text_info, maybe_headers);
let module_result = analyze_module(
specifier,
&parsed_source_result,
maybe_headers,
maybe_resolver,
);
let module_result =
analyze_module(specifier, &parsed_source_result, maybe_headers, resolver);
(Some(parsed_source_result), Some(module_result))
}
@ -1434,7 +1419,7 @@ fn analyze_module(
specifier: &ModuleSpecifier,
parsed_source_result: &ParsedSourceResult,
maybe_headers: Option<&HashMap<String, String>>,
maybe_resolver: Option<&dyn deno_graph::source::Resolver>,
resolver: &dyn deno_graph::source::Resolver,
) -> ModuleResult {
match parsed_source_result {
Ok(parsed_source) => Ok(deno_graph::parse_module_from_ast(
@ -1442,7 +1427,7 @@ fn analyze_module(
deno_graph::ModuleKind::Esm,
maybe_headers,
parsed_source,
maybe_resolver,
Some(resolver),
)),
Err(err) => Err(deno_graph::ModuleGraphError::ParseErr(
specifier.clone(),

View file

@ -69,7 +69,7 @@ use crate::args::TsConfig;
use crate::cache::DenoDir;
use crate::cache::HttpCache;
use crate::file_fetcher::FileFetcher;
use crate::graph_util::graph_valid;
use crate::graph_util;
use crate::http_util::HttpClient;
use crate::npm::NpmCache;
use crate::npm::NpmPackageResolver;
@ -176,11 +176,11 @@ impl LanguageServer {
let graph = ps
.create_graph_with_loader(roots.clone(), &mut loader)
.await?;
graph_valid(
graph_util::graph_valid(
&graph,
&roots,
deno_graph::WalkOptions {
follow_dynamic: false,
graph_util::GraphValidOptions {
is_vendoring: false,
follow_type_only: true,
check_js: false,
},

View file

@ -30,7 +30,7 @@ use crate::args::flags_from_vec;
use crate::args::DenoSubcommand;
use crate::args::Flags;
use crate::proc_state::ProcState;
use crate::resolver::CliResolver;
use crate::resolver::CliGraphResolver;
use crate::util::display;
use crate::util::v8::get_v8_flags_from_env;
use crate::util::v8::init_v8_flags;

View file

@ -28,7 +28,7 @@ use crate::npm::NpmPackageReference;
use crate::npm::NpmPackageReq;
use crate::npm::NpmPackageResolver;
use crate::npm::RealNpmRegistryApi;
use crate::resolver::CliResolver;
use crate::resolver::CliGraphResolver;
use crate::tools::check;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
@ -58,6 +58,7 @@ use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::permissions::PermissionsContainer;
use import_map::ImportMap;
use log::warn;
use std::borrow::Cow;
use std::collections::HashMap;
use std::collections::HashSet;
use std::ops::Deref;
@ -90,7 +91,7 @@ pub struct Inner {
pub shared_array_buffer_store: SharedArrayBufferStore,
pub compiled_wasm_module_store: CompiledWasmModuleStore,
pub parsed_source_cache: ParsedSourceCache,
pub maybe_resolver: Option<Arc<CliResolver>>,
pub resolver: Arc<CliGraphResolver>,
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
pub node_analysis_cache: NodeAnalysisCache,
pub npm_cache: NpmCache,
@ -152,7 +153,7 @@ impl ProcState {
shared_array_buffer_store: Default::default(),
compiled_wasm_module_store: Default::default(),
parsed_source_cache: self.parsed_source_cache.reset_for_file_watcher(),
maybe_resolver: self.maybe_resolver.clone(),
resolver: self.resolver.clone(),
maybe_file_watcher_reporter: self.maybe_file_watcher_reporter.clone(),
node_analysis_cache: self.node_analysis_cache.clone(),
npm_cache: self.npm_cache.clone(),
@ -219,11 +220,10 @@ impl ProcState {
let maybe_inspector_server =
cli_options.resolve_inspector_server().map(Arc::new);
let maybe_cli_resolver = CliResolver::maybe_new(
let resolver = Arc::new(CliGraphResolver::new(
cli_options.to_maybe_jsx_import_source_config(),
maybe_import_map.clone(),
);
let maybe_resolver = maybe_cli_resolver.map(Arc::new);
));
let maybe_file_watcher_reporter =
maybe_sender.map(|sender| FileWatcherReporter {
@ -286,7 +286,7 @@ impl ProcState {
shared_array_buffer_store,
compiled_wasm_module_store,
parsed_source_cache,
maybe_resolver,
resolver,
maybe_file_watcher_reporter,
node_analysis_cache,
npm_cache,
@ -320,8 +320,7 @@ impl ProcState {
dynamic_permissions,
);
let maybe_imports = self.options.to_maybe_imports()?;
let maybe_resolver =
self.maybe_resolver.as_ref().map(|r| r.as_graph_resolver());
let resolver = self.resolver.as_graph_resolver();
let maybe_file_watcher_reporter: Option<&dyn deno_graph::source::Reporter> =
if let Some(reporter) = &self.maybe_file_watcher_reporter {
Some(reporter)
@ -346,7 +345,7 @@ impl ProcState {
deno_graph::BuildOptions {
is_dynamic,
imports: maybe_imports,
resolver: maybe_resolver,
resolver: Some(resolver),
module_analyzer: Some(&*analyzer),
reporter: maybe_file_watcher_reporter,
},
@ -589,12 +588,14 @@ impl ProcState {
// FIXME(bartlomieju): this is another hack way to provide NPM specifier
// support in REPL. This should be fixed.
let resolution = self.resolver.resolve(specifier, &referrer);
if is_repl {
let specifier = self
.maybe_resolver
let specifier = resolution
.as_ref()
.and_then(|resolver| resolver.resolve(specifier, &referrer).ok())
.or_else(|| ModuleSpecifier::parse(specifier).ok());
.ok()
.map(Cow::Borrowed)
.or_else(|| ModuleSpecifier::parse(specifier).ok().map(Cow::Owned));
if let Some(specifier) = specifier {
if let Ok(reference) = NpmPackageReference::from_specifier(&specifier) {
return self
@ -609,12 +610,7 @@ impl ProcState {
}
}
if let Some(resolver) = &self.maybe_resolver {
resolver.resolve(specifier, &referrer)
} else {
deno_core::resolve_import(specifier, referrer.as_str())
.map_err(|err| err.into())
}
resolution
}
pub fn cache_module_emits(&self) -> Result<(), AnyError> {
@ -671,12 +667,11 @@ impl ProcState {
) -> Result<deno_graph::ModuleGraph, AnyError> {
let maybe_imports = self.options.to_maybe_imports()?;
let maybe_cli_resolver = CliResolver::maybe_new(
let cli_resolver = CliGraphResolver::new(
self.options.to_maybe_jsx_import_source_config(),
self.maybe_import_map.clone(),
);
let maybe_graph_resolver =
maybe_cli_resolver.as_ref().map(|r| r.as_graph_resolver());
let graph_resolver = cli_resolver.as_graph_resolver();
let analyzer = self.parsed_source_cache.as_analyzer();
let mut graph = ModuleGraph::default();
@ -687,7 +682,7 @@ impl ProcState {
deno_graph::BuildOptions {
is_dynamic: false,
imports: maybe_imports,
resolver: maybe_graph_resolver,
resolver: Some(graph_resolver),
module_analyzer: Some(&*analyzer),
reporter: None,
},

View file

@ -1,7 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::resolve_import;
use deno_core::ModuleSpecifier;
use deno_graph::source::Resolver;
use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE;
@ -13,41 +12,33 @@ use crate::args::JsxImportSourceConfig;
/// A resolver that takes care of resolution, taking into account loaded
/// import map, JSX settings.
#[derive(Debug, Clone, Default)]
pub struct CliResolver {
pub struct CliGraphResolver {
maybe_import_map: Option<Arc<ImportMap>>,
maybe_default_jsx_import_source: Option<String>,
maybe_jsx_import_source_module: Option<String>,
}
impl CliResolver {
pub fn maybe_new(
impl CliGraphResolver {
pub fn new(
maybe_jsx_import_source_config: Option<JsxImportSourceConfig>,
maybe_import_map: Option<Arc<ImportMap>>,
) -> Option<Self> {
if maybe_jsx_import_source_config.is_some() || maybe_import_map.is_some() {
Some(Self {
maybe_import_map,
maybe_default_jsx_import_source: maybe_jsx_import_source_config
.as_ref()
.and_then(|c| c.default_specifier.clone()),
maybe_jsx_import_source_module: maybe_jsx_import_source_config
.map(|c| c.module),
})
} else {
None
) -> Self {
Self {
maybe_import_map,
maybe_default_jsx_import_source: maybe_jsx_import_source_config
.as_ref()
.and_then(|c| c.default_specifier.clone()),
maybe_jsx_import_source_module: maybe_jsx_import_source_config
.map(|c| c.module),
}
}
pub fn with_import_map(import_map: Arc<ImportMap>) -> Self {
Self::maybe_new(None, Some(import_map)).unwrap()
}
pub fn as_graph_resolver(&self) -> &dyn Resolver {
self
}
}
impl Resolver for CliResolver {
impl Resolver for CliGraphResolver {
fn default_jsx_import_source(&self) -> Option<String> {
self.maybe_default_jsx_import_source.clone()
}
@ -69,7 +60,7 @@ impl Resolver for CliResolver {
.resolve(specifier, referrer)
.map_err(|err| err.into())
} else {
resolve_import(specifier, referrer.as_str()).map_err(|err| err.into())
deno_graph::resolve_import(specifier, referrer).map_err(|err| err.into())
}
}
}

View file

@ -8,7 +8,7 @@ use crate::ops;
use crate::proc_state::ProcState;
use crate::util::v8::construct_v8_flags;
use crate::version;
use crate::CliResolver;
use crate::CliGraphResolver;
use deno_core::anyhow::Context;
use deno_core::error::type_error;
use deno_core::error::AnyError;
@ -127,7 +127,7 @@ fn u64_from_bytes(arr: &[u8]) -> Result<u64, AnyError> {
struct EmbeddedModuleLoader {
eszip: eszip::EszipV2,
maybe_import_map_resolver: Option<CliResolver>,
maybe_import_map_resolver: Option<CliGraphResolver>,
}
impl ModuleLoader for EmbeddedModuleLoader {
@ -235,9 +235,12 @@ pub async fn run(
eszip,
maybe_import_map_resolver: metadata.maybe_import_map.map(
|(base, source)| {
CliResolver::with_import_map(Arc::new(
parse_from_json(&base, &source).unwrap().import_map,
))
CliGraphResolver::new(
None,
Some(Arc::new(
parse_from_json(&base, &source).unwrap().import_map,
)),
)
},
),
});

View file

@ -3379,6 +3379,9 @@ async fn test_resolve_dns() {
.unwrap();
let err = String::from_utf8_lossy(&output.stderr);
let out = String::from_utf8_lossy(&output.stdout);
if !output.status.success() {
eprintln!("stderr: {err}");
}
assert!(output.status.success());
assert!(err.starts_with("Check file"));

View file

@ -478,6 +478,14 @@ fn dynamic_non_analyzable_import() {
assert!(output.status.success());
}
itest!(dynamic_non_existent {
args: "vendor http://localhost:4545/vendor/dynamic_non_existent.ts",
temp_cwd: true,
exit_code: 0,
http_server: true,
output: "vendor/dynamic_non_existent.ts.out",
});
#[test]
fn update_existing_config_test() {
let _server = http_server();

View file

@ -0,0 +1,11 @@
// this should still vendor
// deno-lint-ignore no-constant-condition
if (false) {
await import("./non-existent.js");
}
export class Logger {
log(text: string) {
console.log(text);
}
}

View file

@ -0,0 +1,7 @@
Download http://localhost:4545/vendor/dynamic_non_existent.ts
Download http://localhost:4545/vendor/non-existent.js
Ignoring: Dynamic import not found "http://localhost:4545/vendor/non-existent.js".
at http://localhost:4545/vendor/dynamic_non_existent.ts:4:16
Vendored 1 module into vendor/ directory.
To use vendored modules, specify the `--import-map vendor/import_map.json` flag when invoking Deno subcommands or add an `"importMap": "<path_to_vendored_import_map>"` entry to a deno.json file.

View file

@ -618,7 +618,8 @@ impl<'a> GraphDisplayContext<'a> {
ModuleGraphError::UnsupportedMediaType { .. } => {
self.build_error_msg(specifier, "(unsupported)")
}
ModuleGraphError::Missing(_, _) => {
ModuleGraphError::Missing(_, _)
| ModuleGraphError::MissingDynamic(_, _) => {
self.build_error_msg(specifier, "(missing)")
}
}

View file

@ -444,9 +444,9 @@ impl ReplSession {
.flat_map(|i| {
self
.proc_state
.maybe_resolver
.as_ref()
.and_then(|resolver| resolver.resolve(i, &self.referrer).ok())
.resolver
.resolve(i, &self.referrer)
.ok()
.or_else(|| ModuleSpecifier::parse(i).ok())
})
.collect::<Vec<_>>();

View file

@ -82,10 +82,9 @@ pub fn build(
graph_util::graph_valid(
&graph,
&graph.roots,
deno_graph::WalkOptions {
// surface all errors
graph_util::GraphValidOptions {
is_vendoring: true,
check_js: true,
follow_dynamic: true,
follow_type_only: true,
},
)?;

View file

@ -290,7 +290,12 @@ fn handle_dep_specifier(
referrer: &ModuleSpecifier,
mappings: &Mappings,
) {
let specifier = graph.resolve(unresolved_specifier);
let specifier = match graph.get(unresolved_specifier) {
Some(module) => module.specifier.clone(),
// Ignore when None. The graph was previous validated so this is a
// dynamic import that was missing and is ignored for vendoring
None => return,
};
// check if it's referencing a remote module
if is_remote_specifier(&specifier) {
handle_remote_dep_specifier(

View file

@ -20,7 +20,7 @@ use deno_graph::ModuleGraph;
use import_map::ImportMap;
use crate::cache::ParsedSourceCache;
use crate::resolver::CliResolver;
use crate::resolver::CliGraphResolver;
use super::build::VendorEnvironment;
@ -261,7 +261,7 @@ async fn build_test_graph(
analyzer: &dyn deno_graph::ModuleAnalyzer,
) -> ModuleGraph {
let resolver =
original_import_map.map(|m| CliResolver::with_import_map(Arc::new(m)));
original_import_map.map(|m| CliGraphResolver::new(None, Some(Arc::new(m))));
let mut graph = ModuleGraph::default();
graph
.build(