mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 12:58:54 -05:00
parent
b6d5ae1ecd
commit
63a821b78b
16 changed files with 446 additions and 269 deletions
|
@ -46,7 +46,7 @@ impl DiskCache {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cache_filename(&self, url: &Url) -> PathBuf {
|
fn get_cache_filename(&self, url: &Url) -> Option<PathBuf> {
|
||||||
let mut out = PathBuf::new();
|
let mut out = PathBuf::new();
|
||||||
|
|
||||||
let scheme = url.scheme();
|
let scheme = url.scheme();
|
||||||
|
@ -105,31 +105,25 @@ impl DiskCache {
|
||||||
|
|
||||||
out = out.join(remaining_components);
|
out = out.join(remaining_components);
|
||||||
}
|
}
|
||||||
scheme => {
|
_ => return None,
|
||||||
unimplemented!(
|
|
||||||
"Don't know how to create cache name for scheme: {}\n Url: {}",
|
|
||||||
scheme,
|
|
||||||
url
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
out
|
Some(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cache_filename_with_extension(
|
pub fn get_cache_filename_with_extension(
|
||||||
&self,
|
&self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
extension: &str,
|
extension: &str,
|
||||||
) -> PathBuf {
|
) -> Option<PathBuf> {
|
||||||
let base = self.get_cache_filename(url);
|
let base = self.get_cache_filename(url)?;
|
||||||
|
|
||||||
match base.extension() {
|
match base.extension() {
|
||||||
None => base.with_extension(extension),
|
None => Some(base.with_extension(extension)),
|
||||||
Some(ext) => {
|
Some(ext) => {
|
||||||
let original_extension = OsStr::to_str(ext).unwrap();
|
let original_extension = OsStr::to_str(ext).unwrap();
|
||||||
let final_extension = format!("{}.{}", original_extension, extension);
|
let final_extension = format!("{}.{}", original_extension, extension);
|
||||||
base.with_extension(final_extension)
|
Some(base.with_extension(final_extension))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +228,7 @@ mod tests {
|
||||||
for test_case in &test_cases {
|
for test_case in &test_cases {
|
||||||
let cache_filename =
|
let cache_filename =
|
||||||
cache.get_cache_filename(&Url::parse(test_case.0).unwrap());
|
cache.get_cache_filename(&Url::parse(test_case.0).unwrap());
|
||||||
assert_eq!(cache_filename, PathBuf::from(test_case.1));
|
assert_eq!(cache_filename, Some(PathBuf::from(test_case.1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +274,7 @@ mod tests {
|
||||||
&Url::parse(test_case.0).unwrap(),
|
&Url::parse(test_case.0).unwrap(),
|
||||||
test_case.1
|
test_case.1
|
||||||
),
|
),
|
||||||
PathBuf::from(test_case.2)
|
Some(PathBuf::from(test_case.2))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ use crate::tsc_config::TsConfig;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
use crate::AnyError;
|
use crate::AnyError;
|
||||||
|
|
||||||
|
use deno_core::error::anyhow;
|
||||||
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::Context;
|
use deno_core::error::Context;
|
||||||
use deno_core::futures::stream::FuturesUnordered;
|
use deno_core::futures::stream::FuturesUnordered;
|
||||||
use deno_core::futures::stream::StreamExt;
|
use deno_core::futures::stream::StreamExt;
|
||||||
|
@ -38,6 +40,7 @@ use deno_core::serde::Serializer;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::serde_json::Value;
|
use deno_core::serde_json::Value;
|
||||||
use deno_core::ModuleResolutionError;
|
use deno_core::ModuleResolutionError;
|
||||||
|
use deno_core::ModuleSource;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -482,6 +485,10 @@ impl Module {
|
||||||
Ok(specifier)
|
Ok(specifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_emit(&mut self, code: String, maybe_map: Option<String>) {
|
||||||
|
self.maybe_emit = Some(Emit::Cli((code, maybe_map)));
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate the hashed version of the module and update the `maybe_version`.
|
/// Calculate the hashed version of the module and update the `maybe_version`.
|
||||||
pub fn set_version(&mut self, config: &[u8]) {
|
pub fn set_version(&mut self, config: &[u8]) {
|
||||||
self.maybe_version =
|
self.maybe_version =
|
||||||
|
@ -523,6 +530,9 @@ pub struct ResultInfo {
|
||||||
/// A structure which provides diagnostic information (usually from `tsc`)
|
/// A structure which provides diagnostic information (usually from `tsc`)
|
||||||
/// about the code in the module graph.
|
/// about the code in the module graph.
|
||||||
pub diagnostics: Diagnostics,
|
pub diagnostics: Diagnostics,
|
||||||
|
/// A map of specifiers to the result of their resolution in the module graph.
|
||||||
|
pub loadable_modules:
|
||||||
|
HashMap<ModuleSpecifier, Result<ModuleSource, AnyError>>,
|
||||||
/// Optionally ignored compiler options that represent any options that were
|
/// Optionally ignored compiler options that represent any options that were
|
||||||
/// ignored if there was a user provided configuration.
|
/// ignored if there was a user provided configuration.
|
||||||
pub maybe_ignored_options: Option<IgnoredCompilerOptions>,
|
pub maybe_ignored_options: Option<IgnoredCompilerOptions>,
|
||||||
|
@ -637,6 +647,18 @@ pub struct TranspileOptions {
|
||||||
pub reload: bool,
|
pub reload: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum ModuleSlot {
|
||||||
|
/// The module fetch resulted in a non-recoverable error.
|
||||||
|
Err(Rc<AnyError>),
|
||||||
|
/// The the fetch resulted in a module.
|
||||||
|
Module(Box<Module>),
|
||||||
|
/// Used to denote a module that isn't part of the graph.
|
||||||
|
None,
|
||||||
|
/// The fetch of the module is pending.
|
||||||
|
Pending,
|
||||||
|
}
|
||||||
|
|
||||||
/// A dependency graph of modules, were the modules that have been inserted via
|
/// A dependency graph of modules, were the modules that have been inserted via
|
||||||
/// the builder will be loaded into the graph. Also provides an interface to
|
/// the builder will be loaded into the graph. Also provides an interface to
|
||||||
/// be able to manipulate and handle the graph.
|
/// be able to manipulate and handle the graph.
|
||||||
|
@ -649,7 +671,7 @@ pub struct Graph {
|
||||||
/// invoked.
|
/// invoked.
|
||||||
maybe_tsbuildinfo: Option<String>,
|
maybe_tsbuildinfo: Option<String>,
|
||||||
/// The modules that are part of the graph.
|
/// The modules that are part of the graph.
|
||||||
modules: HashMap<ModuleSpecifier, Module>,
|
modules: HashMap<ModuleSpecifier, ModuleSlot>,
|
||||||
/// A map of redirects, where a module specifier is redirected to another
|
/// A map of redirects, where a module specifier is redirected to another
|
||||||
/// module specifier by the handler. All modules references should be
|
/// module specifier by the handler. All modules references should be
|
||||||
/// resolved internally via this, before attempting to access the module via
|
/// resolved internally via this, before attempting to access the module via
|
||||||
|
@ -667,6 +689,44 @@ pub struct Graph {
|
||||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert a specifier and a module slot in a result to the module source which
|
||||||
|
/// is needed by Deno core for loading the module.
|
||||||
|
fn to_module_result(
|
||||||
|
(specifier, module_slot): (&ModuleSpecifier, &ModuleSlot),
|
||||||
|
) -> (ModuleSpecifier, Result<ModuleSource, AnyError>) {
|
||||||
|
match module_slot {
|
||||||
|
ModuleSlot::Err(err) => (specifier.clone(), Err(anyhow!(err.to_string()))),
|
||||||
|
ModuleSlot::Module(module) => (
|
||||||
|
specifier.clone(),
|
||||||
|
if let Some(emit) = &module.maybe_emit {
|
||||||
|
match emit {
|
||||||
|
Emit::Cli((code, _)) => Ok(ModuleSource {
|
||||||
|
code: code.clone(),
|
||||||
|
module_url_found: module.specifier.to_string(),
|
||||||
|
module_url_specified: specifier.to_string(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match module.media_type {
|
||||||
|
MediaType::JavaScript | MediaType::Unknown => Ok(ModuleSource {
|
||||||
|
code: module.source.clone(),
|
||||||
|
module_url_found: module.specifier.to_string(),
|
||||||
|
module_url_specified: specifier.to_string(),
|
||||||
|
}),
|
||||||
|
_ => Err(custom_error(
|
||||||
|
"NotFound",
|
||||||
|
format!("Compiled module not found \"{}\"", specifier),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_ => (
|
||||||
|
specifier.clone(),
|
||||||
|
Err(anyhow!("Module \"{}\" unavailable.", specifier)),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Graph {
|
impl Graph {
|
||||||
/// Create a new instance of a graph, ready to have modules loaded it.
|
/// Create a new instance of a graph, ready to have modules loaded it.
|
||||||
///
|
///
|
||||||
|
@ -767,6 +827,7 @@ impl Graph {
|
||||||
debug!("graph does not need to be checked or emitted.");
|
debug!("graph does not need to be checked or emitted.");
|
||||||
return Ok(ResultInfo {
|
return Ok(ResultInfo {
|
||||||
maybe_ignored_options,
|
maybe_ignored_options,
|
||||||
|
loadable_modules: self.get_loadable_modules(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -834,9 +895,10 @@ impl Graph {
|
||||||
}
|
}
|
||||||
let config = config.as_bytes();
|
let config = config.as_bytes();
|
||||||
for (specifier, code) in codes.iter() {
|
for (specifier, code) in codes.iter() {
|
||||||
if let Some(module) = graph.get_module_mut(specifier) {
|
if let ModuleSlot::Module(module) =
|
||||||
module.maybe_emit =
|
graph.get_module_mut(specifier).unwrap()
|
||||||
Some(Emit::Cli((code.clone(), maps.get(specifier).cloned())));
|
{
|
||||||
|
module.set_emit(code.clone(), maps.get(specifier).cloned());
|
||||||
module.set_version(&config);
|
module.set_version(&config);
|
||||||
module.is_dirty = true;
|
module.is_dirty = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -849,16 +911,12 @@ impl Graph {
|
||||||
|
|
||||||
Ok(ResultInfo {
|
Ok(ResultInfo {
|
||||||
diagnostics: response.diagnostics,
|
diagnostics: response.diagnostics,
|
||||||
|
loadable_modules: graph.get_loadable_modules(),
|
||||||
maybe_ignored_options,
|
maybe_ignored_options,
|
||||||
stats: response.stats,
|
stats: response.stats,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_module(&self, specifier: &ModuleSpecifier) -> bool {
|
|
||||||
let s = self.resolve_specifier(specifier);
|
|
||||||
self.modules.contains_key(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Emit the module graph in a specific format. This is specifically designed
|
/// Emit the module graph in a specific format. This is specifically designed
|
||||||
/// to be an "all-in-one" API for access by the runtime, allowing both
|
/// to be an "all-in-one" API for access by the runtime, allowing both
|
||||||
/// emitting single modules as well as bundles, using Deno module resolution
|
/// emitting single modules as well as bundles, using Deno module resolution
|
||||||
|
@ -921,13 +979,13 @@ impl Graph {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut emitted_files = HashMap::new();
|
let mut emitted_files = HashMap::new();
|
||||||
|
let graph = graph.borrow();
|
||||||
match options.bundle_type {
|
match options.bundle_type {
|
||||||
BundleType::Esm => {
|
BundleType::Esm => {
|
||||||
assert!(
|
assert!(
|
||||||
response.emitted_files.is_empty(),
|
response.emitted_files.is_empty(),
|
||||||
"No files should have been emitted from tsc."
|
"No files should have been emitted from tsc."
|
||||||
);
|
);
|
||||||
let graph = graph.borrow();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
graph.roots.len(),
|
graph.roots.len(),
|
||||||
1,
|
1,
|
||||||
|
@ -966,6 +1024,7 @@ impl Graph {
|
||||||
emitted_files,
|
emitted_files,
|
||||||
ResultInfo {
|
ResultInfo {
|
||||||
diagnostics: response.diagnostics,
|
diagnostics: response.diagnostics,
|
||||||
|
loadable_modules: graph.get_loadable_modules(),
|
||||||
maybe_ignored_options,
|
maybe_ignored_options,
|
||||||
stats: response.stats,
|
stats: response.stats,
|
||||||
},
|
},
|
||||||
|
@ -1023,15 +1082,17 @@ impl Graph {
|
||||||
/// any build info if present.
|
/// any build info if present.
|
||||||
fn flush(&mut self) -> Result<(), AnyError> {
|
fn flush(&mut self) -> Result<(), AnyError> {
|
||||||
let mut handler = self.handler.borrow_mut();
|
let mut handler = self.handler.borrow_mut();
|
||||||
for (_, module) in self.modules.iter_mut() {
|
for (_, module_slot) in self.modules.iter_mut() {
|
||||||
if module.is_dirty {
|
if let ModuleSlot::Module(module) = module_slot {
|
||||||
if let Some(emit) = &module.maybe_emit {
|
if module.is_dirty {
|
||||||
handler.set_cache(&module.specifier, emit)?;
|
if let Some(emit) = &module.maybe_emit {
|
||||||
|
handler.set_cache(&module.specifier, emit)?;
|
||||||
|
}
|
||||||
|
if let Some(version) = &module.maybe_version {
|
||||||
|
handler.set_version(&module.specifier, version.clone())?;
|
||||||
|
}
|
||||||
|
module.is_dirty = false;
|
||||||
}
|
}
|
||||||
if let Some(version) = &module.maybe_version {
|
|
||||||
handler.set_version(&module.specifier, version.clone())?;
|
|
||||||
}
|
|
||||||
module.is_dirty = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for root_specifier in self.roots.iter() {
|
for root_specifier in self.roots.iter() {
|
||||||
|
@ -1050,7 +1111,12 @@ impl Graph {
|
||||||
totals: &mut HashMap<ModuleSpecifier, usize>,
|
totals: &mut HashMap<ModuleSpecifier, usize>,
|
||||||
) -> ModuleInfo {
|
) -> ModuleInfo {
|
||||||
let not_seen = seen.insert(specifier.clone());
|
let not_seen = seen.insert(specifier.clone());
|
||||||
let module = self.get_module(specifier).unwrap();
|
let module = if let ModuleSlot::Module(module) = self.get_module(specifier)
|
||||||
|
{
|
||||||
|
module
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
let mut deps = Vec::new();
|
let mut deps = Vec::new();
|
||||||
let mut total_size = None;
|
let mut total_size = None;
|
||||||
|
|
||||||
|
@ -1097,50 +1163,79 @@ impl Graph {
|
||||||
let map = self
|
let map = self
|
||||||
.modules
|
.modules
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(specifier, module)| {
|
.filter_map(|(specifier, module_slot)| {
|
||||||
let mut deps = BTreeSet::new();
|
if let ModuleSlot::Module(module) = module_slot {
|
||||||
for (_, dep) in module.dependencies.iter() {
|
let mut deps = BTreeSet::new();
|
||||||
if let Some(code_dep) = &dep.maybe_code {
|
for (_, dep) in module.dependencies.iter() {
|
||||||
deps.insert(code_dep.clone());
|
if let Some(code_dep) = &dep.maybe_code {
|
||||||
|
deps.insert(code_dep.clone());
|
||||||
|
}
|
||||||
|
if let Some(type_dep) = &dep.maybe_type {
|
||||||
|
deps.insert(type_dep.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(type_dep) = &dep.maybe_type {
|
if let Some((_, types_dep)) = &module.maybe_types {
|
||||||
deps.insert(type_dep.clone());
|
deps.insert(types_dep.clone());
|
||||||
}
|
}
|
||||||
|
let item = ModuleInfoMapItem {
|
||||||
|
deps: deps.into_iter().collect(),
|
||||||
|
size: module.size(),
|
||||||
|
};
|
||||||
|
Some((specifier.clone(), item))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
if let Some((_, types_dep)) = &module.maybe_types {
|
|
||||||
deps.insert(types_dep.clone());
|
|
||||||
}
|
|
||||||
let item = ModuleInfoMapItem {
|
|
||||||
deps: deps.into_iter().collect(),
|
|
||||||
size: module.size(),
|
|
||||||
};
|
|
||||||
(specifier.clone(), item)
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
ModuleInfoMap::new(map)
|
ModuleInfoMap::new(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve a map that contains a representation of each module in the graph
|
||||||
|
/// which can be used to provide code to a module loader without holding all
|
||||||
|
/// the state to be able to operate on the graph.
|
||||||
|
pub fn get_loadable_modules(
|
||||||
|
&self,
|
||||||
|
) -> HashMap<ModuleSpecifier, Result<ModuleSource, AnyError>> {
|
||||||
|
let mut loadable_modules: HashMap<
|
||||||
|
ModuleSpecifier,
|
||||||
|
Result<ModuleSource, AnyError>,
|
||||||
|
> = self.modules.iter().map(to_module_result).collect();
|
||||||
|
for (specifier, _) in self.redirects.iter() {
|
||||||
|
if let Some(module_slot) =
|
||||||
|
self.modules.get(self.resolve_specifier(specifier))
|
||||||
|
{
|
||||||
|
let (_, result) = to_module_result((specifier, module_slot));
|
||||||
|
loadable_modules.insert(specifier.clone(), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadable_modules
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_media_type(
|
pub fn get_media_type(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Option<MediaType> {
|
) -> Option<MediaType> {
|
||||||
if let Some(module) = self.get_module(specifier) {
|
if let ModuleSlot::Module(module) = self.get_module(specifier) {
|
||||||
Some(module.media_type)
|
Some(module.media_type)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_module(&self, specifier: &ModuleSpecifier) -> Option<&Module> {
|
fn get_module(&self, specifier: &ModuleSpecifier) -> &ModuleSlot {
|
||||||
let s = self.resolve_specifier(specifier);
|
let s = self.resolve_specifier(specifier);
|
||||||
self.modules.get(s)
|
if let Some(module_slot) = self.modules.get(s) {
|
||||||
|
module_slot
|
||||||
|
} else {
|
||||||
|
&ModuleSlot::None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_module_mut(
|
fn get_module_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Option<&mut Module> {
|
) -> Option<&mut ModuleSlot> {
|
||||||
// this is duplicated code because `.resolve_specifier` requires an
|
// this is duplicated code because `.resolve_specifier` requires an
|
||||||
// immutable borrow, but if `.resolve_specifier` is mut, then everything
|
// immutable borrow, but if `.resolve_specifier` is mut, then everything
|
||||||
// that calls it is is mut
|
// that calls it is is mut
|
||||||
|
@ -1174,12 +1269,14 @@ impl Graph {
|
||||||
// files will not get emitted. To counter act that behavior, we will
|
// files will not get emitted. To counter act that behavior, we will
|
||||||
// include all modules that are emittable.
|
// include all modules that are emittable.
|
||||||
let mut specifiers = HashSet::<&ModuleSpecifier>::new();
|
let mut specifiers = HashSet::<&ModuleSpecifier>::new();
|
||||||
for (_, module) in self.modules.iter() {
|
for (_, module_slot) in self.modules.iter() {
|
||||||
if module.media_type == MediaType::JSX
|
if let ModuleSlot::Module(module) = module_slot {
|
||||||
|| module.media_type == MediaType::TypeScript
|
if module.media_type == MediaType::JSX
|
||||||
|| module.media_type == MediaType::TSX
|
|| module.media_type == MediaType::TypeScript
|
||||||
{
|
|| module.media_type == MediaType::TSX
|
||||||
specifiers.insert(&module.specifier);
|
{
|
||||||
|
specifiers.insert(&module.specifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We should include all the original roots as well.
|
// We should include all the original roots as well.
|
||||||
|
@ -1196,7 +1293,12 @@ impl Graph {
|
||||||
// if the root module has a types specifier, we should be sending that
|
// if the root module has a types specifier, we should be sending that
|
||||||
// to tsc instead of the original specifier
|
// to tsc instead of the original specifier
|
||||||
let specifier = self.resolve_specifier(ms);
|
let specifier = self.resolve_specifier(ms);
|
||||||
let module = self.get_module(specifier).unwrap();
|
let module =
|
||||||
|
if let ModuleSlot::Module(module) = self.get_module(specifier) {
|
||||||
|
module
|
||||||
|
} else {
|
||||||
|
panic!("missing module");
|
||||||
|
};
|
||||||
let specifier = if let Some((_, types_specifier)) = &module.maybe_types
|
let specifier = if let Some((_, types_specifier)) = &module.maybe_types
|
||||||
{
|
{
|
||||||
self.resolve_specifier(types_specifier)
|
self.resolve_specifier(types_specifier)
|
||||||
|
@ -1216,7 +1318,7 @@ impl Graph {
|
||||||
/// Get the source for a given module specifier. If the module is not part
|
/// Get the source for a given module specifier. If the module is not part
|
||||||
/// of the graph, the result will be `None`.
|
/// of the graph, the result will be `None`.
|
||||||
pub fn get_source(&self, specifier: &ModuleSpecifier) -> Option<String> {
|
pub fn get_source(&self, specifier: &ModuleSpecifier) -> Option<String> {
|
||||||
if let Some(module) = self.get_module(specifier) {
|
if let ModuleSlot::Module(module) = self.get_module(specifier) {
|
||||||
Some(module.source.clone())
|
Some(module.source.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1232,7 +1334,11 @@ impl Graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
let module = self.roots[0].clone();
|
let module = self.roots[0].clone();
|
||||||
let m = self.get_module(&module).unwrap();
|
let m = if let ModuleSlot::Module(module) = self.get_module(&module) {
|
||||||
|
module
|
||||||
|
} else {
|
||||||
|
return Err(GraphError::MissingSpecifier(module.clone()).into());
|
||||||
|
};
|
||||||
|
|
||||||
let mut seen = HashSet::new();
|
let mut seen = HashSet::new();
|
||||||
let mut totals = HashMap::new();
|
let mut totals = HashMap::new();
|
||||||
|
@ -1247,9 +1353,19 @@ impl Graph {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let dep_count = self
|
||||||
|
.modules
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(_, m)| match m {
|
||||||
|
ModuleSlot::Module(_) => Some(1),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.count()
|
||||||
|
- 1;
|
||||||
|
|
||||||
Ok(ModuleGraphInfo {
|
Ok(ModuleGraphInfo {
|
||||||
compiled,
|
compiled,
|
||||||
dep_count: self.modules.len() - 1,
|
dep_count,
|
||||||
file_type: m.media_type,
|
file_type: m.media_type,
|
||||||
files,
|
files,
|
||||||
info,
|
info,
|
||||||
|
@ -1267,15 +1383,19 @@ impl Graph {
|
||||||
let check_js = config.get_check_js();
|
let check_js = config.get_check_js();
|
||||||
let config = config.as_bytes();
|
let config = config.as_bytes();
|
||||||
self.modules.iter().all(|(_, m)| {
|
self.modules.iter().all(|(_, m)| {
|
||||||
let needs_emit = match m.media_type {
|
if let ModuleSlot::Module(m) = m {
|
||||||
MediaType::TypeScript | MediaType::TSX | MediaType::JSX => true,
|
let needs_emit = match m.media_type {
|
||||||
MediaType::JavaScript => check_js,
|
MediaType::TypeScript | MediaType::TSX | MediaType::JSX => true,
|
||||||
_ => false,
|
MediaType::JavaScript => check_js,
|
||||||
};
|
_ => false,
|
||||||
if needs_emit {
|
};
|
||||||
m.is_emit_valid(&config)
|
if needs_emit {
|
||||||
|
m.is_emit_valid(&config)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
true
|
false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1286,15 +1406,17 @@ impl Graph {
|
||||||
pub fn lock(&self) {
|
pub fn lock(&self) {
|
||||||
if let Some(lf) = self.maybe_lockfile.as_ref() {
|
if let Some(lf) = self.maybe_lockfile.as_ref() {
|
||||||
let mut lockfile = lf.lock().unwrap();
|
let mut lockfile = lf.lock().unwrap();
|
||||||
for (ms, module) in self.modules.iter() {
|
for (ms, module_slot) in self.modules.iter() {
|
||||||
let specifier = module.specifier.to_string();
|
if let ModuleSlot::Module(module) = module_slot {
|
||||||
let valid = lockfile.check_or_insert(&specifier, &module.source);
|
let specifier = module.specifier.to_string();
|
||||||
if !valid {
|
let valid = lockfile.check_or_insert(&specifier, &module.source);
|
||||||
eprintln!(
|
if !valid {
|
||||||
"{}",
|
eprintln!(
|
||||||
GraphError::InvalidSource(ms.clone(), lockfile.filename.clone())
|
"{}",
|
||||||
);
|
GraphError::InvalidSource(ms.clone(), lockfile.filename.clone())
|
||||||
std::process::exit(10);
|
);
|
||||||
|
std::process::exit(10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1305,9 +1427,12 @@ impl Graph {
|
||||||
/// checked to determine if it is valid.
|
/// checked to determine if it is valid.
|
||||||
fn needs_emit(&self, config: &TsConfig) -> bool {
|
fn needs_emit(&self, config: &TsConfig) -> bool {
|
||||||
let check_js = config.get_check_js();
|
let check_js = config.get_check_js();
|
||||||
self.modules.iter().any(|(_, m)| match m.media_type {
|
self.modules.iter().any(|(_, m)| match m {
|
||||||
MediaType::TypeScript | MediaType::TSX | MediaType::JSX => true,
|
ModuleSlot::Module(m) => match m.media_type {
|
||||||
MediaType::JavaScript => check_js,
|
MediaType::TypeScript | MediaType::TSX | MediaType::JSX => true,
|
||||||
|
MediaType::JavaScript => check_js,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1332,10 +1457,11 @@ impl Graph {
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
prefer_types: bool,
|
prefer_types: bool,
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
) -> Result<ModuleSpecifier, AnyError> {
|
||||||
if !self.contains_module(referrer) {
|
let module = if let ModuleSlot::Module(module) = self.get_module(referrer) {
|
||||||
return Err(GraphError::MissingSpecifier(referrer.to_owned()).into());
|
module
|
||||||
}
|
} else {
|
||||||
let module = self.get_module(referrer).unwrap();
|
return Err(GraphError::MissingSpecifier(referrer.clone()).into());
|
||||||
|
};
|
||||||
if !module.dependencies.contains_key(specifier) {
|
if !module.dependencies.contains_key(specifier) {
|
||||||
return Err(
|
return Err(
|
||||||
GraphError::MissingDependency(
|
GraphError::MissingDependency(
|
||||||
|
@ -1363,7 +1489,11 @@ impl Graph {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
if !self.contains_module(&resolved_specifier) {
|
let dep_module = if let ModuleSlot::Module(dep_module) =
|
||||||
|
self.get_module(&resolved_specifier)
|
||||||
|
{
|
||||||
|
dep_module
|
||||||
|
} else {
|
||||||
return Err(
|
return Err(
|
||||||
GraphError::MissingDependency(
|
GraphError::MissingDependency(
|
||||||
referrer.to_owned(),
|
referrer.to_owned(),
|
||||||
|
@ -1371,8 +1501,7 @@ impl Graph {
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
let dep_module = self.get_module(&resolved_specifier).unwrap();
|
|
||||||
// In the case that there is a X-TypeScript-Types or a triple-slash types,
|
// In the case that there is a X-TypeScript-Types or a triple-slash types,
|
||||||
// then the `maybe_types` specifier will be populated and we should use that
|
// then the `maybe_types` specifier will be populated and we should use that
|
||||||
// instead.
|
// instead.
|
||||||
|
@ -1424,7 +1553,7 @@ impl Graph {
|
||||||
pub fn transpile(
|
pub fn transpile(
|
||||||
&mut self,
|
&mut self,
|
||||||
options: TranspileOptions,
|
options: TranspileOptions,
|
||||||
) -> Result<(Stats, Option<IgnoredCompilerOptions>), AnyError> {
|
) -> Result<ResultInfo, AnyError> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
let mut ts_config = TsConfig::new(json!({
|
let mut ts_config = TsConfig::new(json!({
|
||||||
|
@ -1443,37 +1572,39 @@ impl Graph {
|
||||||
|
|
||||||
let mut emit_count: u128 = 0;
|
let mut emit_count: u128 = 0;
|
||||||
let config = ts_config.as_bytes();
|
let config = ts_config.as_bytes();
|
||||||
for (_, module) in self.modules.iter_mut() {
|
for (_, module_slot) in self.modules.iter_mut() {
|
||||||
// TODO(kitsonk) a lot of this logic should be refactored into `Module` as
|
if let ModuleSlot::Module(module) = module_slot {
|
||||||
// we start to support other methods on the graph. Especially managing
|
// TODO(kitsonk) a lot of this logic should be refactored into `Module` as
|
||||||
// the dirty state is something the module itself should "own".
|
// we start to support other methods on the graph. Especially managing
|
||||||
|
// the dirty state is something the module itself should "own".
|
||||||
|
|
||||||
// if the module is a Dts file we should skip it
|
// if the module is a Dts file we should skip it
|
||||||
if module.media_type == MediaType::Dts {
|
if module.media_type == MediaType::Dts {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
// if we don't have check_js enabled, we won't touch non TypeScript or JSX
|
||||||
|
// modules
|
||||||
|
if !(emit_options.check_js
|
||||||
|
|| module.media_type == MediaType::JSX
|
||||||
|
|| module.media_type == MediaType::TSX
|
||||||
|
|| module.media_type == MediaType::TypeScript)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// skip modules that already have a valid emit
|
||||||
|
if !options.reload && module.is_emit_valid(&config) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if module.maybe_parsed_module.is_none() {
|
||||||
|
module.parse()?;
|
||||||
|
}
|
||||||
|
let parsed_module = module.maybe_parsed_module.clone().unwrap();
|
||||||
|
let emit = parsed_module.transpile(&emit_options)?;
|
||||||
|
emit_count += 1;
|
||||||
|
module.maybe_emit = Some(Emit::Cli(emit));
|
||||||
|
module.set_version(&config);
|
||||||
|
module.is_dirty = true;
|
||||||
}
|
}
|
||||||
// if we don't have check_js enabled, we won't touch non TypeScript or JSX
|
|
||||||
// modules
|
|
||||||
if !(emit_options.check_js
|
|
||||||
|| module.media_type == MediaType::JSX
|
|
||||||
|| module.media_type == MediaType::TSX
|
|
||||||
|| module.media_type == MediaType::TypeScript)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// skip modules that already have a valid emit
|
|
||||||
if !options.reload && module.is_emit_valid(&config) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if module.maybe_parsed_module.is_none() {
|
|
||||||
module.parse()?;
|
|
||||||
}
|
|
||||||
let parsed_module = module.maybe_parsed_module.clone().unwrap();
|
|
||||||
let emit = parsed_module.transpile(&emit_options)?;
|
|
||||||
emit_count += 1;
|
|
||||||
module.maybe_emit = Some(Emit::Cli(emit));
|
|
||||||
module.set_version(&config);
|
|
||||||
module.is_dirty = true;
|
|
||||||
}
|
}
|
||||||
self.flush()?;
|
self.flush()?;
|
||||||
|
|
||||||
|
@ -1483,7 +1614,12 @@ impl Graph {
|
||||||
("Total time".to_string(), start.elapsed().as_millis()),
|
("Total time".to_string(), start.elapsed().as_millis()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Ok((stats, maybe_ignored_options))
|
Ok(ResultInfo {
|
||||||
|
diagnostics: Default::default(),
|
||||||
|
loadable_modules: self.get_loadable_modules(),
|
||||||
|
maybe_ignored_options,
|
||||||
|
stats,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1510,7 +1646,6 @@ impl swc_bundler::Resolve for Graph {
|
||||||
|
|
||||||
/// A structure for building a dependency graph of modules.
|
/// A structure for building a dependency graph of modules.
|
||||||
pub struct GraphBuilder {
|
pub struct GraphBuilder {
|
||||||
fetched: HashSet<ModuleSpecifier>,
|
|
||||||
graph: Graph,
|
graph: Graph,
|
||||||
maybe_import_map: Option<Rc<RefCell<ImportMap>>>,
|
maybe_import_map: Option<Rc<RefCell<ImportMap>>>,
|
||||||
pending: FuturesUnordered<FetchFuture>,
|
pending: FuturesUnordered<FetchFuture>,
|
||||||
|
@ -1529,7 +1664,6 @@ impl GraphBuilder {
|
||||||
};
|
};
|
||||||
GraphBuilder {
|
GraphBuilder {
|
||||||
graph: Graph::new(handler, maybe_lockfile),
|
graph: Graph::new(handler, maybe_lockfile),
|
||||||
fetched: HashSet::new(),
|
|
||||||
maybe_import_map: internal_import_map,
|
maybe_import_map: internal_import_map,
|
||||||
pending: FuturesUnordered::new(),
|
pending: FuturesUnordered::new(),
|
||||||
}
|
}
|
||||||
|
@ -1543,12 +1677,22 @@ impl GraphBuilder {
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
is_dynamic: bool,
|
is_dynamic: bool,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.fetch(specifier, &None, is_dynamic)?;
|
self.fetch(specifier, &None, is_dynamic);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let cached_module = self.pending.next().await.unwrap()?;
|
match self.pending.next().await {
|
||||||
let is_root = &cached_module.specifier == specifier;
|
Some(Err((specifier, err))) => {
|
||||||
self.visit(cached_module, is_root)?;
|
self
|
||||||
|
.graph
|
||||||
|
.modules
|
||||||
|
.insert(specifier, ModuleSlot::Err(Rc::new(err)));
|
||||||
|
}
|
||||||
|
Some(Ok(cached_module)) => {
|
||||||
|
let is_root = &cached_module.specifier == specifier;
|
||||||
|
self.visit(cached_module, is_root)?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
if self.pending.is_empty() {
|
if self.pending.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1573,20 +1717,19 @@ impl GraphBuilder {
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_referrer: &Option<Location>,
|
maybe_referrer: &Option<Location>,
|
||||||
is_dynamic: bool,
|
is_dynamic: bool,
|
||||||
) -> Result<(), AnyError> {
|
) {
|
||||||
if self.fetched.contains(&specifier) {
|
if !self.graph.modules.contains_key(&specifier) {
|
||||||
return Ok(());
|
self
|
||||||
|
.graph
|
||||||
|
.modules
|
||||||
|
.insert(specifier.clone(), ModuleSlot::Pending);
|
||||||
|
let future = self.graph.handler.borrow_mut().fetch(
|
||||||
|
specifier.clone(),
|
||||||
|
maybe_referrer.clone(),
|
||||||
|
is_dynamic,
|
||||||
|
);
|
||||||
|
self.pending.push(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fetched.insert(specifier.clone());
|
|
||||||
let future = self.graph.handler.borrow_mut().fetch(
|
|
||||||
specifier.clone(),
|
|
||||||
maybe_referrer.clone(),
|
|
||||||
is_dynamic,
|
|
||||||
);
|
|
||||||
self.pending.push(future);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit a module that has been fetched, hydrating the module, analyzing its
|
/// Visit a module that has been fetched, hydrating the module, analyzing its
|
||||||
|
@ -1632,14 +1775,14 @@ impl GraphBuilder {
|
||||||
for (_, dep) in module.dependencies.iter() {
|
for (_, dep) in module.dependencies.iter() {
|
||||||
let maybe_referrer = Some(dep.location.clone());
|
let maybe_referrer = Some(dep.location.clone());
|
||||||
if let Some(specifier) = dep.maybe_code.as_ref() {
|
if let Some(specifier) = dep.maybe_code.as_ref() {
|
||||||
self.fetch(specifier, &maybe_referrer, dep.is_dynamic)?;
|
self.fetch(specifier, &maybe_referrer, dep.is_dynamic);
|
||||||
}
|
}
|
||||||
if let Some(specifier) = dep.maybe_type.as_ref() {
|
if let Some(specifier) = dep.maybe_type.as_ref() {
|
||||||
self.fetch(specifier, &maybe_referrer, dep.is_dynamic)?;
|
self.fetch(specifier, &maybe_referrer, dep.is_dynamic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some((_, specifier)) = module.maybe_types.as_ref() {
|
if let Some((_, specifier)) = module.maybe_types.as_ref() {
|
||||||
self.fetch(specifier, &None, false)?;
|
self.fetch(specifier, &None, false);
|
||||||
}
|
}
|
||||||
if specifier != requested_specifier {
|
if specifier != requested_specifier {
|
||||||
self
|
self
|
||||||
|
@ -1647,7 +1790,10 @@ impl GraphBuilder {
|
||||||
.redirects
|
.redirects
|
||||||
.insert(requested_specifier, specifier.clone());
|
.insert(requested_specifier, specifier.clone());
|
||||||
}
|
}
|
||||||
self.graph.modules.insert(specifier, module);
|
self
|
||||||
|
.graph
|
||||||
|
.modules
|
||||||
|
.insert(specifier, ModuleSlot::Module(Box::new(module)));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1702,7 +1848,7 @@ pub mod tests {
|
||||||
fn get_cache(
|
fn get_cache(
|
||||||
&self,
|
&self,
|
||||||
specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
) -> Result<CachedModule, AnyError> {
|
) -> Result<CachedModule, (ModuleSpecifier, AnyError)> {
|
||||||
let specifier_text = specifier
|
let specifier_text = specifier
|
||||||
.to_string()
|
.to_string()
|
||||||
.replace(":///", "_")
|
.replace(":///", "_")
|
||||||
|
@ -1710,7 +1856,8 @@ pub mod tests {
|
||||||
.replace("/", "-");
|
.replace("/", "-");
|
||||||
let source_path = self.fixtures.join(specifier_text);
|
let source_path = self.fixtures.join(specifier_text);
|
||||||
let media_type = MediaType::from(&source_path);
|
let media_type = MediaType::from(&source_path);
|
||||||
let source = fs::read_to_string(&source_path)?;
|
let source = fs::read_to_string(&source_path)
|
||||||
|
.map_err(|err| (specifier.clone(), err.into()))?;
|
||||||
let is_remote = specifier.as_url().scheme() != "file";
|
let is_remote = specifier.as_url().scheme() != "file";
|
||||||
|
|
||||||
Ok(CachedModule {
|
Ok(CachedModule {
|
||||||
|
@ -2280,10 +2427,9 @@ pub mod tests {
|
||||||
ModuleSpecifier::resolve_url_or_path("file:///tests/main.ts")
|
ModuleSpecifier::resolve_url_or_path("file:///tests/main.ts")
|
||||||
.expect("could not resolve module");
|
.expect("could not resolve module");
|
||||||
let (mut graph, handler) = setup(specifier).await;
|
let (mut graph, handler) = setup(specifier).await;
|
||||||
let (stats, maybe_ignored_options) =
|
let result_info = graph.transpile(TranspileOptions::default()).unwrap();
|
||||||
graph.transpile(TranspileOptions::default()).unwrap();
|
assert_eq!(result_info.stats.0.len(), 3);
|
||||||
assert_eq!(stats.0.len(), 3);
|
assert_eq!(result_info.maybe_ignored_options, None);
|
||||||
assert_eq!(maybe_ignored_options, None);
|
|
||||||
let h = handler.borrow();
|
let h = handler.borrow();
|
||||||
assert_eq!(h.cache_calls.len(), 2);
|
assert_eq!(h.cache_calls.len(), 2);
|
||||||
match &h.cache_calls[0].1 {
|
match &h.cache_calls[0].1 {
|
||||||
|
@ -2334,7 +2480,7 @@ pub mod tests {
|
||||||
ModuleSpecifier::resolve_url_or_path("https://deno.land/x/transpile.tsx")
|
ModuleSpecifier::resolve_url_or_path("https://deno.land/x/transpile.tsx")
|
||||||
.expect("could not resolve module");
|
.expect("could not resolve module");
|
||||||
let (mut graph, handler) = setup(specifier).await;
|
let (mut graph, handler) = setup(specifier).await;
|
||||||
let (_, maybe_ignored_options) = graph
|
let result_info = graph
|
||||||
.transpile(TranspileOptions {
|
.transpile(TranspileOptions {
|
||||||
debug: false,
|
debug: false,
|
||||||
maybe_config_path: Some("tests/module_graph/tsconfig.json".to_string()),
|
maybe_config_path: Some("tests/module_graph/tsconfig.json".to_string()),
|
||||||
|
@ -2342,7 +2488,7 @@ pub mod tests {
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
maybe_ignored_options.unwrap().items,
|
result_info.maybe_ignored_options.unwrap().items,
|
||||||
vec!["target".to_string()],
|
vec!["target".to_string()],
|
||||||
"the 'target' options should have been ignored"
|
"the 'target' options should have been ignored"
|
||||||
);
|
);
|
||||||
|
|
|
@ -94,26 +94,14 @@ impl ModuleLoader for CliModuleLoader {
|
||||||
maybe_referrer: Option<ModuleSpecifier>,
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
_is_dynamic: bool,
|
_is_dynamic: bool,
|
||||||
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
) -> Pin<Box<deno_core::ModuleSourceFuture>> {
|
||||||
let module_specifier = module_specifier.to_owned();
|
let module_specifier = module_specifier.clone();
|
||||||
let module_url_specified = module_specifier.to_string();
|
|
||||||
let program_state = self.program_state.clone();
|
let program_state = self.program_state.clone();
|
||||||
|
|
||||||
// NOTE: this block is async only because of `deno_core`
|
// NOTE: this block is async only because of `deno_core`
|
||||||
// interface requirements; module was already loaded
|
// interface requirements; module was already loaded
|
||||||
// when constructing module graph during call to `prepare_load`.
|
// when constructing module graph during call to `prepare_load`.
|
||||||
let fut = async move {
|
async move { program_state.load(module_specifier, maybe_referrer) }
|
||||||
let compiled_module = program_state
|
.boxed_local()
|
||||||
.fetch_compiled_module(module_specifier, maybe_referrer)?;
|
|
||||||
Ok(deno_core::ModuleSource {
|
|
||||||
// Real module name, might be different from initial specifier
|
|
||||||
// due to redirections.
|
|
||||||
code: compiled_module.code,
|
|
||||||
module_url_specified,
|
|
||||||
module_url_found: compiled_module.name,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
fut.boxed_local()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_load(
|
fn prepare_load(
|
||||||
|
|
|
@ -8,7 +8,6 @@ use crate::http_cache;
|
||||||
use crate::http_util;
|
use crate::http_util;
|
||||||
use crate::import_map::ImportMap;
|
use crate::import_map::ImportMap;
|
||||||
use crate::lockfile::Lockfile;
|
use crate::lockfile::Lockfile;
|
||||||
use crate::media_type::MediaType;
|
|
||||||
use crate::module_graph::CheckOptions;
|
use crate::module_graph::CheckOptions;
|
||||||
use crate::module_graph::GraphBuilder;
|
use crate::module_graph::GraphBuilder;
|
||||||
use crate::module_graph::TranspileOptions;
|
use crate::module_graph::TranspileOptions;
|
||||||
|
@ -18,11 +17,14 @@ use crate::specifier_handler::FetchHandler;
|
||||||
use deno_runtime::inspector::InspectorServer;
|
use deno_runtime::inspector::InspectorServer;
|
||||||
use deno_runtime::permissions::Permissions;
|
use deno_runtime::permissions::Permissions;
|
||||||
|
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::anyhow;
|
||||||
|
use deno_core::error::get_custom_error_class;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use deno_core::ModuleSource;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -36,12 +38,6 @@ pub fn exit_unstable(api_name: &str) {
|
||||||
std::process::exit(70);
|
std::process::exit(70);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(@kitsonk) probably can refactor this better with the graph.
|
|
||||||
pub struct CompiledModule {
|
|
||||||
pub code: String,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This structure represents state of single "deno" program.
|
/// This structure represents state of single "deno" program.
|
||||||
///
|
///
|
||||||
/// It is shared by all created workers (thus V8 isolates).
|
/// It is shared by all created workers (thus V8 isolates).
|
||||||
|
@ -50,6 +46,8 @@ pub struct ProgramState {
|
||||||
pub flags: flags::Flags,
|
pub flags: flags::Flags,
|
||||||
pub dir: deno_dir::DenoDir,
|
pub dir: deno_dir::DenoDir,
|
||||||
pub file_fetcher: FileFetcher,
|
pub file_fetcher: FileFetcher,
|
||||||
|
pub modules:
|
||||||
|
Arc<Mutex<HashMap<ModuleSpecifier, Result<ModuleSource, AnyError>>>>,
|
||||||
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
pub maybe_import_map: Option<ImportMap>,
|
pub maybe_import_map: Option<ImportMap>,
|
||||||
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
|
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
|
@ -111,6 +109,7 @@ impl ProgramState {
|
||||||
dir,
|
dir,
|
||||||
flags,
|
flags,
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
|
modules: Default::default(),
|
||||||
lockfile,
|
lockfile,
|
||||||
maybe_import_map,
|
maybe_import_map,
|
||||||
maybe_inspector_server,
|
maybe_inspector_server,
|
||||||
|
@ -146,17 +145,17 @@ impl ProgramState {
|
||||||
let debug = self.flags.log_level == Some(log::Level::Debug);
|
let debug = self.flags.log_level == Some(log::Level::Debug);
|
||||||
let maybe_config_path = self.flags.config_path.clone();
|
let maybe_config_path = self.flags.config_path.clone();
|
||||||
|
|
||||||
if self.flags.no_check {
|
let result_modules = if self.flags.no_check {
|
||||||
let (stats, maybe_ignored_options) =
|
let result_info = graph.transpile(TranspileOptions {
|
||||||
graph.transpile(TranspileOptions {
|
debug,
|
||||||
debug,
|
maybe_config_path,
|
||||||
maybe_config_path,
|
reload: self.flags.reload,
|
||||||
reload: self.flags.reload,
|
})?;
|
||||||
})?;
|
debug!("{}", result_info.stats);
|
||||||
debug!("{}", stats);
|
if let Some(ignored_options) = result_info.maybe_ignored_options {
|
||||||
if let Some(ignored_options) = maybe_ignored_options {
|
warn!("{}", ignored_options);
|
||||||
eprintln!("{}", ignored_options);
|
|
||||||
}
|
}
|
||||||
|
result_info.loadable_modules
|
||||||
} else {
|
} else {
|
||||||
let result_info = graph.check(CheckOptions {
|
let result_info = graph.check(CheckOptions {
|
||||||
debug,
|
debug,
|
||||||
|
@ -171,10 +170,14 @@ impl ProgramState {
|
||||||
eprintln!("{}", ignored_options);
|
eprintln!("{}", ignored_options);
|
||||||
}
|
}
|
||||||
if !result_info.diagnostics.is_empty() {
|
if !result_info.diagnostics.is_empty() {
|
||||||
return Err(generic_error(result_info.diagnostics.to_string()));
|
return Err(anyhow!(result_info.diagnostics));
|
||||||
}
|
}
|
||||||
|
result_info.loadable_modules
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut loadable_modules = self.modules.lock().unwrap();
|
||||||
|
loadable_modules.extend(result_modules);
|
||||||
|
|
||||||
if let Some(ref lockfile) = self.lockfile {
|
if let Some(ref lockfile) = self.lockfile {
|
||||||
let g = lockfile.lock().unwrap();
|
let g = lockfile.lock().unwrap();
|
||||||
g.write()?;
|
g.write()?;
|
||||||
|
@ -183,56 +186,55 @@ impl ProgramState {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch_compiled_module(
|
pub fn load(
|
||||||
&self,
|
&self,
|
||||||
module_specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
maybe_referrer: Option<ModuleSpecifier>,
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
) -> Result<CompiledModule, AnyError> {
|
) -> Result<ModuleSource, AnyError> {
|
||||||
// TODO(@kitsonk) this really needs to be avoided and refactored out, as we
|
let modules = self.modules.lock().unwrap();
|
||||||
// really should just be getting this from the module graph.
|
modules
|
||||||
let out = self
|
.get(&specifier)
|
||||||
.file_fetcher
|
.map(|r| match r {
|
||||||
.get_source(&module_specifier)
|
Ok(module_source) => Ok(module_source.clone()),
|
||||||
.expect("Cached source file doesn't exist");
|
Err(err) => {
|
||||||
|
// TODO(@kitsonk) this feels a bit hacky but it works, without
|
||||||
let specifier = out.specifier.clone();
|
// introducing another enum to have to try to deal with.
|
||||||
let compiled_module = if let Some((code, _)) =
|
if get_custom_error_class(err) == Some("NotFound") {
|
||||||
self.get_emit(&specifier.as_url())
|
let message = if let Some(referrer) = &maybe_referrer {
|
||||||
{
|
format!("{}\n From: {}\n If the source module contains only types, use `import type` and `export type` to import it instead.", err, referrer)
|
||||||
CompiledModule {
|
} else {
|
||||||
code: String::from_utf8(code).unwrap(),
|
format!("{}\n If the source module contains only types, use `import type` and `export type` to import it instead.", err)
|
||||||
name: specifier.as_url().to_string(),
|
};
|
||||||
}
|
warn!("{}: {}", crate::colors::yellow("warning"), message);
|
||||||
// We expect a compiled source for any non-JavaScript files, except for
|
Ok(ModuleSource {
|
||||||
// local files that have an unknown media type and no referrer (root modules
|
code: "".to_string(),
|
||||||
// that do not have an extension.)
|
module_url_found: specifier.to_string(),
|
||||||
} else if out.media_type != MediaType::JavaScript
|
module_url_specified: specifier.to_string(),
|
||||||
&& !(out.media_type == MediaType::Unknown
|
})
|
||||||
&& maybe_referrer.is_none()
|
} else {
|
||||||
&& specifier.as_url().scheme() == "file")
|
// anyhow errors don't support cloning, so we have to manage this
|
||||||
{
|
// ourselves
|
||||||
let message = if let Some(referrer) = maybe_referrer {
|
Err(anyhow!(err.to_string()))
|
||||||
format!("Compiled module not found \"{}\"\n From: {}\n If the source module contains only types, use `import type` and `export type` to import it instead.", module_specifier, referrer)
|
}
|
||||||
} else {
|
},
|
||||||
format!("Compiled module not found \"{}\"\n If the source module contains only types, use `import type` and `export type` to import it instead.", module_specifier)
|
})
|
||||||
};
|
.unwrap_or_else(|| {
|
||||||
info!("{}: {}", crate::colors::yellow("warning"), message);
|
if let Some(referrer) = maybe_referrer {
|
||||||
CompiledModule {
|
Err(anyhow!(
|
||||||
code: "".to_string(),
|
"Module \"{}\" is missing from the graph.\n From: {}",
|
||||||
name: specifier.as_url().to_string(),
|
specifier,
|
||||||
}
|
referrer
|
||||||
} else {
|
))
|
||||||
CompiledModule {
|
} else {
|
||||||
code: out.source,
|
Err(anyhow!(
|
||||||
name: specifier.as_url().to_string(),
|
"Module \"{}\" is missing from the graph.",
|
||||||
}
|
specifier
|
||||||
};
|
))
|
||||||
|
}
|
||||||
Ok(compiled_module)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(@kitsonk) this should be a straight forward API on file_fetcher or
|
// TODO(@kitsonk) this should be refactored to get it from the module graph
|
||||||
// whatever future refactors do...
|
|
||||||
fn get_emit(&self, url: &Url) -> Option<(Vec<u8>, Option<Vec<u8>>)> {
|
fn get_emit(&self, url: &Url) -> Option<(Vec<u8>, Option<Vec<u8>>)> {
|
||||||
match url.scheme() {
|
match url.scheme() {
|
||||||
// we should only be looking for emits for schemes that denote external
|
// we should only be looking for emits for schemes that denote external
|
||||||
|
@ -245,11 +247,11 @@ impl ProgramState {
|
||||||
let emit_path = self
|
let emit_path = self
|
||||||
.dir
|
.dir
|
||||||
.gen_cache
|
.gen_cache
|
||||||
.get_cache_filename_with_extension(&url, "js");
|
.get_cache_filename_with_extension(&url, "js")?;
|
||||||
let emit_map_path = self
|
let emit_map_path = self
|
||||||
.dir
|
.dir
|
||||||
.gen_cache
|
.gen_cache
|
||||||
.get_cache_filename_with_extension(&url, "js.map");
|
.get_cache_filename_with_extension(&url, "js.map")?;
|
||||||
if let Ok(code) = self.dir.gen_cache.get(&emit_path) {
|
if let Ok(code) = self.dir.gen_cache.get(&emit_path) {
|
||||||
let maybe_map = if let Ok(map) = self.dir.gen_cache.get(&emit_map_path) {
|
let maybe_map = if let Ok(map) = self.dir.gen_cache.get(&emit_map_path) {
|
||||||
Some(map)
|
Some(map)
|
||||||
|
|
|
@ -25,8 +25,12 @@ use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub type DependencyMap = HashMap<String, Dependency>;
|
pub type DependencyMap = HashMap<String, Dependency>;
|
||||||
pub type FetchFuture =
|
pub type FetchFuture = Pin<
|
||||||
Pin<Box<(dyn Future<Output = Result<CachedModule, AnyError>> + 'static)>>;
|
Box<
|
||||||
|
(dyn Future<Output = Result<CachedModule, (ModuleSpecifier, AnyError)>>
|
||||||
|
+ 'static),
|
||||||
|
>,
|
||||||
|
>;
|
||||||
|
|
||||||
/// A group of errors that represent errors that can occur with an
|
/// A group of errors that represent errors that can occur with an
|
||||||
/// an implementation of `SpecifierHandler`.
|
/// an implementation of `SpecifierHandler`.
|
||||||
|
@ -287,23 +291,30 @@ impl SpecifierHandler for FetchHandler {
|
||||||
// they cannot actually get to the source code that is quoted, as
|
// they cannot actually get to the source code that is quoted, as
|
||||||
// it only exists in the runtime memory of Deno.
|
// it only exists in the runtime memory of Deno.
|
||||||
if !location.filename.contains("$deno$") {
|
if !location.filename.contains("$deno$") {
|
||||||
HandlerError::FetchErrorWithLocation(err.to_string(), location)
|
(
|
||||||
.into()
|
requested_specifier.clone(),
|
||||||
|
HandlerError::FetchErrorWithLocation(err.to_string(), location)
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
err
|
(requested_specifier.clone(), err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err
|
(requested_specifier.clone(), err)
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
let url = source_file.specifier.as_url();
|
let url = source_file.specifier.as_url();
|
||||||
let is_remote = url.scheme() != "file";
|
let is_remote = url.scheme() != "file";
|
||||||
let filename = disk_cache.get_cache_filename_with_extension(url, "meta");
|
let filename = disk_cache.get_cache_filename_with_extension(url, "meta");
|
||||||
let maybe_version = if let Ok(bytes) = disk_cache.get(&filename) {
|
let maybe_version = if let Some(filename) = filename {
|
||||||
if let Ok(compiled_file_metadata) =
|
if let Ok(bytes) = disk_cache.get(&filename) {
|
||||||
CompiledFileMetadata::from_bytes(&bytes)
|
if let Ok(compiled_file_metadata) =
|
||||||
{
|
CompiledFileMetadata::from_bytes(&bytes)
|
||||||
Some(compiled_file_metadata.version_hash)
|
{
|
||||||
|
Some(compiled_file_metadata.version_hash)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -314,19 +325,26 @@ impl SpecifierHandler for FetchHandler {
|
||||||
let mut maybe_map_path = None;
|
let mut maybe_map_path = None;
|
||||||
let map_path =
|
let map_path =
|
||||||
disk_cache.get_cache_filename_with_extension(&url, "js.map");
|
disk_cache.get_cache_filename_with_extension(&url, "js.map");
|
||||||
let maybe_map = if let Ok(map) = disk_cache.get(&map_path) {
|
let maybe_map = if let Some(map_path) = map_path {
|
||||||
maybe_map_path = Some(disk_cache.location.join(map_path));
|
if let Ok(map) = disk_cache.get(&map_path) {
|
||||||
Some(String::from_utf8(map)?)
|
maybe_map_path = Some(disk_cache.location.join(map_path));
|
||||||
|
Some(String::from_utf8(map).unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let mut maybe_emit = None;
|
let mut maybe_emit = None;
|
||||||
let mut maybe_emit_path = None;
|
let mut maybe_emit_path = None;
|
||||||
let emit_path = disk_cache.get_cache_filename_with_extension(&url, "js");
|
let emit_path = disk_cache.get_cache_filename_with_extension(&url, "js");
|
||||||
if let Ok(code) = disk_cache.get(&emit_path) {
|
if let Some(emit_path) = emit_path {
|
||||||
maybe_emit = Some(Emit::Cli((String::from_utf8(code)?, maybe_map)));
|
if let Ok(code) = disk_cache.get(&emit_path) {
|
||||||
maybe_emit_path =
|
maybe_emit =
|
||||||
Some((disk_cache.location.join(emit_path), maybe_map_path));
|
Some(Emit::Cli((String::from_utf8(code).unwrap(), maybe_map)));
|
||||||
|
maybe_emit_path =
|
||||||
|
Some((disk_cache.location.join(emit_path), maybe_map_path));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(CachedModule {
|
Ok(CachedModule {
|
||||||
|
@ -353,8 +371,12 @@ impl SpecifierHandler for FetchHandler {
|
||||||
let filename = self
|
let filename = self
|
||||||
.disk_cache
|
.disk_cache
|
||||||
.get_cache_filename_with_extension(specifier.as_url(), "buildinfo");
|
.get_cache_filename_with_extension(specifier.as_url(), "buildinfo");
|
||||||
if let Ok(tsbuildinfo) = self.disk_cache.get(&filename) {
|
if let Some(filename) = filename {
|
||||||
Ok(Some(String::from_utf8(tsbuildinfo)?))
|
if let Ok(tsbuildinfo) = self.disk_cache.get(&filename) {
|
||||||
|
Ok(Some(String::from_utf8(tsbuildinfo)?))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -367,7 +389,8 @@ impl SpecifierHandler for FetchHandler {
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let filename = self
|
let filename = self
|
||||||
.disk_cache
|
.disk_cache
|
||||||
.get_cache_filename_with_extension(specifier.as_url(), "buildinfo");
|
.get_cache_filename_with_extension(specifier.as_url(), "buildinfo")
|
||||||
|
.unwrap();
|
||||||
debug!("set_tsbuildinfo - filename {:?}", filename);
|
debug!("set_tsbuildinfo - filename {:?}", filename);
|
||||||
self
|
self
|
||||||
.disk_cache
|
.disk_cache
|
||||||
|
@ -383,14 +406,17 @@ impl SpecifierHandler for FetchHandler {
|
||||||
match emit {
|
match emit {
|
||||||
Emit::Cli((code, maybe_map)) => {
|
Emit::Cli((code, maybe_map)) => {
|
||||||
let url = specifier.as_url();
|
let url = specifier.as_url();
|
||||||
let filename =
|
let filename = self
|
||||||
self.disk_cache.get_cache_filename_with_extension(url, "js");
|
.disk_cache
|
||||||
|
.get_cache_filename_with_extension(url, "js")
|
||||||
|
.unwrap();
|
||||||
self.disk_cache.set(&filename, code.as_bytes())?;
|
self.disk_cache.set(&filename, code.as_bytes())?;
|
||||||
|
|
||||||
if let Some(map) = maybe_map {
|
if let Some(map) = maybe_map {
|
||||||
let filename = self
|
let filename = self
|
||||||
.disk_cache
|
.disk_cache
|
||||||
.get_cache_filename_with_extension(url, "js.map");
|
.get_cache_filename_with_extension(url, "js.map")
|
||||||
|
.unwrap();
|
||||||
self.disk_cache.set(&filename, map.as_bytes())?;
|
self.disk_cache.set(&filename, map.as_bytes())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,7 +451,8 @@ impl SpecifierHandler for FetchHandler {
|
||||||
let compiled_file_metadata = CompiledFileMetadata { version_hash };
|
let compiled_file_metadata = CompiledFileMetadata { version_hash };
|
||||||
let filename = self
|
let filename = self
|
||||||
.disk_cache
|
.disk_cache
|
||||||
.get_cache_filename_with_extension(specifier.as_url(), "meta");
|
.get_cache_filename_with_extension(specifier.as_url(), "meta")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self
|
self
|
||||||
.disk_cache
|
.disk_cache
|
||||||
|
@ -475,9 +502,12 @@ impl SpecifierHandler for MemoryHandler {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(custom_error(
|
Err((
|
||||||
"NotFound",
|
specifier.clone(),
|
||||||
format!("Unable to find specifier in sources: {}", specifier),
|
custom_error(
|
||||||
|
"NotFound",
|
||||||
|
format!("Unable to find specifier in sources: {}", specifier),
|
||||||
|
),
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
2
cli/tests/dynamic_import/b.js
Normal file
2
cli/tests/dynamic_import/b.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import "./bad.mjs";
|
||||||
|
export default () => "error";
|
2
cli/tests/dynamic_import/c.js
Normal file
2
cli/tests/dynamic_import/c.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
await import("./bad2.mjs");
|
||||||
|
export default () => "error";
|
|
@ -1,2 +1,4 @@
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
import * as badModule from "./bad-module.ts";
|
import * as badModule from "./bad-module.ts";
|
||||||
|
|
||||||
|
console.log(badModule);
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
error: Cannot resolve module "[WILDCARD]/bad-module.ts" from "[WILDCARD]/error_005_missing_dynamic_import.ts".
|
error: Uncaught (in promise) TypeError: Cannot resolve module "[WILDCARD]/cli/tests/bad-module.ts".
|
||||||
at file:///[WILDCARD]/error_005_missing_dynamic_import.ts:3:26
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
error: network access to "http://localhost:4545/cli/tests/subdir/mod4.js", run again with the --allow-net flag
|
error: Uncaught (in promise) TypeError: network access to "http://localhost:4545/cli/tests/subdir/mod4.js", run again with the --allow-net flag
|
||||||
at file:///[WILDCARD]cli/tests/error_015_dynamic_import_permissions.js:[WILDCARD]
|
|
||||||
|
|
7
cli/tests/fix_dynamic_import_errors.js
Normal file
7
cli/tests/fix_dynamic_import_errors.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import("./dynamic_import/b.js").catch(() => {
|
||||||
|
console.log("caught import error from b.js");
|
||||||
|
});
|
||||||
|
|
||||||
|
import("./dynamic_import/c.js").catch(() => {
|
||||||
|
console.log("caught import error from c.js");
|
||||||
|
});
|
2
cli/tests/fix_dynamic_import_errors.js.out
Normal file
2
cli/tests/fix_dynamic_import_errors.js.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
caught import error from [WILDCARD].js
|
||||||
|
caught import error from [WILDCARD].js
|
|
@ -3227,6 +3227,11 @@ itest!(tsx_imports {
|
||||||
output: "tsx_imports.ts.out",
|
output: "tsx_imports.ts.out",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(fix_dynamic_import_errors {
|
||||||
|
args: "run --reload fix_dynamic_import_errors.js",
|
||||||
|
output: "fix_dynamic_import_errors.js.out",
|
||||||
|
});
|
||||||
|
|
||||||
itest!(fix_emittable_skipped {
|
itest!(fix_emittable_skipped {
|
||||||
args: "run --reload fix_emittable_skipped.js",
|
args: "run --reload fix_emittable_skipped.js",
|
||||||
output: "fix_emittable_skipped.ts.out",
|
output: "fix_emittable_skipped.ts.out",
|
||||||
|
|
|
@ -2,5 +2,4 @@ Download http://localhost:4548/cli/tests/subdir/redirects/a.ts
|
||||||
Download http://localhost:4546/cli/tests/subdir/redirects/a.ts
|
Download http://localhost:4546/cli/tests/subdir/redirects/a.ts
|
||||||
Download http://localhost:4545/cli/tests/subdir/redirects/a.ts
|
Download http://localhost:4545/cli/tests/subdir/redirects/a.ts
|
||||||
Download http://localhost:4545/cli/tests/subdir/redirects/b.ts
|
Download http://localhost:4545/cli/tests/subdir/redirects/b.ts
|
||||||
Download http://localhost:4545/cli/tests/subdir/redirects/a.ts
|
|
||||||
Check http://localhost:4548/cli/tests/subdir/redirects/a.ts
|
Check http://localhost:4548/cli/tests/subdir/redirects/a.ts
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Unsupported scheme "xxx" for module "xxx:". Supported schemes: [
|
error: Uncaught (in promise) TypeError: Unsupported scheme "xxx" for module "xxx:". Supported schemes: [
|
||||||
"http",
|
"http",
|
||||||
"https",
|
"https",
|
||||||
"file",
|
"file",
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub type ModuleLoadId = i32;
|
||||||
// that happened; not only first and final target. It would simplify a lot
|
// that happened; not only first and final target. It would simplify a lot
|
||||||
// of things throughout the codebase otherwise we may end up requesting
|
// of things throughout the codebase otherwise we may end up requesting
|
||||||
// intermediate redirects from file loader.
|
// intermediate redirects from file loader.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct ModuleSource {
|
pub struct ModuleSource {
|
||||||
pub code: String,
|
pub code: String,
|
||||||
pub module_url_specified: String,
|
pub module_url_specified: String,
|
||||||
|
|
Loading…
Reference in a new issue