mirror of
https://github.com/denoland/deno.git
synced 2024-11-22 15:06:54 -05:00
f6caf4883d
This commit disabled flaky test in cli/module_graph.rs. The test uses 019_media_types.ts which was known to be flaky for some time. Test should be reenabled once test HTTP server is rewritten to Rust.
735 lines
22 KiB
Rust
735 lines
22 KiB
Rust
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
|
|
|
use crate::file_fetcher::SourceFile;
|
|
use crate::file_fetcher::SourceFileFetcher;
|
|
use crate::import_map::ImportMap;
|
|
use crate::msg::MediaType;
|
|
use crate::op_error::OpError;
|
|
use crate::permissions::Permissions;
|
|
use crate::swc_util::analyze_dependencies_and_references;
|
|
use crate::swc_util::TsReferenceKind;
|
|
use crate::tsc::get_available_libs;
|
|
use deno_core::ErrBox;
|
|
use deno_core::ModuleSpecifier;
|
|
use futures::stream::FuturesUnordered;
|
|
use futures::stream::StreamExt;
|
|
use futures::Future;
|
|
use futures::FutureExt;
|
|
use serde::Serialize;
|
|
use serde::Serializer;
|
|
use std::collections::HashMap;
|
|
use std::hash::BuildHasher;
|
|
use std::pin::Pin;
|
|
|
|
fn serialize_module_specifier<S>(
|
|
spec: &ModuleSpecifier,
|
|
s: S,
|
|
) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
s.serialize_str(&spec.to_string())
|
|
}
|
|
|
|
fn serialize_option_module_specifier<S>(
|
|
maybe_spec: &Option<ModuleSpecifier>,
|
|
s: S,
|
|
) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
if let Some(spec) = maybe_spec {
|
|
serialize_module_specifier(spec, s)
|
|
} else {
|
|
s.serialize_none()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct ModuleGraph(HashMap<String, ModuleGraphFile>);
|
|
|
|
#[derive(Debug, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ImportDescriptor {
|
|
specifier: String,
|
|
#[serde(serialize_with = "serialize_module_specifier")]
|
|
resolved_specifier: ModuleSpecifier,
|
|
// These two fields are for support of @deno-types directive
|
|
// directly prepending import statement
|
|
type_directive: Option<String>,
|
|
#[serde(serialize_with = "serialize_option_module_specifier")]
|
|
resolved_type_directive: Option<ModuleSpecifier>,
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ReferenceDescriptor {
|
|
specifier: String,
|
|
#[serde(serialize_with = "serialize_module_specifier")]
|
|
resolved_specifier: ModuleSpecifier,
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ModuleGraphFile {
|
|
pub specifier: String,
|
|
pub url: String,
|
|
pub filename: String,
|
|
pub imports: Vec<ImportDescriptor>,
|
|
pub referenced_files: Vec<ReferenceDescriptor>,
|
|
pub lib_directives: Vec<ReferenceDescriptor>,
|
|
pub types_directives: Vec<ReferenceDescriptor>,
|
|
pub type_headers: Vec<ReferenceDescriptor>,
|
|
pub media_type: i32,
|
|
pub source_code: String,
|
|
}
|
|
|
|
type SourceFileFuture =
|
|
Pin<Box<dyn Future<Output = Result<SourceFile, ErrBox>>>>;
|
|
|
|
pub struct ModuleGraphLoader {
|
|
permissions: Permissions,
|
|
file_fetcher: SourceFileFetcher,
|
|
maybe_import_map: Option<ImportMap>,
|
|
pending_downloads: FuturesUnordered<SourceFileFuture>,
|
|
pub graph: ModuleGraph,
|
|
is_dyn_import: bool,
|
|
analyze_dynamic_imports: bool,
|
|
}
|
|
|
|
impl ModuleGraphLoader {
|
|
pub fn new(
|
|
file_fetcher: SourceFileFetcher,
|
|
maybe_import_map: Option<ImportMap>,
|
|
permissions: Permissions,
|
|
is_dyn_import: bool,
|
|
analyze_dynamic_imports: bool,
|
|
) -> Self {
|
|
Self {
|
|
file_fetcher,
|
|
permissions,
|
|
maybe_import_map,
|
|
pending_downloads: FuturesUnordered::new(),
|
|
graph: ModuleGraph(HashMap::new()),
|
|
is_dyn_import,
|
|
analyze_dynamic_imports,
|
|
}
|
|
}
|
|
|
|
/// This method is used to add specified module and all of its
|
|
/// dependencies to the graph.
|
|
///
|
|
/// It resolves when all dependent modules have been fetched and analyzed.
|
|
///
|
|
/// This method can be called multiple times.
|
|
pub async fn add_to_graph(
|
|
&mut self,
|
|
specifier: &ModuleSpecifier,
|
|
) -> Result<(), ErrBox> {
|
|
self.download_module(specifier.clone(), None)?;
|
|
|
|
loop {
|
|
let source_file = self.pending_downloads.next().await.unwrap()?;
|
|
self.visit_module(&source_file.url.clone().into(), source_file)?;
|
|
if self.pending_downloads.is_empty() {
|
|
break;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// This method is used to create a graph from in-memory files stored in
|
|
/// a hash map. Useful for creating module graph for code received from
|
|
/// the runtime.
|
|
pub fn build_local_graph<S: BuildHasher>(
|
|
&mut self,
|
|
_root_name: &str,
|
|
source_map: &HashMap<String, String, S>,
|
|
) -> Result<(), ErrBox> {
|
|
for (spec, source_code) in source_map.iter() {
|
|
self.visit_memory_module(spec.to_string(), source_code.to_string())?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Consumes the loader and returns created graph.
|
|
pub fn get_graph(self) -> HashMap<String, ModuleGraphFile> {
|
|
self.graph.0
|
|
}
|
|
|
|
fn visit_memory_module(
|
|
&mut self,
|
|
specifier: String,
|
|
source_code: String,
|
|
) -> Result<(), ErrBox> {
|
|
let mut imports = vec![];
|
|
let mut referenced_files = vec![];
|
|
let mut lib_directives = vec![];
|
|
let mut types_directives = vec![];
|
|
|
|
// FIXME(bartlomieju):
|
|
// The resolveModules op only handles fully qualified URLs for referrer.
|
|
// However we will have cases where referrer is "/foo.ts". We add this dummy
|
|
// prefix "memory://" in order to use resolution logic.
|
|
let module_specifier =
|
|
if let Ok(spec) = ModuleSpecifier::resolve_url(&specifier) {
|
|
spec
|
|
} else {
|
|
ModuleSpecifier::resolve_url(&format!("memory://{}", specifier))?
|
|
};
|
|
|
|
let (import_descs, ref_descs) = analyze_dependencies_and_references(
|
|
&source_code,
|
|
self.analyze_dynamic_imports,
|
|
)?;
|
|
|
|
for import_desc in import_descs {
|
|
let maybe_resolved =
|
|
if let Some(import_map) = self.maybe_import_map.as_ref() {
|
|
import_map
|
|
.resolve(&import_desc.specifier, &module_specifier.to_string())?
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let resolved_specifier = if let Some(resolved) = maybe_resolved {
|
|
resolved
|
|
} else {
|
|
ModuleSpecifier::resolve_import(
|
|
&import_desc.specifier,
|
|
&module_specifier.to_string(),
|
|
)?
|
|
};
|
|
|
|
let resolved_type_directive =
|
|
if let Some(types_specifier) = import_desc.deno_types.as_ref() {
|
|
Some(ModuleSpecifier::resolve_import(
|
|
&types_specifier,
|
|
&module_specifier.to_string(),
|
|
)?)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let import_descriptor = ImportDescriptor {
|
|
specifier: import_desc.specifier.to_string(),
|
|
resolved_specifier,
|
|
type_directive: import_desc.deno_types,
|
|
resolved_type_directive,
|
|
};
|
|
|
|
imports.push(import_descriptor);
|
|
}
|
|
|
|
let available_libs = get_available_libs();
|
|
|
|
for ref_desc in ref_descs {
|
|
if available_libs.contains(&ref_desc.specifier) {
|
|
continue;
|
|
}
|
|
|
|
let resolved_specifier = ModuleSpecifier::resolve_import(
|
|
&ref_desc.specifier,
|
|
&module_specifier.to_string(),
|
|
)?;
|
|
|
|
let reference_descriptor = ReferenceDescriptor {
|
|
specifier: ref_desc.specifier.to_string(),
|
|
resolved_specifier,
|
|
};
|
|
|
|
match ref_desc.kind {
|
|
TsReferenceKind::Lib => {
|
|
lib_directives.push(reference_descriptor);
|
|
}
|
|
TsReferenceKind::Types => {
|
|
types_directives.push(reference_descriptor);
|
|
}
|
|
TsReferenceKind::Path => {
|
|
referenced_files.push(reference_descriptor);
|
|
}
|
|
}
|
|
}
|
|
|
|
self.graph.0.insert(
|
|
module_specifier.to_string(),
|
|
ModuleGraphFile {
|
|
specifier: specifier.to_string(),
|
|
url: specifier.to_string(),
|
|
filename: specifier,
|
|
// ignored, it's set in TS worker
|
|
media_type: MediaType::JavaScript as i32,
|
|
source_code,
|
|
imports,
|
|
referenced_files,
|
|
lib_directives,
|
|
types_directives,
|
|
type_headers: vec![],
|
|
},
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
fn download_module(
|
|
&mut self,
|
|
module_specifier: ModuleSpecifier,
|
|
maybe_referrer: Option<ModuleSpecifier>,
|
|
) -> Result<(), ErrBox> {
|
|
if self.graph.0.contains_key(&module_specifier.to_string()) {
|
|
return Ok(());
|
|
}
|
|
|
|
if !self.is_dyn_import {
|
|
// Verify that remote file doesn't try to statically import local file.
|
|
if let Some(referrer) = maybe_referrer.as_ref() {
|
|
let referrer_url = referrer.as_url();
|
|
match referrer_url.scheme() {
|
|
"http" | "https" => {
|
|
let specifier_url = module_specifier.as_url();
|
|
match specifier_url.scheme() {
|
|
"http" | "https" => {}
|
|
_ => {
|
|
let e = OpError::permission_denied("Remote module are not allowed to statically import local modules. Use dynamic import instead.".to_string());
|
|
return Err(e.into());
|
|
}
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
let spec = module_specifier;
|
|
let file_fetcher = self.file_fetcher.clone();
|
|
let perms = self.permissions.clone();
|
|
|
|
let load_future = async move {
|
|
let spec_ = spec.clone();
|
|
let source_file = file_fetcher
|
|
.fetch_source_file(&spec_, maybe_referrer, perms)
|
|
.await?;
|
|
// FIXME(bartlomieju):
|
|
// because of redirects we may end up with wrong URL,
|
|
// substitute with original one
|
|
Ok(SourceFile {
|
|
url: spec_.as_url().to_owned(),
|
|
..source_file
|
|
})
|
|
}
|
|
.boxed_local();
|
|
|
|
self.pending_downloads.push(load_future);
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_module(
|
|
&mut self,
|
|
module_specifier: &ModuleSpecifier,
|
|
source_file: SourceFile,
|
|
) -> Result<(), ErrBox> {
|
|
let mut imports = vec![];
|
|
let mut referenced_files = vec![];
|
|
let mut lib_directives = vec![];
|
|
let mut types_directives = vec![];
|
|
let mut type_headers = vec![];
|
|
|
|
let source_code = String::from_utf8(source_file.source_code)?;
|
|
|
|
if source_file.media_type == MediaType::JavaScript
|
|
|| source_file.media_type == MediaType::TypeScript
|
|
{
|
|
if let Some(types_specifier) = source_file.types_header {
|
|
let type_header = ReferenceDescriptor {
|
|
specifier: types_specifier.to_string(),
|
|
resolved_specifier: ModuleSpecifier::resolve_import(
|
|
&types_specifier,
|
|
&module_specifier.to_string(),
|
|
)?,
|
|
};
|
|
self.download_module(
|
|
type_header.resolved_specifier.clone(),
|
|
Some(module_specifier.clone()),
|
|
)?;
|
|
type_headers.push(type_header);
|
|
}
|
|
|
|
let (import_descs, ref_descs) = analyze_dependencies_and_references(
|
|
&source_code,
|
|
self.analyze_dynamic_imports,
|
|
)?;
|
|
|
|
for import_desc in import_descs {
|
|
let maybe_resolved =
|
|
if let Some(import_map) = self.maybe_import_map.as_ref() {
|
|
import_map
|
|
.resolve(&import_desc.specifier, &module_specifier.to_string())?
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let resolved_specifier = if let Some(resolved) = maybe_resolved {
|
|
resolved
|
|
} else {
|
|
ModuleSpecifier::resolve_import(
|
|
&import_desc.specifier,
|
|
&module_specifier.to_string(),
|
|
)?
|
|
};
|
|
|
|
let resolved_type_directive =
|
|
if let Some(types_specifier) = import_desc.deno_types.as_ref() {
|
|
Some(ModuleSpecifier::resolve_import(
|
|
&types_specifier,
|
|
&module_specifier.to_string(),
|
|
)?)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let import_descriptor = ImportDescriptor {
|
|
specifier: import_desc.specifier.to_string(),
|
|
resolved_specifier,
|
|
type_directive: import_desc.deno_types,
|
|
resolved_type_directive,
|
|
};
|
|
|
|
self.download_module(
|
|
import_descriptor.resolved_specifier.clone(),
|
|
Some(module_specifier.clone()),
|
|
)?;
|
|
|
|
if let Some(type_dir_url) =
|
|
import_descriptor.resolved_type_directive.as_ref()
|
|
{
|
|
self.download_module(
|
|
type_dir_url.clone(),
|
|
Some(module_specifier.clone()),
|
|
)?;
|
|
}
|
|
|
|
imports.push(import_descriptor);
|
|
}
|
|
|
|
let available_libs = get_available_libs();
|
|
|
|
for ref_desc in ref_descs {
|
|
if available_libs.contains(&ref_desc.specifier) {
|
|
continue;
|
|
}
|
|
|
|
let resolved_specifier = ModuleSpecifier::resolve_import(
|
|
&ref_desc.specifier,
|
|
&module_specifier.to_string(),
|
|
)?;
|
|
|
|
let reference_descriptor = ReferenceDescriptor {
|
|
specifier: ref_desc.specifier.to_string(),
|
|
resolved_specifier,
|
|
};
|
|
|
|
self.download_module(
|
|
reference_descriptor.resolved_specifier.clone(),
|
|
Some(module_specifier.clone()),
|
|
)?;
|
|
|
|
match ref_desc.kind {
|
|
TsReferenceKind::Lib => {
|
|
lib_directives.push(reference_descriptor);
|
|
}
|
|
TsReferenceKind::Types => {
|
|
types_directives.push(reference_descriptor);
|
|
}
|
|
TsReferenceKind::Path => {
|
|
referenced_files.push(reference_descriptor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self.graph.0.insert(
|
|
module_specifier.to_string(),
|
|
ModuleGraphFile {
|
|
specifier: module_specifier.to_string(),
|
|
url: source_file.url.to_string(),
|
|
filename: source_file.filename.to_str().unwrap().to_string(),
|
|
media_type: source_file.media_type as i32,
|
|
source_code,
|
|
imports,
|
|
referenced_files,
|
|
lib_directives,
|
|
types_directives,
|
|
type_headers,
|
|
},
|
|
);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::GlobalState;
|
|
|
|
async fn build_graph(
|
|
module_specifier: &ModuleSpecifier,
|
|
) -> Result<HashMap<String, ModuleGraphFile>, ErrBox> {
|
|
let global_state = GlobalState::new(Default::default()).unwrap();
|
|
let mut graph_loader = ModuleGraphLoader::new(
|
|
global_state.file_fetcher.clone(),
|
|
None,
|
|
Permissions::allow_all(),
|
|
false,
|
|
false,
|
|
);
|
|
graph_loader.add_to_graph(&module_specifier).await?;
|
|
Ok(graph_loader.get_graph())
|
|
}
|
|
|
|
// TODO(bartlomieju): this test is flaky, because it's using 019_media_types
|
|
// file, reenable once Python server is replaced with Rust one.
|
|
#[ignore]
|
|
#[tokio::test]
|
|
async fn source_graph_fetch() {
|
|
let http_server_guard = crate::test_util::http_server();
|
|
|
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(
|
|
"http://localhost:4545/cli/tests/019_media_types.ts",
|
|
)
|
|
.unwrap();
|
|
let graph = build_graph(&module_specifier)
|
|
.await
|
|
.expect("Failed to build graph");
|
|
|
|
let a = graph
|
|
.get("http://localhost:4545/cli/tests/019_media_types.ts")
|
|
.unwrap();
|
|
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/subdir/mt_text_ecmascript.j3.js"
|
|
));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/subdir/mt_video_vdn.t2.ts"
|
|
));
|
|
assert!(graph.contains_key("http://localhost:4545/cli/tests/subdir/mt_application_x_typescript.t4.ts"));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/subdir/mt_video_mp2t.t3.ts"
|
|
));
|
|
assert!(graph.contains_key("http://localhost:4545/cli/tests/subdir/mt_application_x_javascript.j4.js"));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/subdir/mt_application_ecmascript.j2.js"
|
|
));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/subdir/mt_text_javascript.j1.js"
|
|
));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/subdir/mt_text_typescript.t1.ts"
|
|
));
|
|
|
|
assert_eq!(
|
|
serde_json::to_value(&a.imports).unwrap(),
|
|
json!([
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_text_typescript.t1.ts",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_text_typescript.t1.ts",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_video_vdn.t2.ts",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_video_vdn.t2.ts",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_video_mp2t.t3.ts",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_video_mp2t.t3.ts",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_application_x_typescript.t4.ts",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_application_x_typescript.t4.ts",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_text_javascript.j1.js",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_text_javascript.j1.js",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_application_ecmascript.j2.js",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_application_ecmascript.j2.js",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_text_ecmascript.j3.js",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_text_ecmascript.j3.js",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
{
|
|
"specifier": "http://localhost:4545/cli/tests/subdir/mt_application_x_javascript.j4.js",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/mt_application_x_javascript.j4.js",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
])
|
|
);
|
|
drop(http_server_guard);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn source_graph_type_references() {
|
|
let http_server_guard = crate::test_util::http_server();
|
|
|
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(
|
|
"http://localhost:4545/cli/tests/type_definitions.ts",
|
|
)
|
|
.unwrap();
|
|
|
|
let graph = build_graph(&module_specifier)
|
|
.await
|
|
.expect("Failed to build graph");
|
|
|
|
eprintln!("json {:#?}", serde_json::to_value(&graph).unwrap());
|
|
|
|
let a = graph
|
|
.get("http://localhost:4545/cli/tests/type_definitions.ts")
|
|
.unwrap();
|
|
assert_eq!(
|
|
serde_json::to_value(&a.imports).unwrap(),
|
|
json!([
|
|
{
|
|
"specifier": "./type_definitions/foo.js",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/type_definitions/foo.js",
|
|
"typeDirective": "./type_definitions/foo.d.ts",
|
|
"resolvedTypeDirective": "http://localhost:4545/cli/tests/type_definitions/foo.d.ts"
|
|
},
|
|
{
|
|
"specifier": "./type_definitions/fizz.js",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/type_definitions/fizz.js",
|
|
"typeDirective": "./type_definitions/fizz.d.ts",
|
|
"resolvedTypeDirective": "http://localhost:4545/cli/tests/type_definitions/fizz.d.ts"
|
|
},
|
|
{
|
|
"specifier": "./type_definitions/qat.ts",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/type_definitions/qat.ts",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
},
|
|
])
|
|
);
|
|
assert!(graph
|
|
.contains_key("http://localhost:4545/cli/tests/type_definitions/foo.js"));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/type_definitions/foo.d.ts"
|
|
));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/type_definitions/fizz.js"
|
|
));
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/type_definitions/fizz.d.ts"
|
|
));
|
|
assert!(graph
|
|
.contains_key("http://localhost:4545/cli/tests/type_definitions/qat.ts"));
|
|
|
|
drop(http_server_guard);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn source_graph_type_references2() {
|
|
let http_server_guard = crate::test_util::http_server();
|
|
|
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(
|
|
"http://localhost:4545/cli/tests/type_directives_02.ts",
|
|
)
|
|
.unwrap();
|
|
|
|
let graph = build_graph(&module_specifier)
|
|
.await
|
|
.expect("Failed to build graph");
|
|
|
|
eprintln!("{:#?}", serde_json::to_value(&graph).unwrap());
|
|
|
|
let a = graph
|
|
.get("http://localhost:4545/cli/tests/type_directives_02.ts")
|
|
.unwrap();
|
|
assert_eq!(
|
|
serde_json::to_value(&a.imports).unwrap(),
|
|
json!([
|
|
{
|
|
"specifier": "./subdir/type_reference.js",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/type_reference.js",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
}
|
|
])
|
|
);
|
|
|
|
assert!(graph.contains_key(
|
|
"http://localhost:4545/cli/tests/subdir/type_reference.d.ts"
|
|
));
|
|
|
|
let b = graph
|
|
.get("http://localhost:4545/cli/tests/subdir/type_reference.js")
|
|
.unwrap();
|
|
assert_eq!(
|
|
serde_json::to_value(&b.types_directives).unwrap(),
|
|
json!([
|
|
{
|
|
"specifier": "./type_reference.d.ts",
|
|
"resolvedSpecifier": "http://localhost:4545/cli/tests/subdir/type_reference.d.ts",
|
|
}
|
|
])
|
|
);
|
|
drop(http_server_guard);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn source_graph_type_references3() {
|
|
let http_server_guard = crate::test_util::http_server();
|
|
|
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(
|
|
"http://localhost:4545/cli/tests/type_directives_01.ts",
|
|
)
|
|
.unwrap();
|
|
|
|
let graph = build_graph(&module_specifier)
|
|
.await
|
|
.expect("Failed to build graph");
|
|
|
|
let ts = graph
|
|
.get("http://localhost:4545/cli/tests/type_directives_01.ts")
|
|
.unwrap();
|
|
assert_eq!(
|
|
serde_json::to_value(&ts.imports).unwrap(),
|
|
json!([
|
|
{
|
|
"specifier": "http://127.0.0.1:4545/xTypeScriptTypes.js",
|
|
"resolvedSpecifier": "http://127.0.0.1:4545/xTypeScriptTypes.js",
|
|
"typeDirective": null,
|
|
"resolvedTypeDirective": null,
|
|
}
|
|
])
|
|
);
|
|
|
|
let headers = graph
|
|
.get("http://127.0.0.1:4545/xTypeScriptTypes.js")
|
|
.unwrap();
|
|
assert_eq!(
|
|
serde_json::to_value(&headers.type_headers).unwrap(),
|
|
json!([
|
|
{
|
|
"specifier": "./xTypeScriptTypes.d.ts",
|
|
"resolvedSpecifier": "http://127.0.0.1:4545/xTypeScriptTypes.d.ts"
|
|
}
|
|
])
|
|
);
|
|
drop(http_server_guard);
|
|
}
|
|
}
|