mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
feat(unstable/npm): initial type checking of npm specifiers (#16332)
This commit is contained in:
parent
0e1a71fec6
commit
bcfe279fba
64 changed files with 2135 additions and 280 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4752,6 +4752,7 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
|
"url",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -201,6 +201,11 @@ fn create_compiler_snapshot(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_is_node_file() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
fn op_script_version(
|
fn op_script_version(
|
||||||
_state: &mut OpState,
|
_state: &mut OpState,
|
||||||
|
@ -266,6 +271,7 @@ fn create_compiler_snapshot(
|
||||||
op_build_info::decl(),
|
op_build_info::decl(),
|
||||||
op_cwd::decl(),
|
op_cwd::decl(),
|
||||||
op_exists::decl(),
|
op_exists::decl(),
|
||||||
|
op_is_node_file::decl(),
|
||||||
op_load::decl(),
|
op_load::decl(),
|
||||||
op_script_version::decl(),
|
op_script_version::decl(),
|
||||||
])
|
])
|
||||||
|
|
18
cli/dts/README.md
vendored
18
cli/dts/README.md
vendored
|
@ -4,16 +4,26 @@ The files in this directory are mostly from the TypeScript repository. We
|
||||||
currently (unfortunately) have a rather manual process for upgrading TypeScript.
|
currently (unfortunately) have a rather manual process for upgrading TypeScript.
|
||||||
It works like this currently:
|
It works like this currently:
|
||||||
|
|
||||||
1. Checkout typescript repo in a separate directory.
|
1. Checkout denoland/TypeScript repo in a separate directory.
|
||||||
2. Copy typescript.js into Deno repo.
|
1. Add Microsoft/TypeScript as a remote and fetch its latest tags
|
||||||
3. Copy d.ts files into dts directory.
|
1. Checkout a new branch based on this tag.
|
||||||
|
1. Cherry pick the custom commit we made in a previous release to the new one.
|
||||||
|
1. This commit has a "deno.ts" file in it. Read the instructions in it.
|
||||||
|
1. Copy typescript.js into Deno repo.
|
||||||
|
1. Copy d.ts files into dts directory.
|
||||||
|
|
||||||
So that might look something like this:
|
So that might look something like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/microsoft/TypeScript.git
|
git clone https://github.com/denoland/TypeScript.git
|
||||||
cd typescript
|
cd typescript
|
||||||
|
git remote add upstream https://github.com/Microsoft/TypeScript
|
||||||
|
git fetch upstream
|
||||||
git checkout v3.9.7
|
git checkout v3.9.7
|
||||||
|
git checkout -b branch_v3.9.7
|
||||||
|
git cherry pick <previous-release-branch-commit-we-did>
|
||||||
|
npm install
|
||||||
|
gulp local
|
||||||
rsync lib/typescript.js ~/src/deno/cli/tsc/00_typescript.js
|
rsync lib/typescript.js ~/src/deno/cli/tsc/00_typescript.js
|
||||||
rsync --exclude=protocol.d.ts --exclude=tsserverlibrary.d.ts --exclude=typescriptServices.d.ts lib/*.d.ts ~/src/deno/cli/dts/
|
rsync --exclude=protocol.d.ts --exclude=tsserverlibrary.d.ts --exclude=typescriptServices.d.ts lib/*.d.ts ~/src/deno/cli/dts/
|
||||||
```
|
```
|
||||||
|
|
|
@ -458,6 +458,13 @@ async fn generate_lint_diagnostics(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore any npm package files
|
||||||
|
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
|
||||||
|
if npm_resolver.in_npm_package(document.specifier()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let version = document.maybe_lsp_version();
|
let version = document.maybe_lsp_version();
|
||||||
diagnostics_vec.push((
|
diagnostics_vec.push((
|
||||||
document.specifier().clone(),
|
document.specifier().clone(),
|
||||||
|
@ -597,6 +604,8 @@ pub enum DenoDiagnostic {
|
||||||
NoCacheBlob,
|
NoCacheBlob,
|
||||||
/// A data module was not found in the cache.
|
/// A data module was not found in the cache.
|
||||||
NoCacheData(ModuleSpecifier),
|
NoCacheData(ModuleSpecifier),
|
||||||
|
/// A remote npm package reference was not found in the cache.
|
||||||
|
NoCacheNpm(NpmPackageReference, ModuleSpecifier),
|
||||||
/// A local module was not found on the local file system.
|
/// A local module was not found on the local file system.
|
||||||
NoLocal(ModuleSpecifier),
|
NoLocal(ModuleSpecifier),
|
||||||
/// The specifier resolved to a remote specifier that was redirected to
|
/// The specifier resolved to a remote specifier that was redirected to
|
||||||
|
@ -622,6 +631,7 @@ impl DenoDiagnostic {
|
||||||
Self::NoCache(_) => "no-cache",
|
Self::NoCache(_) => "no-cache",
|
||||||
Self::NoCacheBlob => "no-cache-blob",
|
Self::NoCacheBlob => "no-cache-blob",
|
||||||
Self::NoCacheData(_) => "no-cache-data",
|
Self::NoCacheData(_) => "no-cache-data",
|
||||||
|
Self::NoCacheNpm(_, _) => "no-cache-npm",
|
||||||
Self::NoLocal(_) => "no-local",
|
Self::NoLocal(_) => "no-local",
|
||||||
Self::Redirect { .. } => "redirect",
|
Self::Redirect { .. } => "redirect",
|
||||||
Self::ResolutionError(err) => match err {
|
Self::ResolutionError(err) => match err {
|
||||||
|
@ -690,16 +700,17 @@ impl DenoDiagnostic {
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
"no-cache" | "no-cache-data" => {
|
"no-cache" | "no-cache-data" | "no-cache-npm" => {
|
||||||
let data = diagnostic
|
let data = diagnostic
|
||||||
.data
|
.data
|
||||||
.clone()
|
.clone()
|
||||||
.ok_or_else(|| anyhow!("Diagnostic is missing data"))?;
|
.ok_or_else(|| anyhow!("Diagnostic is missing data"))?;
|
||||||
let data: DiagnosticDataSpecifier = serde_json::from_value(data)?;
|
let data: DiagnosticDataSpecifier = serde_json::from_value(data)?;
|
||||||
let title = if code == "no-cache" {
|
let title = match code.as_str() {
|
||||||
format!("Cache \"{}\" and its dependencies.", data.specifier)
|
"no-cache" | "no-cache-npm" => {
|
||||||
} else {
|
format!("Cache \"{}\" and its dependencies.", data.specifier)
|
||||||
"Cache the data URL and its dependencies.".to_string()
|
}
|
||||||
|
_ => "Cache the data URL and its dependencies.".to_string(),
|
||||||
};
|
};
|
||||||
lsp::CodeAction {
|
lsp::CodeAction {
|
||||||
title,
|
title,
|
||||||
|
@ -757,6 +768,7 @@ impl DenoDiagnostic {
|
||||||
code.as_str(),
|
code.as_str(),
|
||||||
"import-map-remap"
|
"import-map-remap"
|
||||||
| "no-cache"
|
| "no-cache"
|
||||||
|
| "no-cache-npm"
|
||||||
| "no-cache-data"
|
| "no-cache-data"
|
||||||
| "no-assert-type"
|
| "no-assert-type"
|
||||||
| "redirect"
|
| "redirect"
|
||||||
|
@ -777,6 +789,7 @@ impl DenoDiagnostic {
|
||||||
Self::NoCache(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing remote URL: \"{}\".", specifier), Some(json!({ "specifier": specifier }))),
|
Self::NoCache(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing remote URL: \"{}\".", specifier), Some(json!({ "specifier": specifier }))),
|
||||||
Self::NoCacheBlob => (lsp::DiagnosticSeverity::ERROR, "Uncached blob URL.".to_string(), None),
|
Self::NoCacheBlob => (lsp::DiagnosticSeverity::ERROR, "Uncached blob URL.".to_string(), None),
|
||||||
Self::NoCacheData(specifier) => (lsp::DiagnosticSeverity::ERROR, "Uncached data URL.".to_string(), Some(json!({ "specifier": specifier }))),
|
Self::NoCacheData(specifier) => (lsp::DiagnosticSeverity::ERROR, "Uncached data URL.".to_string(), Some(json!({ "specifier": specifier }))),
|
||||||
|
Self::NoCacheNpm(pkg_ref, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing npm package: \"{}\".", pkg_ref.req), Some(json!({ "specifier": specifier }))),
|
||||||
Self::NoLocal(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Unable to load a local module: \"{}\".\n Please check the file path.", specifier), None),
|
Self::NoLocal(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Unable to load a local module: \"{}\".\n Please check the file path.", specifier), None),
|
||||||
Self::Redirect { from, to} => (lsp::DiagnosticSeverity::INFORMATION, format!("The import of \"{}\" was redirected to \"{}\".", from, to), Some(json!({ "specifier": from, "redirect": to }))),
|
Self::Redirect { from, to} => (lsp::DiagnosticSeverity::INFORMATION, format!("The import of \"{}\" was redirected to \"{}\".", from, to), Some(json!({ "specifier": from, "redirect": to }))),
|
||||||
Self::ResolutionError(err) => (lsp::DiagnosticSeverity::ERROR, err.to_string(), None),
|
Self::ResolutionError(err) => (lsp::DiagnosticSeverity::ERROR, err.to_string(), None),
|
||||||
|
@ -847,8 +860,20 @@ fn diagnose_resolved(
|
||||||
.push(DenoDiagnostic::NoAssertType.to_lsp_diagnostic(&range)),
|
.push(DenoDiagnostic::NoAssertType.to_lsp_diagnostic(&range)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if NpmPackageReference::from_specifier(specifier).is_ok() {
|
} else if let Ok(pkg_ref) = NpmPackageReference::from_specifier(specifier)
|
||||||
// ignore npm specifiers for now
|
{
|
||||||
|
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
|
||||||
|
// show diagnostics for npm package references that aren't cached
|
||||||
|
if npm_resolver
|
||||||
|
.resolve_package_folder_from_deno_module(&pkg_ref.req)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
diagnostics.push(
|
||||||
|
DenoDiagnostic::NoCacheNpm(pkg_ref, specifier.clone())
|
||||||
|
.to_lsp_diagnostic(&range),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// When the document is not available, it means that it cannot be found
|
// When the document is not available, it means that it cannot be found
|
||||||
// in the cache or locally on the disk, so we want to issue a diagnostic
|
// in the cache or locally on the disk, so we want to issue a diagnostic
|
||||||
|
@ -882,6 +907,12 @@ fn diagnose_dependency(
|
||||||
dependency_key: &str,
|
dependency_key: &str,
|
||||||
dependency: &deno_graph::Dependency,
|
dependency: &deno_graph::Dependency,
|
||||||
) {
|
) {
|
||||||
|
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
|
||||||
|
if npm_resolver.in_npm_package(referrer) {
|
||||||
|
return; // ignore, surface typescript errors instead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(import_map) = &snapshot.maybe_import_map {
|
if let Some(import_map) = &snapshot.maybe_import_map {
|
||||||
if let Resolved::Ok {
|
if let Resolved::Ok {
|
||||||
specifier, range, ..
|
specifier, range, ..
|
||||||
|
@ -938,8 +969,8 @@ async fn generate_deno_diagnostics(
|
||||||
&mut diagnostics,
|
&mut diagnostics,
|
||||||
snapshot,
|
snapshot,
|
||||||
specifier,
|
specifier,
|
||||||
&dependency_key,
|
dependency_key,
|
||||||
&dependency,
|
dependency,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,13 @@ use crate::file_fetcher::SUPPORTED_SCHEMES;
|
||||||
use crate::fs_util::specifier_to_file_path;
|
use crate::fs_util::specifier_to_file_path;
|
||||||
use crate::http_cache;
|
use crate::http_cache;
|
||||||
use crate::http_cache::HttpCache;
|
use crate::http_cache::HttpCache;
|
||||||
|
use crate::node;
|
||||||
|
use crate::node::node_resolve_npm_reference;
|
||||||
|
use crate::node::NodeResolution;
|
||||||
|
use crate::node::NodeResolutionMode;
|
||||||
|
use crate::npm::NpmPackageReference;
|
||||||
|
use crate::npm::NpmPackageReq;
|
||||||
|
use crate::npm::NpmPackageResolver;
|
||||||
use crate::resolver::ImportMapResolver;
|
use crate::resolver::ImportMapResolver;
|
||||||
use crate::resolver::JsxResolver;
|
use crate::resolver::JsxResolver;
|
||||||
use crate::text_encoding;
|
use crate::text_encoding;
|
||||||
|
@ -209,6 +216,29 @@ impl AssetOrDocument {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct DocumentDependencies {
|
||||||
|
deps: BTreeMap<String, deno_graph::Dependency>,
|
||||||
|
maybe_types_dependency: Option<(String, Resolved)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocumentDependencies {
|
||||||
|
pub fn from_maybe_module(maybe_module: &MaybeModuleResult) -> Self {
|
||||||
|
if let Some(Ok(module)) = &maybe_module {
|
||||||
|
Self::from_module(module)
|
||||||
|
} else {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_module(module: &deno_graph::Module) -> Self {
|
||||||
|
Self {
|
||||||
|
deps: module.dependencies.clone(),
|
||||||
|
maybe_types_dependency: module.maybe_types_dependency.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type MaybeModuleResult =
|
type MaybeModuleResult =
|
||||||
Option<Result<deno_graph::Module, deno_graph::ModuleGraphError>>;
|
Option<Result<deno_graph::Module, deno_graph::ModuleGraphError>>;
|
||||||
type MaybeParsedSourceResult =
|
type MaybeParsedSourceResult =
|
||||||
|
@ -217,7 +247,7 @@ type MaybeParsedSourceResult =
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct DocumentInner {
|
struct DocumentInner {
|
||||||
/// contains the last-known-good set of dependencies from parsing the module
|
/// contains the last-known-good set of dependencies from parsing the module
|
||||||
dependencies: Arc<BTreeMap<String, deno_graph::Dependency>>,
|
dependencies: Arc<DocumentDependencies>,
|
||||||
fs_version: String,
|
fs_version: String,
|
||||||
line_index: Arc<LineIndex>,
|
line_index: Arc<LineIndex>,
|
||||||
maybe_language_id: Option<LanguageId>,
|
maybe_language_id: Option<LanguageId>,
|
||||||
|
@ -249,12 +279,9 @@ impl Document {
|
||||||
maybe_headers,
|
maybe_headers,
|
||||||
maybe_resolver,
|
maybe_resolver,
|
||||||
);
|
);
|
||||||
let dependencies = if let Some(Ok(module)) = &maybe_module {
|
let dependencies =
|
||||||
Arc::new(module.dependencies.clone())
|
Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
|
||||||
} else {
|
// todo(dsherret): retrieve this from the parsed source if it exists
|
||||||
Arc::new(BTreeMap::new())
|
|
||||||
};
|
|
||||||
// todo(dsherret): retrieve this from the parsed source if it
|
|
||||||
let text_info = SourceTextInfo::new(content);
|
let text_info = SourceTextInfo::new(content);
|
||||||
let line_index = Arc::new(LineIndex::new(text_info.text_str()));
|
let line_index = Arc::new(LineIndex::new(text_info.text_str()));
|
||||||
Self(Arc::new(DocumentInner {
|
Self(Arc::new(DocumentInner {
|
||||||
|
@ -289,11 +316,8 @@ impl Document {
|
||||||
} else {
|
} else {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
let dependencies = if let Some(Ok(module)) = &maybe_module {
|
let dependencies =
|
||||||
Arc::new(module.dependencies.clone())
|
Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
|
||||||
} else {
|
|
||||||
Arc::new(BTreeMap::new())
|
|
||||||
};
|
|
||||||
let source = SourceTextInfo::new(content);
|
let source = SourceTextInfo::new(content);
|
||||||
let line_index = Arc::new(LineIndex::new(source.text_str()));
|
let line_index = Arc::new(LineIndex::new(source.text_str()));
|
||||||
Self(Arc::new(DocumentInner {
|
Self(Arc::new(DocumentInner {
|
||||||
|
@ -355,9 +379,9 @@ impl Document {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
let dependencies = if let Some(Ok(module)) = &maybe_module {
|
let dependencies = if let Some(Ok(module)) = &maybe_module {
|
||||||
Arc::new(module.dependencies.clone())
|
Arc::new(DocumentDependencies::from_module(module))
|
||||||
} else {
|
} else {
|
||||||
self.0.dependencies.clone()
|
self.0.dependencies.clone() // use the last known good
|
||||||
};
|
};
|
||||||
let text_info = SourceTextInfo::new(content);
|
let text_info = SourceTextInfo::new(content);
|
||||||
let line_index = if index_valid == IndexValid::All {
|
let line_index = if index_valid == IndexValid::All {
|
||||||
|
@ -435,15 +459,9 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_types_dependency(&self) -> deno_graph::Resolved {
|
pub fn maybe_types_dependency(&self) -> deno_graph::Resolved {
|
||||||
let module_result = match self.0.maybe_module.as_ref() {
|
if let Some((_, maybe_dep)) =
|
||||||
Some(module_result) => module_result,
|
self.0.dependencies.maybe_types_dependency.as_ref()
|
||||||
_ => return deno_graph::Resolved::None,
|
{
|
||||||
};
|
|
||||||
let module = match module_result.as_ref() {
|
|
||||||
Ok(module) => module,
|
|
||||||
Err(_) => return deno_graph::Resolved::None,
|
|
||||||
};
|
|
||||||
if let Some((_, maybe_dep)) = module.maybe_types_dependency.as_ref() {
|
|
||||||
maybe_dep.clone()
|
maybe_dep.clone()
|
||||||
} else {
|
} else {
|
||||||
deno_graph::Resolved::None
|
deno_graph::Resolved::None
|
||||||
|
@ -479,13 +497,8 @@ impl Document {
|
||||||
self.0.maybe_navigation_tree.clone()
|
self.0.maybe_navigation_tree.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dependencies(&self) -> Vec<(String, deno_graph::Dependency)> {
|
pub fn dependencies(&self) -> &BTreeMap<String, deno_graph::Dependency> {
|
||||||
self
|
&self.0.dependencies.deps
|
||||||
.0
|
|
||||||
.dependencies
|
|
||||||
.iter()
|
|
||||||
.map(|(s, d)| (s.clone(), d.clone()))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the supplied position is within a dependency range, return the resolved
|
/// If the supplied position is within a dependency range, return the resolved
|
||||||
|
@ -698,6 +711,8 @@ pub struct Documents {
|
||||||
maybe_import_map: Option<ImportMapResolver>,
|
maybe_import_map: Option<ImportMapResolver>,
|
||||||
/// The optional JSX resolver, which is used when JSX imports are configured.
|
/// The optional JSX resolver, which is used when JSX imports are configured.
|
||||||
maybe_jsx_resolver: Option<JsxResolver>,
|
maybe_jsx_resolver: Option<JsxResolver>,
|
||||||
|
/// The npm package requirements.
|
||||||
|
npm_reqs: HashSet<NpmPackageReq>,
|
||||||
/// Resolves a specifier to its final redirected to specifier.
|
/// Resolves a specifier to its final redirected to specifier.
|
||||||
specifier_resolver: Arc<SpecifierResolver>,
|
specifier_resolver: Arc<SpecifierResolver>,
|
||||||
}
|
}
|
||||||
|
@ -713,6 +728,7 @@ impl Documents {
|
||||||
imports: Default::default(),
|
imports: Default::default(),
|
||||||
maybe_import_map: None,
|
maybe_import_map: None,
|
||||||
maybe_jsx_resolver: None,
|
maybe_jsx_resolver: None,
|
||||||
|
npm_reqs: HashSet::new(),
|
||||||
specifier_resolver: Arc::new(SpecifierResolver::new(location)),
|
specifier_resolver: Arc::new(SpecifierResolver::new(location)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -847,6 +863,12 @@ impl Documents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a collection of npm package requirements.
|
||||||
|
pub fn npm_package_reqs(&mut self) -> HashSet<NpmPackageReq> {
|
||||||
|
self.calculate_dependents_if_dirty();
|
||||||
|
self.npm_reqs.clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// Return a document for the specifier.
|
/// Return a document for the specifier.
|
||||||
pub fn get(&self, original_specifier: &ModuleSpecifier) -> Option<Document> {
|
pub fn get(&self, original_specifier: &ModuleSpecifier) -> Option<Document> {
|
||||||
let specifier = self.specifier_resolver.resolve(original_specifier)?;
|
let specifier = self.specifier_resolver.resolve(original_specifier)?;
|
||||||
|
@ -921,10 +943,28 @@ impl Documents {
|
||||||
&self,
|
&self,
|
||||||
specifiers: Vec<String>,
|
specifiers: Vec<String>,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
maybe_npm_resolver: Option<&NpmPackageResolver>,
|
||||||
) -> Option<Vec<Option<(ModuleSpecifier, MediaType)>>> {
|
) -> Option<Vec<Option<(ModuleSpecifier, MediaType)>>> {
|
||||||
let dependencies = self.get(referrer)?.0.dependencies.clone();
|
let dependencies = self.get(referrer)?.0.dependencies.clone();
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
for specifier in specifiers {
|
for specifier in specifiers {
|
||||||
|
if let Some(npm_resolver) = maybe_npm_resolver {
|
||||||
|
if npm_resolver.in_npm_package(referrer) {
|
||||||
|
// we're in an npm package, so use node resolution
|
||||||
|
results.push(Some(NodeResolution::into_specifier_and_media_type(
|
||||||
|
node::node_resolve(
|
||||||
|
&specifier,
|
||||||
|
referrer,
|
||||||
|
node::NodeResolutionMode::Types,
|
||||||
|
npm_resolver,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.flatten(),
|
||||||
|
)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle npm:<package> urls
|
||||||
if specifier.starts_with("asset:") {
|
if specifier.starts_with("asset:") {
|
||||||
if let Ok(specifier) = ModuleSpecifier::parse(&specifier) {
|
if let Ok(specifier) = ModuleSpecifier::parse(&specifier) {
|
||||||
let media_type = MediaType::from(&specifier);
|
let media_type = MediaType::from(&specifier);
|
||||||
|
@ -932,11 +972,11 @@ impl Documents {
|
||||||
} else {
|
} else {
|
||||||
results.push(None);
|
results.push(None);
|
||||||
}
|
}
|
||||||
} else if let Some(dep) = dependencies.get(&specifier) {
|
} else if let Some(dep) = dependencies.deps.get(&specifier) {
|
||||||
if let Resolved::Ok { specifier, .. } = &dep.maybe_type {
|
if let Resolved::Ok { specifier, .. } = &dep.maybe_type {
|
||||||
results.push(self.resolve_dependency(specifier));
|
results.push(self.resolve_dependency(specifier, maybe_npm_resolver));
|
||||||
} else if let Resolved::Ok { specifier, .. } = &dep.maybe_code {
|
} else if let Resolved::Ok { specifier, .. } = &dep.maybe_code {
|
||||||
results.push(self.resolve_dependency(specifier));
|
results.push(self.resolve_dependency(specifier, maybe_npm_resolver));
|
||||||
} else {
|
} else {
|
||||||
results.push(None);
|
results.push(None);
|
||||||
}
|
}
|
||||||
|
@ -945,7 +985,19 @@ impl Documents {
|
||||||
{
|
{
|
||||||
// clone here to avoid double borrow of self
|
// clone here to avoid double borrow of self
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
results.push(self.resolve_dependency(&specifier));
|
results.push(self.resolve_dependency(&specifier, maybe_npm_resolver));
|
||||||
|
} else if let Ok(npm_ref) = NpmPackageReference::from_str(&specifier) {
|
||||||
|
results.push(maybe_npm_resolver.map(|npm_resolver| {
|
||||||
|
NodeResolution::into_specifier_and_media_type(
|
||||||
|
node_resolve_npm_reference(
|
||||||
|
&npm_ref,
|
||||||
|
NodeResolutionMode::Types,
|
||||||
|
npm_resolver,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
results.push(None);
|
results.push(None);
|
||||||
}
|
}
|
||||||
|
@ -1038,32 +1090,36 @@ impl Documents {
|
||||||
// favour documents that are open in case a document exists in both collections
|
// favour documents that are open in case a document exists in both collections
|
||||||
let documents = file_system_docs.docs.iter().chain(self.open_docs.iter());
|
let documents = file_system_docs.docs.iter().chain(self.open_docs.iter());
|
||||||
for (specifier, doc) in documents {
|
for (specifier, doc) in documents {
|
||||||
if let Some(Ok(module)) = doc.maybe_module() {
|
for dependency in doc.dependencies().values() {
|
||||||
for dependency in module.dependencies.values() {
|
if let Some(dep) = dependency.get_code() {
|
||||||
if let Some(dep) = dependency.get_code() {
|
dependents_map
|
||||||
dependents_map
|
.entry(dep.clone())
|
||||||
.entry(dep.clone())
|
.or_default()
|
||||||
.or_default()
|
.insert(specifier.clone());
|
||||||
.insert(specifier.clone());
|
|
||||||
}
|
|
||||||
if let Some(dep) = dependency.get_type() {
|
|
||||||
dependents_map
|
|
||||||
.entry(dep.clone())
|
|
||||||
.or_default()
|
|
||||||
.insert(specifier.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Some((_, Resolved::Ok { specifier: dep, .. })) =
|
if let Some(dep) = dependency.get_type() {
|
||||||
&module.maybe_types_dependency
|
|
||||||
{
|
|
||||||
dependents_map
|
dependents_map
|
||||||
.entry(dep.clone())
|
.entry(dep.clone())
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(specifier.clone());
|
.insert(specifier.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Resolved::Ok { specifier: dep, .. } = doc.maybe_types_dependency()
|
||||||
|
{
|
||||||
|
dependents_map
|
||||||
|
.entry(dep.clone())
|
||||||
|
.or_default()
|
||||||
|
.insert(specifier.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut npm_reqs = HashSet::new();
|
||||||
|
for specifier in dependents_map.keys() {
|
||||||
|
if let Ok(reference) = NpmPackageReference::from_specifier(specifier) {
|
||||||
|
npm_reqs.insert(reference.req);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.dependents_map = Arc::new(dependents_map);
|
self.dependents_map = Arc::new(dependents_map);
|
||||||
|
self.npm_reqs = npm_reqs;
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
file_system_docs.dirty = false;
|
file_system_docs.dirty = false;
|
||||||
}
|
}
|
||||||
|
@ -1079,7 +1135,21 @@ impl Documents {
|
||||||
fn resolve_dependency(
|
fn resolve_dependency(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
maybe_npm_resolver: Option<&NpmPackageResolver>,
|
||||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||||
|
if let Ok(npm_ref) = NpmPackageReference::from_specifier(specifier) {
|
||||||
|
return maybe_npm_resolver.map(|npm_resolver| {
|
||||||
|
NodeResolution::into_specifier_and_media_type(
|
||||||
|
node_resolve_npm_reference(
|
||||||
|
&npm_ref,
|
||||||
|
NodeResolutionMode::Types,
|
||||||
|
npm_resolver,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
let doc = self.get(specifier)?;
|
let doc = self.get(specifier)?;
|
||||||
let maybe_module = doc.maybe_module().and_then(|r| r.as_ref().ok());
|
let maybe_module = doc.maybe_module().and_then(|r| r.as_ref().ok());
|
||||||
let maybe_types_dependency = maybe_module.and_then(|m| {
|
let maybe_types_dependency = maybe_module.and_then(|m| {
|
||||||
|
@ -1088,7 +1158,7 @@ impl Documents {
|
||||||
.map(|(_, resolved)| resolved.clone())
|
.map(|(_, resolved)| resolved.clone())
|
||||||
});
|
});
|
||||||
if let Some(Resolved::Ok { specifier, .. }) = maybe_types_dependency {
|
if let Some(Resolved::Ok { specifier, .. }) = maybe_types_dependency {
|
||||||
self.resolve_dependency(&specifier)
|
self.resolve_dependency(&specifier, maybe_npm_resolver)
|
||||||
} else {
|
} else {
|
||||||
let media_type = doc.media_type();
|
let media_type = doc.media_type();
|
||||||
Some((specifier.clone(), media_type))
|
Some((specifier.clone(), media_type))
|
||||||
|
@ -1113,12 +1183,12 @@ impl Documents {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loader that will look at the open documents.
|
/// Loader that will look at the open documents.
|
||||||
pub struct DocumentsDenoGraphLoader<'a> {
|
pub struct OpenDocumentsGraphLoader<'a> {
|
||||||
pub inner_loader: &'a mut dyn deno_graph::source::Loader,
|
pub inner_loader: &'a mut dyn deno_graph::source::Loader,
|
||||||
pub open_docs: &'a HashMap<ModuleSpecifier, Document>,
|
pub open_docs: &'a HashMap<ModuleSpecifier, Document>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> deno_graph::source::Loader for DocumentsDenoGraphLoader<'a> {
|
impl<'a> deno_graph::source::Loader for OpenDocumentsGraphLoader<'a> {
|
||||||
fn load(
|
fn load(
|
||||||
&mut self,
|
&mut self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
|
|
@ -66,10 +66,15 @@ use crate::args::LintConfig;
|
||||||
use crate::args::TsConfig;
|
use crate::args::TsConfig;
|
||||||
use crate::deno_dir;
|
use crate::deno_dir;
|
||||||
use crate::file_fetcher::get_source_from_data_url;
|
use crate::file_fetcher::get_source_from_data_url;
|
||||||
|
use crate::file_fetcher::CacheSetting;
|
||||||
use crate::fs_util;
|
use crate::fs_util;
|
||||||
use crate::graph_util::graph_valid;
|
use crate::graph_util::graph_valid;
|
||||||
|
use crate::npm::NpmCache;
|
||||||
|
use crate::npm::NpmPackageResolver;
|
||||||
|
use crate::npm::NpmRegistryApi;
|
||||||
use crate::proc_state::import_map_from_text;
|
use crate::proc_state::import_map_from_text;
|
||||||
use crate::proc_state::ProcState;
|
use crate::proc_state::ProcState;
|
||||||
|
use crate::progress_bar::ProgressBar;
|
||||||
use crate::tools::fmt::format_file;
|
use crate::tools::fmt::format_file;
|
||||||
use crate::tools::fmt::format_parsed_source;
|
use crate::tools::fmt::format_parsed_source;
|
||||||
|
|
||||||
|
@ -87,6 +92,7 @@ pub struct StateSnapshot {
|
||||||
pub documents: Documents,
|
pub documents: Documents,
|
||||||
pub maybe_import_map: Option<Arc<ImportMap>>,
|
pub maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
pub root_uri: Option<Url>,
|
pub root_uri: Option<Url>,
|
||||||
|
pub maybe_npm_resolver: Option<NpmPackageResolver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -125,6 +131,8 @@ pub struct Inner {
|
||||||
pub maybe_lint_config: Option<LintConfig>,
|
pub maybe_lint_config: Option<LintConfig>,
|
||||||
/// A lazily create "server" for handling test run requests.
|
/// A lazily create "server" for handling test run requests.
|
||||||
maybe_testing_server: Option<testing::TestServer>,
|
maybe_testing_server: Option<testing::TestServer>,
|
||||||
|
/// Resolver for npm packages.
|
||||||
|
npm_resolver: NpmPackageResolver,
|
||||||
/// A collection of measurements which instrument that performance of the LSP.
|
/// A collection of measurements which instrument that performance of the LSP.
|
||||||
performance: Arc<Performance>,
|
performance: Arc<Performance>,
|
||||||
/// A memoized version of fixable diagnostic codes retrieved from TypeScript.
|
/// A memoized version of fixable diagnostic codes retrieved from TypeScript.
|
||||||
|
@ -250,6 +258,26 @@ impl Inner {
|
||||||
ts_server.clone(),
|
ts_server.clone(),
|
||||||
);
|
);
|
||||||
let assets = Assets::new(ts_server.clone());
|
let assets = Assets::new(ts_server.clone());
|
||||||
|
let registry_url = NpmRegistryApi::default_url();
|
||||||
|
// Use an "only" cache setting in order to make the
|
||||||
|
// user do an explicit "cache" command and prevent
|
||||||
|
// the cache from being filled with lots of packages while
|
||||||
|
// the user is typing.
|
||||||
|
let cache_setting = CacheSetting::Only;
|
||||||
|
let progress_bar = ProgressBar::default();
|
||||||
|
let npm_cache = NpmCache::from_deno_dir(
|
||||||
|
&dir,
|
||||||
|
cache_setting.clone(),
|
||||||
|
progress_bar.clone(),
|
||||||
|
);
|
||||||
|
let api = NpmRegistryApi::new(
|
||||||
|
registry_url,
|
||||||
|
npm_cache.clone(),
|
||||||
|
cache_setting,
|
||||||
|
progress_bar,
|
||||||
|
);
|
||||||
|
let npm_resolver =
|
||||||
|
NpmPackageResolver::new(npm_cache, api, true, false, None);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
assets,
|
assets,
|
||||||
|
@ -267,6 +295,7 @@ impl Inner {
|
||||||
maybe_testing_server: None,
|
maybe_testing_server: None,
|
||||||
module_registries,
|
module_registries,
|
||||||
module_registries_location,
|
module_registries_location,
|
||||||
|
npm_resolver,
|
||||||
performance,
|
performance,
|
||||||
ts_fixable_diagnostics: Default::default(),
|
ts_fixable_diagnostics: Default::default(),
|
||||||
ts_server,
|
ts_server,
|
||||||
|
@ -435,6 +464,7 @@ impl Inner {
|
||||||
cache_metadata: self.cache_metadata.clone(),
|
cache_metadata: self.cache_metadata.clone(),
|
||||||
documents: self.documents.clone(),
|
documents: self.documents.clone(),
|
||||||
maybe_import_map: self.maybe_import_map.clone(),
|
maybe_import_map: self.maybe_import_map.clone(),
|
||||||
|
maybe_npm_resolver: Some(self.npm_resolver.snapshotted()),
|
||||||
root_uri: self.config.root_uri.clone(),
|
root_uri: self.config.root_uri.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -828,7 +858,7 @@ impl Inner {
|
||||||
if let Err(err) =
|
if let Err(err) =
|
||||||
self.client.register_capability(vec![registration]).await
|
self.client.register_capability(vec![registration]).await
|
||||||
{
|
{
|
||||||
warn!("Client errored on capabilities.\n{}", err);
|
warn!("Client errored on capabilities.\n{:#}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.config.update_enabled_paths(self.client.clone()).await;
|
self.config.update_enabled_paths(self.client.clone()).await;
|
||||||
|
@ -891,6 +921,7 @@ impl Inner {
|
||||||
) {
|
) {
|
||||||
Ok(document) => {
|
Ok(document) => {
|
||||||
if document.is_diagnosable() {
|
if document.is_diagnosable() {
|
||||||
|
self.refresh_npm_specifiers().await;
|
||||||
self
|
self
|
||||||
.diagnostics_server
|
.diagnostics_server
|
||||||
.invalidate(&self.documents.dependents(&specifier));
|
.invalidate(&self.documents.dependents(&specifier));
|
||||||
|
@ -903,6 +934,13 @@ impl Inner {
|
||||||
self.performance.measure(mark);
|
self.performance.measure(mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn refresh_npm_specifiers(&mut self) {
|
||||||
|
let package_reqs = self.documents.npm_package_reqs();
|
||||||
|
if let Err(err) = self.npm_resolver.set_package_reqs(package_reqs).await {
|
||||||
|
warn!("Could not set npm package requirements. {:#}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn did_close(&mut self, params: DidCloseTextDocumentParams) {
|
async fn did_close(&mut self, params: DidCloseTextDocumentParams) {
|
||||||
let mark = self.performance.mark("did_close", Some(¶ms));
|
let mark = self.performance.mark("did_close", Some(¶ms));
|
||||||
if params.text_document.uri.scheme() == "deno" {
|
if params.text_document.uri.scheme() == "deno" {
|
||||||
|
@ -917,6 +955,7 @@ impl Inner {
|
||||||
error!("{}", err);
|
error!("{}", err);
|
||||||
}
|
}
|
||||||
if self.is_diagnosable(&specifier) {
|
if self.is_diagnosable(&specifier) {
|
||||||
|
self.refresh_npm_specifiers().await;
|
||||||
let mut specifiers = self.documents.dependents(&specifier);
|
let mut specifiers = self.documents.dependents(&specifier);
|
||||||
specifiers.push(specifier.clone());
|
specifiers.push(specifier.clone());
|
||||||
self.diagnostics_server.invalidate(&specifiers);
|
self.diagnostics_server.invalidate(&specifiers);
|
||||||
|
@ -1135,7 +1174,7 @@ impl Inner {
|
||||||
Ok(None) => Some(Vec::new()),
|
Ok(None) => Some(Vec::new()),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// TODO(lucacasonato): handle error properly
|
// TODO(lucacasonato): handle error properly
|
||||||
warn!("Format error: {}", err);
|
warn!("Format error: {:#}", err);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2476,6 +2515,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
||||||
let has_specifier_settings =
|
let has_specifier_settings =
|
||||||
inner.config.has_specifier_settings(&specifier);
|
inner.config.has_specifier_settings(&specifier);
|
||||||
if document.is_diagnosable() {
|
if document.is_diagnosable() {
|
||||||
|
inner.refresh_npm_specifiers().await;
|
||||||
let specifiers = inner.documents.dependents(&specifier);
|
let specifiers = inner.documents.dependents(&specifier);
|
||||||
inner.diagnostics_server.invalidate(&specifiers);
|
inner.diagnostics_server.invalidate(&specifiers);
|
||||||
// don't send diagnostics yet if we don't have the specifier settings
|
// don't send diagnostics yet if we don't have the specifier settings
|
||||||
|
@ -2834,7 +2874,7 @@ impl Inner {
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
|
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
|
||||||
let mut inner_loader = ps.create_graph_loader();
|
let mut inner_loader = ps.create_graph_loader();
|
||||||
let mut loader = crate::lsp::documents::DocumentsDenoGraphLoader {
|
let mut loader = crate::lsp::documents::OpenDocumentsGraphLoader {
|
||||||
inner_loader: &mut inner_loader,
|
inner_loader: &mut inner_loader,
|
||||||
open_docs: &open_docs,
|
open_docs: &open_docs,
|
||||||
};
|
};
|
||||||
|
@ -2870,6 +2910,9 @@ impl Inner {
|
||||||
ca_stores: None,
|
ca_stores: None,
|
||||||
ca_file: None,
|
ca_file: None,
|
||||||
unsafely_ignore_certificate_errors: None,
|
unsafely_ignore_certificate_errors: None,
|
||||||
|
// this is to allow loading npm specifiers, so we can remove this
|
||||||
|
// once stabilizing them
|
||||||
|
unstable: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
self.maybe_config_file.clone(),
|
self.maybe_config_file.clone(),
|
||||||
|
@ -2892,6 +2935,7 @@ impl Inner {
|
||||||
// For that we're invalidating all the existing diagnostics and restarting
|
// For that we're invalidating all the existing diagnostics and restarting
|
||||||
// the language server for TypeScript (as it might hold to some stale
|
// the language server for TypeScript (as it might hold to some stale
|
||||||
// documents).
|
// documents).
|
||||||
|
self.refresh_npm_specifiers().await;
|
||||||
self.diagnostics_server.invalidate_all();
|
self.diagnostics_server.invalidate_all();
|
||||||
let _: bool = self
|
let _: bool = self
|
||||||
.ts_server
|
.ts_server
|
||||||
|
|
|
@ -2678,6 +2678,20 @@ fn op_is_cancelled(state: &mut OpState) -> bool {
|
||||||
state.token.is_cancelled()
|
state.token.is_cancelled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_is_node_file(state: &mut OpState, path: String) -> bool {
|
||||||
|
let state = state.borrow::<State>();
|
||||||
|
match ModuleSpecifier::parse(&path) {
|
||||||
|
Ok(specifier) => state
|
||||||
|
.state_snapshot
|
||||||
|
.maybe_npm_resolver
|
||||||
|
.as_ref()
|
||||||
|
.map(|r| r.in_npm_package(&specifier))
|
||||||
|
.unwrap_or(false),
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
fn op_load(
|
fn op_load(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
|
@ -2692,7 +2706,7 @@ fn op_load(
|
||||||
Some(doc) => {
|
Some(doc) => {
|
||||||
json!({
|
json!({
|
||||||
"data": doc.text(),
|
"data": doc.text(),
|
||||||
"scriptKind": crate::tsc::as_ts_script_kind(&doc.media_type()),
|
"scriptKind": crate::tsc::as_ts_script_kind(doc.media_type()),
|
||||||
"version": state.script_version(&specifier),
|
"version": state.script_version(&specifier),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2709,11 +2723,11 @@ fn op_resolve(
|
||||||
let mark = state.performance.mark("op_resolve", Some(&args));
|
let mark = state.performance.mark("op_resolve", Some(&args));
|
||||||
let referrer = state.normalize_specifier(&args.base)?;
|
let referrer = state.normalize_specifier(&args.base)?;
|
||||||
|
|
||||||
let result = if let Some(resolved) = state
|
let result = if let Some(resolved) = state.state_snapshot.documents.resolve(
|
||||||
.state_snapshot
|
args.specifiers,
|
||||||
.documents
|
&referrer,
|
||||||
.resolve(args.specifiers, &referrer)
|
state.state_snapshot.maybe_npm_resolver.as_ref(),
|
||||||
{
|
) {
|
||||||
Ok(
|
Ok(
|
||||||
resolved
|
resolved
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -2789,6 +2803,7 @@ fn init_extension(performance: Arc<Performance>) -> Extension {
|
||||||
.ops(vec![
|
.ops(vec![
|
||||||
op_exists::decl(),
|
op_exists::decl(),
|
||||||
op_is_cancelled::decl(),
|
op_is_cancelled::decl(),
|
||||||
|
op_is_node_file::decl(),
|
||||||
op_load::decl(),
|
op_load::decl(),
|
||||||
op_resolve::decl(),
|
op_resolve::decl(),
|
||||||
op_respond::decl(),
|
op_respond::decl(),
|
||||||
|
|
|
@ -525,6 +525,7 @@ async fn create_graph_and_maybe_check(
|
||||||
&graph.roots,
|
&graph.roots,
|
||||||
Arc::new(RwLock::new(graph.as_ref().into())),
|
Arc::new(RwLock::new(graph.as_ref().into())),
|
||||||
&cache,
|
&cache,
|
||||||
|
ps.npm_resolver.clone(),
|
||||||
check::CheckOptions {
|
check::CheckOptions {
|
||||||
type_check_mode: ps.options.type_check_mode(),
|
type_check_mode: ps.options.type_check_mode(),
|
||||||
debug,
|
debug,
|
||||||
|
|
180
cli/node/mod.rs
180
cli/node/mod.rs
|
@ -31,6 +31,7 @@ use deno_runtime::deno_node::PathClean;
|
||||||
use deno_runtime::deno_node::RequireNpmResolver;
|
use deno_runtime::deno_node::RequireNpmResolver;
|
||||||
use deno_runtime::deno_node::DEFAULT_CONDITIONS;
|
use deno_runtime::deno_node::DEFAULT_CONDITIONS;
|
||||||
use deno_runtime::deno_node::NODE_GLOBAL_THIS_NAME;
|
use deno_runtime::deno_node::NODE_GLOBAL_THIS_NAME;
|
||||||
|
use deno_runtime::deno_node::TYPES_CONDITIONS;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
@ -55,9 +56,61 @@ impl NodeResolution {
|
||||||
match self {
|
match self {
|
||||||
Self::Esm(u) => u,
|
Self::Esm(u) => u,
|
||||||
Self::CommonJs(u) => u,
|
Self::CommonJs(u) => u,
|
||||||
_ => unreachable!(),
|
Self::BuiltIn(specifier) => {
|
||||||
|
if specifier.starts_with("node:") {
|
||||||
|
ModuleSpecifier::parse(&specifier).unwrap()
|
||||||
|
} else {
|
||||||
|
ModuleSpecifier::parse(&format!("node:{}", specifier)).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_specifier_and_media_type(
|
||||||
|
resolution: Option<Self>,
|
||||||
|
) -> (ModuleSpecifier, MediaType) {
|
||||||
|
match resolution {
|
||||||
|
Some(NodeResolution::CommonJs(specifier)) => {
|
||||||
|
let media_type = MediaType::from(&specifier);
|
||||||
|
(
|
||||||
|
specifier,
|
||||||
|
match media_type {
|
||||||
|
MediaType::JavaScript | MediaType::Jsx => MediaType::Cjs,
|
||||||
|
MediaType::TypeScript | MediaType::Tsx => MediaType::Cts,
|
||||||
|
MediaType::Dts => MediaType::Dcts,
|
||||||
|
_ => media_type,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Some(NodeResolution::Esm(specifier)) => {
|
||||||
|
let media_type = MediaType::from(&specifier);
|
||||||
|
(
|
||||||
|
specifier,
|
||||||
|
match media_type {
|
||||||
|
MediaType::JavaScript | MediaType::Jsx => MediaType::Mjs,
|
||||||
|
MediaType::TypeScript | MediaType::Tsx => MediaType::Mts,
|
||||||
|
MediaType::Dts => MediaType::Dmts,
|
||||||
|
_ => media_type,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
maybe_response => {
|
||||||
|
let specifier = match maybe_response {
|
||||||
|
Some(response) => response.into_url(),
|
||||||
|
None => {
|
||||||
|
ModuleSpecifier::parse("deno:///missing_dependency.d.ts").unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(specifier, MediaType::Dts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum NodeResolutionMode {
|
||||||
|
Execution,
|
||||||
|
Types,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodeModulePolyfill {
|
struct NodeModulePolyfill {
|
||||||
|
@ -389,6 +442,7 @@ pub async fn initialize_binary_command(
|
||||||
pub fn node_resolve(
|
pub fn node_resolve(
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
mode: NodeResolutionMode,
|
||||||
npm_resolver: &dyn RequireNpmResolver,
|
npm_resolver: &dyn RequireNpmResolver,
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
) -> Result<Option<NodeResolution>, AnyError> {
|
||||||
// Note: if we are here, then the referrer is an esm module
|
// Note: if we are here, then the referrer is an esm module
|
||||||
|
@ -425,12 +479,22 @@ pub fn node_resolve(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let conditions = DEFAULT_CONDITIONS;
|
let conditions = mode_conditions(mode);
|
||||||
let url = module_resolve(specifier, referrer, conditions, npm_resolver)?;
|
let url = module_resolve(specifier, referrer, conditions, npm_resolver)?;
|
||||||
let url = match url {
|
let url = match url {
|
||||||
Some(url) => url,
|
Some(url) => url,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
let url = match mode {
|
||||||
|
NodeResolutionMode::Execution => url,
|
||||||
|
NodeResolutionMode::Types => {
|
||||||
|
let path = url.to_file_path().unwrap();
|
||||||
|
// todo(16370): the module kind is not correct here. I think we need
|
||||||
|
// typescript to tell us if the referrer is esm or cjs
|
||||||
|
let path = path_to_declaration_path(path, NodeModuleKind::Esm);
|
||||||
|
ModuleSpecifier::from_file_path(path).unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let resolve_response = url_to_node_resolution(url, npm_resolver)?;
|
let resolve_response = url_to_node_resolution(url, npm_resolver)?;
|
||||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||||
|
@ -440,24 +504,36 @@ pub fn node_resolve(
|
||||||
|
|
||||||
pub fn node_resolve_npm_reference(
|
pub fn node_resolve_npm_reference(
|
||||||
reference: &NpmPackageReference,
|
reference: &NpmPackageReference,
|
||||||
|
mode: NodeResolutionMode,
|
||||||
npm_resolver: &NpmPackageResolver,
|
npm_resolver: &NpmPackageResolver,
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
) -> Result<Option<NodeResolution>, AnyError> {
|
||||||
let package_folder =
|
let package_folder =
|
||||||
npm_resolver.resolve_package_folder_from_deno_module(&reference.req)?;
|
npm_resolver.resolve_package_folder_from_deno_module(&reference.req)?;
|
||||||
let resolved_path = package_config_resolve(
|
let node_module_kind = NodeModuleKind::Esm;
|
||||||
|
let maybe_resolved_path = package_config_resolve(
|
||||||
&reference
|
&reference
|
||||||
.sub_path
|
.sub_path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| format!("./{}", s))
|
.map(|s| format!("./{}", s))
|
||||||
.unwrap_or_else(|| ".".to_string()),
|
.unwrap_or_else(|| ".".to_string()),
|
||||||
&package_folder,
|
&package_folder,
|
||||||
|
node_module_kind,
|
||||||
|
mode_conditions(mode),
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
NodeModuleKind::Esm,
|
|
||||||
)
|
)
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!("Error resolving package config for '{}'.", reference)
|
format!("Error resolving package config for '{}'.", reference)
|
||||||
})?;
|
})?;
|
||||||
|
let resolved_path = match maybe_resolved_path {
|
||||||
|
Some(resolved_path) => resolved_path,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
let resolved_path = match mode {
|
||||||
|
NodeResolutionMode::Execution => resolved_path,
|
||||||
|
NodeResolutionMode::Types => {
|
||||||
|
path_to_declaration_path(resolved_path, node_module_kind)
|
||||||
|
}
|
||||||
|
};
|
||||||
let url = ModuleSpecifier::from_file_path(resolved_path).unwrap();
|
let url = ModuleSpecifier::from_file_path(resolved_path).unwrap();
|
||||||
let resolve_response = url_to_node_resolution(url, npm_resolver)?;
|
let resolve_response = url_to_node_resolution(url, npm_resolver)?;
|
||||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||||
|
@ -465,6 +541,41 @@ pub fn node_resolve_npm_reference(
|
||||||
Ok(Some(resolve_response))
|
Ok(Some(resolve_response))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mode_conditions(mode: NodeResolutionMode) -> &'static [&'static str] {
|
||||||
|
match mode {
|
||||||
|
NodeResolutionMode::Execution => DEFAULT_CONDITIONS,
|
||||||
|
NodeResolutionMode::Types => TYPES_CONDITIONS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the resolved file has a corresponding declaration file.
|
||||||
|
fn path_to_declaration_path(
|
||||||
|
path: PathBuf,
|
||||||
|
referrer_kind: NodeModuleKind,
|
||||||
|
) -> PathBuf {
|
||||||
|
let lowercase_path = path.to_string_lossy().to_lowercase();
|
||||||
|
if lowercase_path.ends_with(".d.ts")
|
||||||
|
|| lowercase_path.ends_with(".d.cts")
|
||||||
|
|| lowercase_path.ends_with(".d.ts")
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
let specific_dts_path = match referrer_kind {
|
||||||
|
NodeModuleKind::Cjs => path.with_extension("d.cts"),
|
||||||
|
NodeModuleKind::Esm => path.with_extension("d.mts"),
|
||||||
|
};
|
||||||
|
if specific_dts_path.exists() {
|
||||||
|
specific_dts_path
|
||||||
|
} else {
|
||||||
|
let dts_path = path.with_extension("d.ts");
|
||||||
|
if dts_path.exists() {
|
||||||
|
dts_path
|
||||||
|
} else {
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn node_resolve_binary_export(
|
pub fn node_resolve_binary_export(
|
||||||
pkg_req: &NpmPackageReq,
|
pkg_req: &NpmPackageReq,
|
||||||
bin_name: Option<&str>,
|
bin_name: Option<&str>,
|
||||||
|
@ -562,45 +673,56 @@ pub fn load_cjs_module_from_ext_node(
|
||||||
fn package_config_resolve(
|
fn package_config_resolve(
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
package_dir: &Path,
|
package_dir: &Path,
|
||||||
npm_resolver: &dyn RequireNpmResolver,
|
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
) -> Result<PathBuf, AnyError> {
|
conditions: &[&str],
|
||||||
|
npm_resolver: &dyn RequireNpmResolver,
|
||||||
|
) -> Result<Option<PathBuf>, AnyError> {
|
||||||
let package_json_path = package_dir.join("package.json");
|
let package_json_path = package_dir.join("package.json");
|
||||||
let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap();
|
let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap();
|
||||||
let package_config =
|
let package_config =
|
||||||
PackageJson::load(npm_resolver, package_json_path.clone())?;
|
PackageJson::load(npm_resolver, package_json_path.clone())?;
|
||||||
if let Some(exports) = &package_config.exports {
|
if let Some(exports) = &package_config.exports {
|
||||||
|
let is_types = conditions == TYPES_CONDITIONS;
|
||||||
|
if is_types && package_subpath == "." {
|
||||||
|
if let Ok(Some(path)) =
|
||||||
|
legacy_main_resolve(&package_config, referrer_kind, conditions)
|
||||||
|
{
|
||||||
|
return Ok(Some(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
return package_exports_resolve(
|
return package_exports_resolve(
|
||||||
&package_json_path,
|
&package_json_path,
|
||||||
package_subpath.to_string(),
|
package_subpath.to_string(),
|
||||||
exports,
|
exports,
|
||||||
&referrer,
|
&referrer,
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
DEFAULT_CONDITIONS,
|
conditions,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
);
|
)
|
||||||
|
.map(Some);
|
||||||
}
|
}
|
||||||
if package_subpath == "." {
|
if package_subpath == "." {
|
||||||
return legacy_main_resolve(&package_config, referrer_kind);
|
return legacy_main_resolve(&package_config, referrer_kind, conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(package_dir.join(package_subpath))
|
Ok(Some(package_dir.join(package_subpath)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn url_to_node_resolution(
|
pub fn url_to_node_resolution(
|
||||||
url: ModuleSpecifier,
|
url: ModuleSpecifier,
|
||||||
npm_resolver: &dyn RequireNpmResolver,
|
npm_resolver: &dyn RequireNpmResolver,
|
||||||
) -> Result<NodeResolution, AnyError> {
|
) -> Result<NodeResolution, AnyError> {
|
||||||
Ok(if url.as_str().starts_with("http") {
|
let url_str = url.as_str().to_lowercase();
|
||||||
|
Ok(if url_str.starts_with("http") {
|
||||||
NodeResolution::Esm(url)
|
NodeResolution::Esm(url)
|
||||||
} else if url.as_str().ends_with(".js") {
|
} else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") {
|
||||||
let package_config = get_closest_package_json(&url, npm_resolver)?;
|
let package_config = get_closest_package_json(&url, npm_resolver)?;
|
||||||
if package_config.typ == "module" {
|
if package_config.typ == "module" {
|
||||||
NodeResolution::Esm(url)
|
NodeResolution::Esm(url)
|
||||||
} else {
|
} else {
|
||||||
NodeResolution::CommonJs(url)
|
NodeResolution::CommonJs(url)
|
||||||
}
|
}
|
||||||
} else if url.as_str().ends_with(".mjs") {
|
} else if url_str.ends_with(".mjs") || url_str.ends_with(".d.mts") {
|
||||||
NodeResolution::Esm(url)
|
NodeResolution::Esm(url)
|
||||||
} else {
|
} else {
|
||||||
NodeResolution::CommonJs(url)
|
NodeResolution::CommonJs(url)
|
||||||
|
@ -666,7 +788,16 @@ fn module_resolve(
|
||||||
// note: if we're here, the referrer is an esm module
|
// note: if we're here, the referrer is an esm module
|
||||||
let url = if should_be_treated_as_relative_or_absolute_path(specifier) {
|
let url = if should_be_treated_as_relative_or_absolute_path(specifier) {
|
||||||
let resolved_specifier = referrer.join(specifier)?;
|
let resolved_specifier = referrer.join(specifier)?;
|
||||||
Some(resolved_specifier)
|
if conditions == TYPES_CONDITIONS {
|
||||||
|
let file_path = to_file_path(&resolved_specifier);
|
||||||
|
// todo(dsherret): the node module kind is not correct and we
|
||||||
|
// should use the value provided by typescript instead
|
||||||
|
let declaration_path =
|
||||||
|
path_to_declaration_path(file_path, NodeModuleKind::Esm);
|
||||||
|
Some(ModuleSpecifier::from_file_path(declaration_path).unwrap())
|
||||||
|
} else {
|
||||||
|
Some(resolved_specifier)
|
||||||
|
}
|
||||||
} else if specifier.starts_with('#') {
|
} else if specifier.starts_with('#') {
|
||||||
Some(
|
Some(
|
||||||
package_imports_resolve(
|
package_imports_resolve(
|
||||||
|
@ -681,16 +812,14 @@ fn module_resolve(
|
||||||
} else if let Ok(resolved) = Url::parse(specifier) {
|
} else if let Ok(resolved) = Url::parse(specifier) {
|
||||||
Some(resolved)
|
Some(resolved)
|
||||||
} else {
|
} else {
|
||||||
Some(
|
package_resolve(
|
||||||
package_resolve(
|
specifier,
|
||||||
specifier,
|
referrer,
|
||||||
referrer,
|
NodeModuleKind::Esm,
|
||||||
NodeModuleKind::Esm,
|
conditions,
|
||||||
conditions,
|
npm_resolver,
|
||||||
npm_resolver,
|
)?
|
||||||
)
|
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())
|
||||||
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())?,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
Ok(match url {
|
Ok(match url {
|
||||||
Some(url) => Some(finalize_resolution(url, referrer)?),
|
Some(url) => Some(finalize_resolution(url, referrer)?),
|
||||||
|
@ -913,6 +1042,7 @@ fn resolve(
|
||||||
let module_dir = npm_resolver.resolve_package_folder_from_package(
|
let module_dir = npm_resolver.resolve_package_folder_from_package(
|
||||||
package_specifier.as_str(),
|
package_specifier.as_str(),
|
||||||
&referrer_path,
|
&referrer_path,
|
||||||
|
conditions,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let package_json_path = module_dir.join("package.json");
|
let package_json_path = module_dir.join("package.json");
|
||||||
|
|
|
@ -160,13 +160,14 @@ impl ReadonlyNpmCache {
|
||||||
.take(if is_scoped_package { 3 } else { 2 })
|
.take(if is_scoped_package { 3 } else { 2 })
|
||||||
.map(|(_, part)| part)
|
.map(|(_, part)| part)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
if parts.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let version = parts.pop().unwrap();
|
let version = parts.pop().unwrap();
|
||||||
let name = parts.join("/");
|
let name = parts.join("/");
|
||||||
|
NpmVersion::parse(version)
|
||||||
Some(NpmPackageId {
|
.ok()
|
||||||
name,
|
.map(|version| NpmPackageId { name, version })
|
||||||
version: NpmVersion::parse(version).unwrap(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cache_location(&self) -> PathBuf {
|
pub fn get_cache_location(&self) -> PathBuf {
|
||||||
|
|
|
@ -13,4 +13,5 @@ pub use resolution::NpmPackageId;
|
||||||
pub use resolution::NpmPackageReference;
|
pub use resolution::NpmPackageReference;
|
||||||
pub use resolution::NpmPackageReq;
|
pub use resolution::NpmPackageReq;
|
||||||
pub use resolution::NpmResolutionPackage;
|
pub use resolution::NpmResolutionPackage;
|
||||||
|
pub use resolution::NpmResolutionSnapshot;
|
||||||
pub use resolvers::NpmPackageResolver;
|
pub use resolvers::NpmPackageResolver;
|
||||||
|
|
|
@ -21,6 +21,7 @@ use super::registry::NpmPackageVersionDistInfo;
|
||||||
use super::registry::NpmPackageVersionInfo;
|
use super::registry::NpmPackageVersionInfo;
|
||||||
use super::registry::NpmRegistryApi;
|
use super::registry::NpmRegistryApi;
|
||||||
use super::semver::NpmVersion;
|
use super::semver::NpmVersion;
|
||||||
|
use super::semver::NpmVersionReq;
|
||||||
use super::semver::SpecifierVersionReq;
|
use super::semver::SpecifierVersionReq;
|
||||||
|
|
||||||
/// The version matcher used for npm schemed urls is more strict than
|
/// The version matcher used for npm schemed urls is more strict than
|
||||||
|
@ -375,15 +376,57 @@ impl NpmResolution {
|
||||||
|
|
||||||
pub async fn add_package_reqs(
|
pub async fn add_package_reqs(
|
||||||
&self,
|
&self,
|
||||||
mut package_reqs: Vec<NpmPackageReq>,
|
package_reqs: Vec<NpmPackageReq>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
// multiple packages are resolved in alphabetical order
|
|
||||||
package_reqs.sort_by(|a, b| a.name.cmp(&b.name));
|
|
||||||
|
|
||||||
// only allow one thread in here at a time
|
// only allow one thread in here at a time
|
||||||
let _permit = self.update_sempahore.acquire().await.unwrap();
|
let _permit = self.update_sempahore.acquire().await.unwrap();
|
||||||
let mut snapshot = self.snapshot.read().clone();
|
let snapshot = self.snapshot.read().clone();
|
||||||
let mut pending_dependencies = VecDeque::new();
|
|
||||||
|
let snapshot = self
|
||||||
|
.add_package_reqs_to_snapshot(package_reqs, snapshot)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
*self.snapshot.write() = snapshot;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_package_reqs(
|
||||||
|
&self,
|
||||||
|
package_reqs: HashSet<NpmPackageReq>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
// only allow one thread in here at a time
|
||||||
|
let _permit = self.update_sempahore.acquire().await.unwrap();
|
||||||
|
let snapshot = self.snapshot.read().clone();
|
||||||
|
|
||||||
|
let has_removed_package = !snapshot
|
||||||
|
.package_reqs
|
||||||
|
.keys()
|
||||||
|
.all(|req| package_reqs.contains(req));
|
||||||
|
// if any packages were removed, we need to completely recreate the npm resolution snapshot
|
||||||
|
let snapshot = if has_removed_package {
|
||||||
|
NpmResolutionSnapshot::default()
|
||||||
|
} else {
|
||||||
|
snapshot
|
||||||
|
};
|
||||||
|
let snapshot = self
|
||||||
|
.add_package_reqs_to_snapshot(
|
||||||
|
package_reqs.into_iter().collect(),
|
||||||
|
snapshot,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
*self.snapshot.write() = snapshot;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn add_package_reqs_to_snapshot(
|
||||||
|
&self,
|
||||||
|
mut package_reqs: Vec<NpmPackageReq>,
|
||||||
|
mut snapshot: NpmResolutionSnapshot,
|
||||||
|
) -> Result<NpmResolutionSnapshot, AnyError> {
|
||||||
|
// multiple packages are resolved in alphabetical order
|
||||||
|
package_reqs.sort_by(|a, b| a.name.cmp(&b.name));
|
||||||
|
|
||||||
// go over the top level packages first, then down the
|
// go over the top level packages first, then down the
|
||||||
// tree one level at a time through all the branches
|
// tree one level at a time through all the branches
|
||||||
|
@ -418,6 +461,7 @@ impl NpmResolution {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut pending_dependencies = VecDeque::new();
|
||||||
for result in futures::future::join_all(unresolved_tasks).await {
|
for result in futures::future::join_all(unresolved_tasks).await {
|
||||||
let (package_req, info) = result??;
|
let (package_req, info) = result??;
|
||||||
let version_and_info = get_resolved_package_version_and_info(
|
let version_and_info = get_resolved_package_version_and_info(
|
||||||
|
@ -546,8 +590,7 @@ impl NpmResolution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*self.snapshot.write() = snapshot;
|
Ok(snapshot)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_package_from_package(
|
pub fn resolve_package_from_package(
|
||||||
|
@ -601,6 +644,22 @@ fn get_resolved_package_version_and_info(
|
||||||
) -> Result<VersionAndInfo, AnyError> {
|
) -> Result<VersionAndInfo, AnyError> {
|
||||||
let mut maybe_best_version: Option<VersionAndInfo> = None;
|
let mut maybe_best_version: Option<VersionAndInfo> = None;
|
||||||
if let Some(tag) = version_matcher.tag() {
|
if let Some(tag) = version_matcher.tag() {
|
||||||
|
// For when someone just specifies @types/node, we want to pull in a
|
||||||
|
// "known good" version of @types/node that works well with Deno and
|
||||||
|
// not necessarily the latest version. For example, we might only be
|
||||||
|
// compatible with Node vX, but then Node vY is published so we wouldn't
|
||||||
|
// want to pull that in.
|
||||||
|
// Note: If the user doesn't want this behavior, then they can specify an
|
||||||
|
// explicit version.
|
||||||
|
if tag == "latest" && pkg_name == "@types/node" {
|
||||||
|
return get_resolved_package_version_and_info(
|
||||||
|
pkg_name,
|
||||||
|
&NpmVersionReq::parse("18.0.0 - 18.8.2").unwrap(),
|
||||||
|
info,
|
||||||
|
parent,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(version) = info.dist_tags.get(tag) {
|
if let Some(version) = info.dist_tags.get(tag) {
|
||||||
match info.versions.get(version) {
|
match info.versions.get(version) {
|
||||||
Some(info) => {
|
Some(info) => {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -26,6 +27,7 @@ pub trait InnerNpmPackageResolver: Send + Sync {
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
conditions: &[&str],
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
|
||||||
fn resolve_package_folder_from_specifier(
|
fn resolve_package_folder_from_specifier(
|
||||||
|
@ -40,6 +42,11 @@ pub trait InnerNpmPackageResolver: Send + Sync {
|
||||||
packages: Vec<NpmPackageReq>,
|
packages: Vec<NpmPackageReq>,
|
||||||
) -> BoxFuture<'static, Result<(), AnyError>>;
|
) -> BoxFuture<'static, Result<(), AnyError>>;
|
||||||
|
|
||||||
|
fn set_package_reqs(
|
||||||
|
&self,
|
||||||
|
packages: HashSet<NpmPackageReq>,
|
||||||
|
) -> BoxFuture<'static, Result<(), AnyError>>;
|
||||||
|
|
||||||
fn ensure_read_permission(&self, path: &Path) -> Result<(), AnyError>;
|
fn ensure_read_permission(&self, path: &Path) -> Result<(), AnyError>;
|
||||||
|
|
||||||
fn snapshot(&self) -> NpmResolutionSnapshot;
|
fn snapshot(&self) -> NpmResolutionSnapshot;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
//! Code for global npm cache resolution.
|
//! Code for global npm cache resolution.
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -11,6 +12,8 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::futures::future::BoxFuture;
|
use deno_core::futures::future::BoxFuture;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use deno_runtime::deno_node::PackageJson;
|
||||||
|
use deno_runtime::deno_node::TYPES_CONDITIONS;
|
||||||
|
|
||||||
use crate::npm::resolution::NpmResolution;
|
use crate::npm::resolution::NpmResolution;
|
||||||
use crate::npm::resolution::NpmResolutionSnapshot;
|
use crate::npm::resolution::NpmResolutionSnapshot;
|
||||||
|
@ -65,14 +68,35 @@ impl InnerNpmPackageResolver for GlobalNpmPackageResolver {
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
conditions: &[&str],
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
let referrer_pkg_id = self
|
let referrer_pkg_id = self
|
||||||
.cache
|
.cache
|
||||||
.resolve_package_id_from_specifier(referrer, &self.registry_url)?;
|
.resolve_package_id_from_specifier(referrer, &self.registry_url)?;
|
||||||
let pkg = self
|
let pkg_result = self
|
||||||
.resolution
|
.resolution
|
||||||
.resolve_package_from_package(name, &referrer_pkg_id)?;
|
.resolve_package_from_package(name, &referrer_pkg_id);
|
||||||
Ok(self.package_folder(&pkg.id))
|
if conditions == TYPES_CONDITIONS && !name.starts_with("@types/") {
|
||||||
|
// When doing types resolution, the package must contain a "types"
|
||||||
|
// entry, or else it will then search for a @types package
|
||||||
|
if let Ok(pkg) = pkg_result {
|
||||||
|
let package_folder = self.package_folder(&pkg.id);
|
||||||
|
let package_json = PackageJson::load_skip_read_permission(
|
||||||
|
package_folder.join("package.json"),
|
||||||
|
)?;
|
||||||
|
if package_json.types.is_some() {
|
||||||
|
return Ok(package_folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = format!("@types/{}", name);
|
||||||
|
let pkg = self
|
||||||
|
.resolution
|
||||||
|
.resolve_package_from_package(&name, &referrer_pkg_id)?;
|
||||||
|
Ok(self.package_folder(&pkg.id))
|
||||||
|
} else {
|
||||||
|
Ok(self.package_folder(&pkg_result?.id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_package_folder_from_specifier(
|
fn resolve_package_folder_from_specifier(
|
||||||
|
@ -96,12 +120,19 @@ impl InnerNpmPackageResolver for GlobalNpmPackageResolver {
|
||||||
let resolver = self.clone();
|
let resolver = self.clone();
|
||||||
async move {
|
async move {
|
||||||
resolver.resolution.add_package_reqs(packages).await?;
|
resolver.resolution.add_package_reqs(packages).await?;
|
||||||
cache_packages(
|
cache_packages_in_resolver(&resolver).await
|
||||||
resolver.resolution.all_packages(),
|
}
|
||||||
&resolver.cache,
|
.boxed()
|
||||||
&resolver.registry_url,
|
}
|
||||||
)
|
|
||||||
.await
|
fn set_package_reqs(
|
||||||
|
&self,
|
||||||
|
packages: HashSet<NpmPackageReq>,
|
||||||
|
) -> BoxFuture<'static, Result<(), AnyError>> {
|
||||||
|
let resolver = self.clone();
|
||||||
|
async move {
|
||||||
|
resolver.resolution.set_package_reqs(packages).await?;
|
||||||
|
cache_packages_in_resolver(&resolver).await
|
||||||
}
|
}
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
@ -115,3 +146,14 @@ impl InnerNpmPackageResolver for GlobalNpmPackageResolver {
|
||||||
self.resolution.snapshot()
|
self.resolution.snapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn cache_packages_in_resolver(
|
||||||
|
resolver: &GlobalNpmPackageResolver,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
cache_packages(
|
||||||
|
resolver.resolution.all_packages(),
|
||||||
|
&resolver.cache,
|
||||||
|
&resolver.registry_url,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ use deno_core::futures::future::BoxFuture;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_runtime::deno_core::futures;
|
use deno_runtime::deno_core::futures;
|
||||||
|
use deno_runtime::deno_node::PackageJson;
|
||||||
|
use deno_runtime::deno_node::TYPES_CONDITIONS;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
use crate::fs_util;
|
use crate::fs_util;
|
||||||
|
@ -124,6 +126,7 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
conditions: &[&str],
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
let local_path = self.resolve_folder_for_specifier(referrer)?;
|
let local_path = self.resolve_folder_for_specifier(referrer)?;
|
||||||
let package_root_path = self.resolve_package_root(&local_path);
|
let package_root_path = self.resolve_package_root(&local_path);
|
||||||
|
@ -132,8 +135,28 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
|
||||||
current_folder = get_next_node_modules_ancestor(current_folder);
|
current_folder = get_next_node_modules_ancestor(current_folder);
|
||||||
let sub_dir = join_package_name(current_folder, name);
|
let sub_dir = join_package_name(current_folder, name);
|
||||||
if sub_dir.is_dir() {
|
if sub_dir.is_dir() {
|
||||||
return Ok(sub_dir);
|
// if doing types resolution, only resolve the package if it specifies a types property
|
||||||
|
if conditions == TYPES_CONDITIONS && !name.starts_with("@types/") {
|
||||||
|
let package_json = PackageJson::load_skip_read_permission(
|
||||||
|
sub_dir.join("package.json"),
|
||||||
|
)?;
|
||||||
|
if package_json.types.is_some() {
|
||||||
|
return Ok(sub_dir);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Ok(sub_dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if doing type resolution, check for the existance of a @types package
|
||||||
|
if conditions == TYPES_CONDITIONS && !name.starts_with("@types/") {
|
||||||
|
let sub_dir =
|
||||||
|
join_package_name(current_folder, &format!("@types/{}", name));
|
||||||
|
if sub_dir.is_dir() {
|
||||||
|
return Ok(sub_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if current_folder == self.root_node_modules_path {
|
if current_folder == self.root_node_modules_path {
|
||||||
bail!(
|
bail!(
|
||||||
"could not find package '{}' from referrer '{}'.",
|
"could not find package '{}' from referrer '{}'.",
|
||||||
|
@ -164,15 +187,20 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
|
||||||
let resolver = self.clone();
|
let resolver = self.clone();
|
||||||
async move {
|
async move {
|
||||||
resolver.resolution.add_package_reqs(packages).await?;
|
resolver.resolution.add_package_reqs(packages).await?;
|
||||||
|
sync_resolver_with_fs(&resolver).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
||||||
sync_resolution_with_fs(
|
fn set_package_reqs(
|
||||||
&resolver.resolution.snapshot(),
|
&self,
|
||||||
&resolver.cache,
|
packages: HashSet<NpmPackageReq>,
|
||||||
&resolver.registry_url,
|
) -> BoxFuture<'static, Result<(), AnyError>> {
|
||||||
&resolver.root_node_modules_path,
|
let resolver = self.clone();
|
||||||
)
|
async move {
|
||||||
.await?;
|
resolver.resolution.set_package_reqs(packages).await?;
|
||||||
|
sync_resolver_with_fs(&resolver).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
.boxed()
|
.boxed()
|
||||||
|
@ -187,6 +215,18 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn sync_resolver_with_fs(
|
||||||
|
resolver: &LocalNpmPackageResolver,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
sync_resolution_with_fs(
|
||||||
|
&resolver.resolution.snapshot(),
|
||||||
|
&resolver.cache,
|
||||||
|
&resolver.registry_url,
|
||||||
|
&resolver.root_node_modules_path,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a pnpm style folder structure.
|
/// Creates a pnpm style folder structure.
|
||||||
async fn sync_resolution_with_fs(
|
async fn sync_resolution_with_fs(
|
||||||
snapshot: &NpmResolutionSnapshot,
|
snapshot: &NpmResolutionSnapshot,
|
||||||
|
|
|
@ -15,6 +15,7 @@ use global::GlobalNpmPackageResolver;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -23,10 +24,10 @@ use crate::fs_util;
|
||||||
|
|
||||||
use self::common::InnerNpmPackageResolver;
|
use self::common::InnerNpmPackageResolver;
|
||||||
use self::local::LocalNpmPackageResolver;
|
use self::local::LocalNpmPackageResolver;
|
||||||
use super::resolution::NpmResolutionSnapshot;
|
|
||||||
use super::NpmCache;
|
use super::NpmCache;
|
||||||
use super::NpmPackageReq;
|
use super::NpmPackageReq;
|
||||||
use super::NpmRegistryApi;
|
use super::NpmRegistryApi;
|
||||||
|
use super::NpmResolutionSnapshot;
|
||||||
|
|
||||||
const RESOLUTION_STATE_ENV_VAR_NAME: &str =
|
const RESOLUTION_STATE_ENV_VAR_NAME: &str =
|
||||||
"DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE";
|
"DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE";
|
||||||
|
@ -67,6 +68,19 @@ pub struct NpmPackageResolver {
|
||||||
no_npm: bool,
|
no_npm: bool,
|
||||||
inner: Arc<dyn InnerNpmPackageResolver>,
|
inner: Arc<dyn InnerNpmPackageResolver>,
|
||||||
local_node_modules_path: Option<PathBuf>,
|
local_node_modules_path: Option<PathBuf>,
|
||||||
|
api: NpmRegistryApi,
|
||||||
|
cache: NpmCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for NpmPackageResolver {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("NpmPackageResolver")
|
||||||
|
.field("unstable", &self.unstable)
|
||||||
|
.field("no_npm", &self.no_npm)
|
||||||
|
.field("inner", &"<omitted>")
|
||||||
|
.field("local_node_modules_path", &self.local_node_modules_path)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NpmPackageResolver {
|
impl NpmPackageResolver {
|
||||||
|
@ -76,6 +90,24 @@ impl NpmPackageResolver {
|
||||||
unstable: bool,
|
unstable: bool,
|
||||||
no_npm: bool,
|
no_npm: bool,
|
||||||
local_node_modules_path: Option<PathBuf>,
|
local_node_modules_path: Option<PathBuf>,
|
||||||
|
) -> Self {
|
||||||
|
Self::new_with_maybe_snapshot(
|
||||||
|
cache,
|
||||||
|
api,
|
||||||
|
unstable,
|
||||||
|
no_npm,
|
||||||
|
local_node_modules_path,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_maybe_snapshot(
|
||||||
|
cache: NpmCache,
|
||||||
|
api: NpmRegistryApi,
|
||||||
|
unstable: bool,
|
||||||
|
no_npm: bool,
|
||||||
|
local_node_modules_path: Option<PathBuf>,
|
||||||
|
initial_snapshot: Option<NpmResolutionSnapshot>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let process_npm_state = NpmProcessState::take();
|
let process_npm_state = NpmProcessState::take();
|
||||||
let local_node_modules_path = local_node_modules_path.or_else(|| {
|
let local_node_modules_path = local_node_modules_path.or_else(|| {
|
||||||
|
@ -83,24 +115,29 @@ impl NpmPackageResolver {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|s| s.local_node_modules_path.as_ref().map(PathBuf::from))
|
.and_then(|s| s.local_node_modules_path.as_ref().map(PathBuf::from))
|
||||||
});
|
});
|
||||||
let maybe_snapshot = process_npm_state.map(|s| s.snapshot);
|
let maybe_snapshot =
|
||||||
|
initial_snapshot.or_else(|| process_npm_state.map(|s| s.snapshot));
|
||||||
let inner: Arc<dyn InnerNpmPackageResolver> = match &local_node_modules_path
|
let inner: Arc<dyn InnerNpmPackageResolver> = match &local_node_modules_path
|
||||||
{
|
{
|
||||||
Some(node_modules_folder) => Arc::new(LocalNpmPackageResolver::new(
|
Some(node_modules_folder) => Arc::new(LocalNpmPackageResolver::new(
|
||||||
cache,
|
cache.clone(),
|
||||||
api,
|
api.clone(),
|
||||||
node_modules_folder.clone(),
|
node_modules_folder.clone(),
|
||||||
maybe_snapshot,
|
maybe_snapshot,
|
||||||
)),
|
)),
|
||||||
None => {
|
None => Arc::new(GlobalNpmPackageResolver::new(
|
||||||
Arc::new(GlobalNpmPackageResolver::new(cache, api, maybe_snapshot))
|
cache.clone(),
|
||||||
}
|
api.clone(),
|
||||||
|
maybe_snapshot,
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
unstable,
|
unstable,
|
||||||
no_npm,
|
no_npm,
|
||||||
inner,
|
inner,
|
||||||
local_node_modules_path,
|
local_node_modules_path,
|
||||||
|
api,
|
||||||
|
cache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +159,11 @@ impl NpmPackageResolver {
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
conditions: &[&str],
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
let path = self
|
let path = self
|
||||||
.inner
|
.inner
|
||||||
.resolve_package_folder_from_package(name, referrer)?;
|
.resolve_package_folder_from_package(name, referrer, conditions)?;
|
||||||
log::debug!("Resolved {} from {} to {}", name, referrer, path.display());
|
log::debug!("Resolved {} from {} to {}", name, referrer, path.display());
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
@ -156,12 +194,14 @@ impl NpmPackageResolver {
|
||||||
self.inner.has_packages()
|
self.inner.has_packages()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a package requirement to the resolver and ensures everything is setup.
|
/// Adds package requirements to the resolver and ensures everything is setup.
|
||||||
pub async fn add_package_reqs(
|
pub async fn add_package_reqs(
|
||||||
&self,
|
&self,
|
||||||
packages: Vec<NpmPackageReq>,
|
packages: Vec<NpmPackageReq>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
assert!(!packages.is_empty());
|
if packages.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
if !self.unstable {
|
if !self.unstable {
|
||||||
bail!(
|
bail!(
|
||||||
|
@ -187,6 +227,14 @@ impl NpmPackageResolver {
|
||||||
self.inner.add_package_reqs(packages).await
|
self.inner.add_package_reqs(packages).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets package requirements to the resolver, removing old requirements and adding new ones.
|
||||||
|
pub async fn set_package_reqs(
|
||||||
|
&self,
|
||||||
|
packages: HashSet<NpmPackageReq>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.inner.set_package_reqs(packages).await
|
||||||
|
}
|
||||||
|
|
||||||
// If the main module should be treated as being in an npm package.
|
// If the main module should be treated as being in an npm package.
|
||||||
// This is triggered via a secret environment variable which is used
|
// This is triggered via a secret environment variable which is used
|
||||||
// for functionality like child_process.fork. Users should NOT depend
|
// for functionality like child_process.fork. Users should NOT depend
|
||||||
|
@ -206,6 +254,18 @@ impl NpmPackageResolver {
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a new resolver with a new snapshotted state.
|
||||||
|
pub fn snapshotted(&self) -> Self {
|
||||||
|
Self::new_with_maybe_snapshot(
|
||||||
|
self.cache.clone(),
|
||||||
|
self.api.clone(),
|
||||||
|
self.unstable,
|
||||||
|
self.no_npm,
|
||||||
|
self.local_node_modules_path.clone(),
|
||||||
|
Some(self.inner.snapshot()),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequireNpmResolver for NpmPackageResolver {
|
impl RequireNpmResolver for NpmPackageResolver {
|
||||||
|
@ -213,9 +273,10 @@ impl RequireNpmResolver for NpmPackageResolver {
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &std::path::Path,
|
referrer: &std::path::Path,
|
||||||
|
conditions: &[&str],
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
let referrer = path_to_specifier(referrer)?;
|
let referrer = path_to_specifier(referrer)?;
|
||||||
self.resolve_package_folder_from_package(specifier, &referrer)
|
self.resolve_package_folder_from_package(specifier, &referrer, conditions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_package_folder_from_path(
|
fn resolve_package_folder_from_path(
|
||||||
|
|
|
@ -34,9 +34,9 @@ use crate::tools::check;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::anyhow::bail;
|
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
|
use deno_core::error::generic_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures;
|
use deno_core::futures;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
|
@ -433,8 +433,13 @@ impl ProcState {
|
||||||
let check_cache =
|
let check_cache =
|
||||||
TypeCheckCache::new(&self.dir.type_checking_cache_db_file_path());
|
TypeCheckCache::new(&self.dir.type_checking_cache_db_file_path());
|
||||||
let graph_data = self.graph_data.clone();
|
let graph_data = self.graph_data.clone();
|
||||||
let check_result =
|
let check_result = check::check(
|
||||||
check::check(&roots, graph_data, &check_cache, options)?;
|
&roots,
|
||||||
|
graph_data,
|
||||||
|
&check_cache,
|
||||||
|
self.npm_resolver.clone(),
|
||||||
|
options,
|
||||||
|
)?;
|
||||||
if !check_result.diagnostics.is_empty() {
|
if !check_result.diagnostics.is_empty() {
|
||||||
return Err(anyhow!(check_result.diagnostics));
|
return Err(anyhow!(check_result.diagnostics));
|
||||||
}
|
}
|
||||||
|
@ -470,7 +475,7 @@ impl ProcState {
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
) -> Result<ModuleSpecifier, AnyError> {
|
||||||
let response = match result? {
|
let response = match result? {
|
||||||
Some(response) => response,
|
Some(response) => response,
|
||||||
None => bail!("Not found."),
|
None => return Err(generic_error("not found")),
|
||||||
};
|
};
|
||||||
if let NodeResolution::CommonJs(specifier) = &response {
|
if let NodeResolution::CommonJs(specifier) = &response {
|
||||||
// remember that this was a common js resolution
|
// remember that this was a common js resolution
|
||||||
|
@ -493,6 +498,7 @@ impl ProcState {
|
||||||
.handle_node_resolve_result(node::node_resolve(
|
.handle_node_resolve_result(node::node_resolve(
|
||||||
specifier,
|
specifier,
|
||||||
&referrer,
|
&referrer,
|
||||||
|
node::NodeResolutionMode::Execution,
|
||||||
&self.npm_resolver,
|
&self.npm_resolver,
|
||||||
))
|
))
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
|
@ -516,6 +522,7 @@ impl ProcState {
|
||||||
return self
|
return self
|
||||||
.handle_node_resolve_result(node::node_resolve_npm_reference(
|
.handle_node_resolve_result(node::node_resolve_npm_reference(
|
||||||
&reference,
|
&reference,
|
||||||
|
node::NodeResolutionMode::Execution,
|
||||||
&self.npm_resolver,
|
&self.npm_resolver,
|
||||||
))
|
))
|
||||||
.with_context(|| format!("Could not resolve '{}'.", reference));
|
.with_context(|| format!("Could not resolve '{}'.", reference));
|
||||||
|
|
|
@ -50,6 +50,13 @@ itest!(declaration_header_file_with_no_exports {
|
||||||
output_str: Some(""),
|
output_str: Some(""),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(check_npm_install_diagnostics {
|
||||||
|
args: "check --quiet check/npm_install_diagnostics/main.ts",
|
||||||
|
output: "check/npm_install_diagnostics/main.out",
|
||||||
|
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
|
||||||
|
exit_code: 1,
|
||||||
|
});
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cache_switching_config_then_no_config() {
|
fn cache_switching_config_then_no_config() {
|
||||||
let deno_dir = util::new_deno_dir();
|
let deno_dir = util::new_deno_dir();
|
||||||
|
|
|
@ -3346,6 +3346,37 @@ fn lsp_code_actions_deno_cache() {
|
||||||
session.shutdown_and_exit();
|
session.shutdown_and_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_code_actions_deno_cache_npm() {
|
||||||
|
let mut session = TestSession::from_file("initialize_params.json");
|
||||||
|
let diagnostics = session.did_open(json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "import chalk from \"npm:chalk\";\n\nconsole.log(chalk.green);\n"
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
assert_eq!(
|
||||||
|
diagnostics.with_source("deno"),
|
||||||
|
load_fixture_as("code_actions/cache_npm/diagnostics.json")
|
||||||
|
);
|
||||||
|
|
||||||
|
let (maybe_res, maybe_err) = session
|
||||||
|
.client
|
||||||
|
.write_request(
|
||||||
|
"textDocument/codeAction",
|
||||||
|
load_fixture("code_actions/cache_npm/cache_action.json"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
assert_eq!(
|
||||||
|
maybe_res,
|
||||||
|
Some(load_fixture("code_actions/cache_npm/cache_response.json"))
|
||||||
|
);
|
||||||
|
session.shutdown_and_exit();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lsp_code_actions_imports() {
|
fn lsp_code_actions_imports() {
|
||||||
let mut session = TestSession::from_file("initialize_params.json");
|
let mut session = TestSession::from_file("initialize_params.json");
|
||||||
|
@ -4046,6 +4077,169 @@ fn lsp_completions_no_snippet() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_completions_npm() {
|
||||||
|
let _g = http_server();
|
||||||
|
let mut client = init("initialize_params.json");
|
||||||
|
did_open(
|
||||||
|
&mut client,
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "import cjsDefault from 'npm:@denotest/cjs-default-export';import chalk from 'npm:chalk';\n\n",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request::<_, _, Value>(
|
||||||
|
"deno/cache",
|
||||||
|
json!({
|
||||||
|
"referrer": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
},
|
||||||
|
"uris": [
|
||||||
|
{
|
||||||
|
"uri": "npm:@denotest/cjs-default-export",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "npm:chalk",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
assert!(maybe_res.is_some());
|
||||||
|
|
||||||
|
// check importing a cjs default import
|
||||||
|
client
|
||||||
|
.write_notification(
|
||||||
|
"textDocument/didChange",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"contentChanges": [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text": "cjsDefault."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
read_diagnostics(&mut client);
|
||||||
|
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request(
|
||||||
|
"textDocument/completion",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts"
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 11
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"triggerKind": 2,
|
||||||
|
"triggerCharacter": "."
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
if let Some(lsp::CompletionResponse::List(list)) = maybe_res {
|
||||||
|
assert!(!list.is_incomplete);
|
||||||
|
assert_eq!(list.items.len(), 3);
|
||||||
|
assert!(list.items.iter().any(|i| i.label == "default"));
|
||||||
|
assert!(list.items.iter().any(|i| i.label == "MyClass"));
|
||||||
|
} else {
|
||||||
|
panic!("unexpected response");
|
||||||
|
}
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request(
|
||||||
|
"completionItem/resolve",
|
||||||
|
load_fixture("completions/npm/resolve_params.json"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
assert_eq!(
|
||||||
|
maybe_res,
|
||||||
|
Some(load_fixture("completions/npm/resolve_response.json"))
|
||||||
|
);
|
||||||
|
|
||||||
|
// now check chalk, which is esm
|
||||||
|
client
|
||||||
|
.write_notification(
|
||||||
|
"textDocument/didChange",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"contentChanges": [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text": "chalk."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
read_diagnostics(&mut client);
|
||||||
|
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request(
|
||||||
|
"textDocument/completion",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts"
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 6
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"triggerKind": 2,
|
||||||
|
"triggerCharacter": "."
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
if let Some(lsp::CompletionResponse::List(list)) = maybe_res {
|
||||||
|
assert!(!list.is_incomplete);
|
||||||
|
assert!(list.items.iter().any(|i| i.label == "green"));
|
||||||
|
assert!(list.items.iter().any(|i| i.label == "red"));
|
||||||
|
} else {
|
||||||
|
panic!("unexpected response");
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown(&mut client);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lsp_completions_registry() {
|
fn lsp_completions_registry() {
|
||||||
let _g = http_server();
|
let _g = http_server();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use deno_core::url::Url;
|
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use test_util as util;
|
use test_util as util;
|
||||||
use util::assert_contains;
|
use util::assert_contains;
|
||||||
|
@ -34,7 +33,7 @@ itest!(esm_module_deno_test {
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(esm_import_cjs_default {
|
itest!(esm_import_cjs_default {
|
||||||
args: "run --allow-read --allow-env --unstable --quiet npm/esm_import_cjs_default/main.js",
|
args: "run --allow-read --allow-env --unstable --quiet --check=all npm/esm_import_cjs_default/main.ts",
|
||||||
output: "npm/esm_import_cjs_default/main.out",
|
output: "npm/esm_import_cjs_default/main.out",
|
||||||
envs: env_vars(),
|
envs: env_vars(),
|
||||||
http_server: true,
|
http_server: true,
|
||||||
|
@ -84,7 +83,7 @@ itest!(translate_cjs_to_esm {
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(compare_globals {
|
itest!(compare_globals {
|
||||||
args: "run --allow-read --unstable npm/compare_globals/main.js",
|
args: "run --allow-read --unstable --check=all npm/compare_globals/main.ts",
|
||||||
output: "npm/compare_globals/main.out",
|
output: "npm/compare_globals/main.out",
|
||||||
envs: env_vars(),
|
envs: env_vars(),
|
||||||
http_server: true,
|
http_server: true,
|
||||||
|
@ -210,6 +209,38 @@ itest!(deno_cache {
|
||||||
http_server: true,
|
http_server: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(check_all {
|
||||||
|
args: "check --unstable --remote npm/check_errors/main.ts",
|
||||||
|
output: "npm/check_errors/main_all.out",
|
||||||
|
envs: env_vars(),
|
||||||
|
http_server: true,
|
||||||
|
exit_code: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(check_local {
|
||||||
|
args: "check --unstable npm/check_errors/main.ts",
|
||||||
|
output: "npm/check_errors/main_local.out",
|
||||||
|
envs: env_vars(),
|
||||||
|
http_server: true,
|
||||||
|
exit_code: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(types_ambient_module {
|
||||||
|
args: "check --unstable --quiet npm/types_ambient_module/main.ts",
|
||||||
|
output: "npm/types_ambient_module/main.out",
|
||||||
|
envs: env_vars(),
|
||||||
|
http_server: true,
|
||||||
|
exit_code: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(types_ambient_module_import_map {
|
||||||
|
args: "check --unstable --quiet --import-map=npm/types_ambient_module/import_map.json npm/types_ambient_module/main_import_map.ts",
|
||||||
|
output: "npm/types_ambient_module/main_import_map.out",
|
||||||
|
envs: env_vars(),
|
||||||
|
http_server: true,
|
||||||
|
exit_code: 1,
|
||||||
|
});
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parallel_downloading() {
|
fn parallel_downloading() {
|
||||||
let (out, _err) = util::run_and_collect_output_with_args(
|
let (out, _err) = util::run_and_collect_output_with_args(
|
||||||
|
@ -672,18 +703,10 @@ fn ensure_registry_files_local() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn std_file_url() -> String {
|
|
||||||
let u = Url::from_directory_path(util::std_path()).unwrap();
|
|
||||||
u.to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn env_vars_no_sync_download() -> Vec<(String, String)> {
|
fn env_vars_no_sync_download() -> Vec<(String, String)> {
|
||||||
vec![
|
vec![
|
||||||
("DENO_NODE_COMPAT_URL".to_string(), std_file_url()),
|
("DENO_NODE_COMPAT_URL".to_string(), util::std_file_url()),
|
||||||
(
|
("DENO_NPM_REGISTRY".to_string(), util::npm_registry_url()),
|
||||||
"DENO_NPM_REGISTRY".to_string(),
|
|
||||||
"http://localhost:4545/npm/registry/".to_string(),
|
|
||||||
),
|
|
||||||
("NO_COLOR".to_string(), "1".to_string()),
|
("NO_COLOR".to_string(), "1".to_string()),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
11
cli/tests/testdata/check/npm_install_diagnostics/main.out
vendored
Normal file
11
cli/tests/testdata/check/npm_install_diagnostics/main.out
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
error: TS2581 [ERROR]: Cannot find name '$'. Did you mean to import jQuery? Try adding `import $ from "npm:jquery";`.
|
||||||
|
$;
|
||||||
|
^
|
||||||
|
at file:///[WILDCARD]/npm_install_diagnostics/main.ts:1:1
|
||||||
|
|
||||||
|
TS2580 [ERROR]: Cannot find name 'process'.
|
||||||
|
process;
|
||||||
|
~~~~~~~
|
||||||
|
at file:///[WILDCARD]/npm_install_diagnostics/main.ts:2:1
|
||||||
|
|
||||||
|
Found 2 errors.
|
2
cli/tests/testdata/check/npm_install_diagnostics/main.ts
vendored
Normal file
2
cli/tests/testdata/check/npm_install_diagnostics/main.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
$;
|
||||||
|
process;
|
41
cli/tests/testdata/lsp/code_actions/cache_npm/cache_action.json
vendored
Normal file
41
cli/tests/testdata/lsp/code_actions/cache_npm/cache_action.json
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts"
|
||||||
|
},
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 18
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 29
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"diagnostics": [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 18
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 29
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"severity": 1,
|
||||||
|
"code": "no-cache-npm",
|
||||||
|
"source": "deno",
|
||||||
|
"message": "Uncached or missing npm package: \"chalk\".",
|
||||||
|
"data": {
|
||||||
|
"specifier": "npm:chalk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"only": [
|
||||||
|
"quickfix"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
36
cli/tests/testdata/lsp/code_actions/cache_npm/cache_response.json
vendored
Normal file
36
cli/tests/testdata/lsp/code_actions/cache_npm/cache_response.json
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Cache \"npm:chalk\" and its dependencies.",
|
||||||
|
"kind": "quickfix",
|
||||||
|
"diagnostics": [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 18
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 29
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"severity": 1,
|
||||||
|
"code": "no-cache-npm",
|
||||||
|
"source": "deno",
|
||||||
|
"message": "Uncached or missing npm package: \"chalk\".",
|
||||||
|
"data": {
|
||||||
|
"specifier": "npm:chalk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"command": {
|
||||||
|
"title": "",
|
||||||
|
"command": "deno.cache",
|
||||||
|
"arguments": [
|
||||||
|
[
|
||||||
|
"npm:chalk"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
25
cli/tests/testdata/lsp/code_actions/cache_npm/diagnostics.json
vendored
Normal file
25
cli/tests/testdata/lsp/code_actions/cache_npm/diagnostics.json
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"diagnostics": [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 18
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 29
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"severity": 1,
|
||||||
|
"code": "no-cache-npm",
|
||||||
|
"source": "deno",
|
||||||
|
"message": "Uncached or missing npm package: \"chalk\".",
|
||||||
|
"data": {
|
||||||
|
"specifier": "npm:chalk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 1
|
||||||
|
}
|
14
cli/tests/testdata/lsp/completions/npm/resolve_params.json
vendored
Normal file
14
cli/tests/testdata/lsp/completions/npm/resolve_params.json
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"label": "MyClass",
|
||||||
|
"kind": 6,
|
||||||
|
"sortText": "1",
|
||||||
|
"insertTextFormat": 1,
|
||||||
|
"data": {
|
||||||
|
"tsc": {
|
||||||
|
"specifier": "file:///a/file.ts",
|
||||||
|
"position": 69,
|
||||||
|
"name": "MyClass",
|
||||||
|
"useCodeSnippet": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
cli/tests/testdata/lsp/completions/npm/resolve_response.json
vendored
Normal file
14
cli/tests/testdata/lsp/completions/npm/resolve_response.json
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"label": "MyClass",
|
||||||
|
"kind": 6,
|
||||||
|
"sortText": "1",
|
||||||
|
"insertTextFormat": 1,
|
||||||
|
"data": {
|
||||||
|
"tsc": {
|
||||||
|
"specifier": "file:///a/file.ts",
|
||||||
|
"position": 69,
|
||||||
|
"name": "MyClass",
|
||||||
|
"useCodeSnippet": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
cli/tests/testdata/npm/check_errors/main.ts
vendored
Normal file
3
cli/tests/testdata/npm/check_errors/main.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import * as test from "npm:@denotest/check-error";
|
||||||
|
|
||||||
|
console.log(test.Asdf); // should error
|
19
cli/tests/testdata/npm/check_errors/main_all.out
vendored
Normal file
19
cli/tests/testdata/npm/check_errors/main_all.out
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Download http://localhost:4545/npm/registry/@denotest/check-error
|
||||||
|
Download http://localhost:4545/npm/registry/@denotest/check-error/1.0.0.tgz
|
||||||
|
Check file:///[WILDCARD]/check_errors/main.ts
|
||||||
|
error: TS2506 [ERROR]: 'Class1' is referenced directly or indirectly in its own base expression.
|
||||||
|
export class Class1 extends Class2 {
|
||||||
|
~~~~~~
|
||||||
|
at file:///[WILDCARD]/check-error/1.0.0/index.d.ts:2:14
|
||||||
|
|
||||||
|
TS2506 [ERROR]: 'Class2' is referenced directly or indirectly in its own base expression.
|
||||||
|
export class Class2 extends Class1 {
|
||||||
|
~~~~~~
|
||||||
|
at file:///[WILDCARD]/check-error/1.0.0/index.d.ts:5:14
|
||||||
|
|
||||||
|
TS2339 [ERROR]: Property 'Asdf' does not exist on type 'typeof import("file:///[WILDCARD]/@denotest/check-error/1.0.0/index.d.ts")'.
|
||||||
|
console.log(test.Asdf); // should error
|
||||||
|
~~~~
|
||||||
|
at file:///[WILDCARD]/check_errors/main.ts:3:18
|
||||||
|
|
||||||
|
Found 3 errors.
|
7
cli/tests/testdata/npm/check_errors/main_local.out
vendored
Normal file
7
cli/tests/testdata/npm/check_errors/main_local.out
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Download http://localhost:4545/npm/registry/@denotest/check-error
|
||||||
|
Download http://localhost:4545/npm/registry/@denotest/check-error/1.0.0.tgz
|
||||||
|
Check file:///[WILDCARD]/check_errors/main.ts
|
||||||
|
error: TS2339 [ERROR]: Property 'Asdf' does not exist on type 'typeof import("file:///[WILDCARD]/@denotest/check-error/1.0.0/index.d.ts")'.
|
||||||
|
console.log(test.Asdf); // should error
|
||||||
|
~~~~
|
||||||
|
at file:///[WILDCARD]/npm/check_errors/main.ts:3:18
|
|
@ -1,2 +0,0 @@
|
||||||
import * as globals from "npm:@denotest/globals";
|
|
||||||
console.log(globals.global === globals.globalThis);
|
|
|
@ -1,3 +1,8 @@
|
||||||
Download http://localhost:4545/npm/registry/@denotest/globals
|
Download http://localhost:4545/npm/registry/@denotest/globals
|
||||||
|
Download http://localhost:4545/npm/registry/@types/node
|
||||||
Download http://localhost:4545/npm/registry/@denotest/globals/1.0.0.tgz
|
Download http://localhost:4545/npm/registry/@denotest/globals/1.0.0.tgz
|
||||||
|
Download http://localhost:4545/npm/registry/@types/node/node-18.8.2.tgz
|
||||||
|
Check file:///[WILDCARD]/npm/compare_globals/main.ts
|
||||||
|
Check file:///[WILDCARD]/std/node/module_all.ts
|
||||||
true
|
true
|
||||||
|
[]
|
||||||
|
|
14
cli/tests/testdata/npm/compare_globals/main.ts
vendored
Normal file
14
cli/tests/testdata/npm/compare_globals/main.ts
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/// <reference types="npm:@types/node" />
|
||||||
|
|
||||||
|
import * as globals from "npm:@denotest/globals";
|
||||||
|
console.log(globals.global === globals.globalThis);
|
||||||
|
console.log(globals.process.execArgv);
|
||||||
|
|
||||||
|
type AssertTrue<T extends true> = never;
|
||||||
|
type _TestNoProcessGlobal = AssertTrue<
|
||||||
|
typeof globalThis extends { process: any } ? false : true
|
||||||
|
>;
|
||||||
|
type _TestHasNodeJsGlobal = NodeJS.Architecture;
|
||||||
|
|
||||||
|
const controller = new AbortController();
|
||||||
|
controller.abort("reason"); // in the NodeJS declaration it doesn't have a reason
|
|
@ -1,3 +1,4 @@
|
||||||
|
// @ts-check
|
||||||
import cjsDefault, {
|
import cjsDefault, {
|
||||||
MyClass as MyCjsClass,
|
MyClass as MyCjsClass,
|
||||||
} from "npm:@denotest/cjs-default-export";
|
} from "npm:@denotest/cjs-default-export";
|
6
cli/tests/testdata/npm/registry/@denotest/check-error/1.0.0/index.d.ts
vendored
Normal file
6
cli/tests/testdata/npm/registry/@denotest/check-error/1.0.0/index.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// intentional type checking errors
|
||||||
|
export class Class1 extends Class2 {
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Class2 extends Class1 {
|
||||||
|
}
|
6
cli/tests/testdata/npm/registry/@denotest/check-error/1.0.0/index.js
vendored
Normal file
6
cli/tests/testdata/npm/registry/@denotest/check-error/1.0.0/index.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
Class1: class {
|
||||||
|
},
|
||||||
|
Class2: class {
|
||||||
|
},
|
||||||
|
};
|
5
cli/tests/testdata/npm/registry/@denotest/check-error/1.0.0/package.json
vendored
Normal file
5
cli/tests/testdata/npm/registry/@denotest/check-error/1.0.0/package.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name": "@denotest/check-error",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"types": "./index.d.ts"
|
||||||
|
}
|
6
cli/tests/testdata/npm/registry/@denotest/cjs-default-export/1.0.0/index.d.ts
vendored
Normal file
6
cli/tests/testdata/npm/registry/@denotest/cjs-default-export/1.0.0/index.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export default function (): number;
|
||||||
|
export declare function named(): number;
|
||||||
|
declare class MyClass {
|
||||||
|
static someStaticMethod(): string;
|
||||||
|
}
|
||||||
|
export { MyClass };
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@denotest/cjs-default-export",
|
"name": "@denotest/cjs-default-export",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0",
|
||||||
|
"types": "./index.d.ts"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@denotest/esm-import-cjs-default",
|
"name": "@denotest/esm-import-cjs-default",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"main": "index.mjs",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@denotest/cjs-default-export": "^1.0.0"
|
"@denotest/cjs-default-export": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
|
13
cli/tests/testdata/npm/registry/@denotest/globals/1.0.0/index.d.ts
vendored
Normal file
13
cli/tests/testdata/npm/registry/@denotest/globals/1.0.0/index.d.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
declare const tempGlobalThis: typeof globalThis;
|
||||||
|
declare const tempGlobal: typeof global;
|
||||||
|
declare const tempProcess: typeof process;
|
||||||
|
export {
|
||||||
|
tempGlobalThis as globalThis,
|
||||||
|
tempGlobal as global,
|
||||||
|
tempProcess as process,
|
||||||
|
};
|
||||||
|
|
||||||
|
type AssertTrue<T extends true> = never;
|
||||||
|
type _TestHasProcessGlobal = AssertTrue<
|
||||||
|
typeof globalThis extends { process: any } ? true : false
|
||||||
|
>;
|
|
@ -1,2 +1,3 @@
|
||||||
exports.globalThis = globalThis;
|
exports.globalThis = globalThis;
|
||||||
exports.global = global;
|
exports.global = global;
|
||||||
|
exports.process = process;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@denotest/globals",
|
"name": "@denotest/globals",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0",
|
||||||
|
"types": "index.d.ts"
|
||||||
}
|
}
|
||||||
|
|
10
cli/tests/testdata/npm/registry/@denotest/types-ambient/1.0.0/index.d.ts
vendored
Normal file
10
cli/tests/testdata/npm/registry/@denotest/types-ambient/1.0.0/index.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Some packages do this. It's really not ideal because instead of allowing
|
||||||
|
// the package to be resolved at any specifier, it instead expects the package
|
||||||
|
// to be resolved via a "@denotest/types-ambient" specifier. To make this work,
|
||||||
|
// we've currently modified the typescript compiler to check for any "<package-name>"
|
||||||
|
// ambient modules when resolving an npm specifier at "npm:<package-name>"
|
||||||
|
declare module "@denotest/types-ambient" {
|
||||||
|
class Test {
|
||||||
|
prop: number;
|
||||||
|
}
|
||||||
|
}
|
3
cli/tests/testdata/npm/registry/@denotest/types-ambient/1.0.0/index.js
vendored
Normal file
3
cli/tests/testdata/npm/registry/@denotest/types-ambient/1.0.0/index.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export class Test {
|
||||||
|
prop = 5;
|
||||||
|
}
|
5
cli/tests/testdata/npm/registry/@denotest/types-ambient/1.0.0/package.json
vendored
Normal file
5
cli/tests/testdata/npm/registry/@denotest/types-ambient/1.0.0/package.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name": "@denotest/types-ambient",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"types": "./index.d.ts"
|
||||||
|
}
|
BIN
cli/tests/testdata/npm/registry/@types/node/node-18.8.2.tgz
vendored
Normal file
BIN
cli/tests/testdata/npm/registry/@types/node/node-18.8.2.tgz
vendored
Normal file
Binary file not shown.
73
cli/tests/testdata/npm/registry/@types/node/registry.json
vendored
Normal file
73
cli/tests/testdata/npm/registry/@types/node/registry.json
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"_id": "@types/node",
|
||||||
|
"_rev": "8944-025a921c7561ec7339c70b87995cb358",
|
||||||
|
"name": "@types/node",
|
||||||
|
"description": "TypeScript definitions for Node.js",
|
||||||
|
"dist-tags": {
|
||||||
|
"latest": "18.8.2"
|
||||||
|
},
|
||||||
|
"versions": {
|
||||||
|
"18.8.2": {
|
||||||
|
"name": "@types/node",
|
||||||
|
"version": "18.8.2",
|
||||||
|
"description": "TypeScript definitions for Node.js",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"typesVersions": { "<4.9.0-0": { "*": ["ts4.8/*"] } },
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/node"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {},
|
||||||
|
"typesPublisherContentHash": "034172ea945b66afc6502e6be34d6fb957c596091e39cf43672e8aca563a8c66",
|
||||||
|
"typeScriptVersion": "4.1",
|
||||||
|
"_id": "@types/node@18.8.2",
|
||||||
|
"dist": {
|
||||||
|
"integrity": "sha512-cRMwIgdDN43GO4xMWAfJAecYn8wV4JbsOGHNfNUIDiuYkUYAR5ec4Rj7IO2SAhFPEfpPtLtUTbbny/TCT7aDwA==",
|
||||||
|
"shasum": "17d42c6322d917764dd3d2d3a10d7884925de067",
|
||||||
|
"tarball": "http://localhost:4545/npm/registry/@types/node/node-18.8.2.tgz",
|
||||||
|
"fileCount": 124,
|
||||||
|
"unpackedSize": 3524549,
|
||||||
|
"signatures": [
|
||||||
|
{
|
||||||
|
"keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
|
||||||
|
"sig": "MEYCIQCAqI3XibndhBD647C/13AFb58Fhmg4WmfCoGrIYrgtzwIhAIB0b0D58Tigwb3qKaOVsKnuYOOr0strAmprZSCi/+oq"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjPFItACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrKAg/+IwaUWPgePlO4IxW7CVhFEEFiyhjEH3FHe0ogC3YmreoBFv/A\r\nPwQrwObdskbGWrBzsAOVFvhzYktzP3kc857HtU2ia9FXeaEYvsSQBqh6jZfA\r\njR1+h+jn+W5JnmbnwRGfNn2riCo/un4tYoZ4o/bKiMdNd9WrdIs0Oii1Dd4N\r\nnsBXPb05UPPP4Uu8cz68u1bj+QQ6aslr6keGNyNeILf8bJsEfcfVkEO3l4cu\r\njyTIrxiD+tM8jrUE9CDeodF8CZNuvLh3hqdMPJeH3U47qkDtPDKEOvZTbyYm\r\ngodto6mcnuBr8F9vmikAQfGiXV0U2cg2XRjWc1lI8HT4X0kESTIo+nzNuliD\r\niTpfjyZHdKBGGIuHP1Ou9dVvx4t5XZ1JsK9EK5WTilvAlu/qZrynxXxAV3Rc\r\nvL9UhIacISprMWB3Sohl9ZtfcmGnV/KMRpM+yPZOWp39gQQCKaKF/j2f/mir\r\n8YFbFUnySZkXKzxgsgjrSsh9QiK2dYAzcqHlazITeFN9jOYRzYUjAFj3qOFm\r\n7o1eJpW0qM5vgR+fPq30WxcdcQ4PaWgHSlb/ll8hiwQG1ZUihO/1RU7FtDoc\r\n1KwcfrGOAJPL6vBSLPReUkhDIUTSBwfmvfMxzqD1aDp6YV5WX7h03B0dWbPJ\r\nmPJmJZjjZje4Trk9jBJ5/ZLpB8/zkrDKvhE=\r\n=LPWa\r\n-----END PGP SIGNATURE-----\r\n"
|
||||||
|
},
|
||||||
|
"_npmUser": { "name": "types", "email": "ts-npm-types@microsoft.com" },
|
||||||
|
"directories": {},
|
||||||
|
"maintainers": [
|
||||||
|
{ "name": "types", "email": "ts-npm-types@microsoft.com" }
|
||||||
|
],
|
||||||
|
"_npmOperationalInternal": {
|
||||||
|
"host": "s3://npm-registry-packages",
|
||||||
|
"tmp": "tmp/node_18.8.2_1664897581729_0.9746861340465625"
|
||||||
|
},
|
||||||
|
"_hasShrinkwrap": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readme": "[object Object]",
|
||||||
|
"maintainers": [{ "name": "types", "email": "ts-npm-types@microsoft.com" }],
|
||||||
|
"time": {
|
||||||
|
"18.8.2": "2022-10-04T15:33:01.913Z"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"readmeFilename": "",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/node"
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
},
|
||||||
|
"contributors": [],
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node"
|
||||||
|
}
|
5
cli/tests/testdata/npm/types_ambient_module/import_map.json
vendored
Normal file
5
cli/tests/testdata/npm/types_ambient_module/import_map.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"types-ambient": "npm:@denotest/types-ambient"
|
||||||
|
}
|
||||||
|
}
|
21
cli/tests/testdata/npm/types_ambient_module/main.out
vendored
Normal file
21
cli/tests/testdata/npm/types_ambient_module/main.out
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
error: TS2551 [ERROR]: Property 'Test2' does not exist on type 'typeof import("@denotest/types-ambient")'. Did you mean 'Test'?
|
||||||
|
console.log(import1.Test2); // should error
|
||||||
|
~~~~~
|
||||||
|
at file:///[WILDCARD]/types_ambient_module/main.ts:5:21
|
||||||
|
|
||||||
|
'Test' is declared here.
|
||||||
|
class Test {
|
||||||
|
~~~~
|
||||||
|
at file:///[WILDCARD]/@denotest/types-ambient/1.0.0/index.d.ts:7:9
|
||||||
|
|
||||||
|
TS2551 [ERROR]: Property 'Test2' does not exist on type 'typeof import("@denotest/types-ambient")'. Did you mean 'Test'?
|
||||||
|
console.log(import2.Test2); // should error
|
||||||
|
~~~~~
|
||||||
|
at file:///[WILDCARD]/types_ambient_module/main.ts:7:21
|
||||||
|
|
||||||
|
'Test' is declared here.
|
||||||
|
class Test {
|
||||||
|
~~~~
|
||||||
|
at file:///[WILDCARD]/@denotest/types-ambient/1.0.0/index.d.ts:7:9
|
||||||
|
|
||||||
|
Found 2 errors.
|
7
cli/tests/testdata/npm/types_ambient_module/main.ts
vendored
Normal file
7
cli/tests/testdata/npm/types_ambient_module/main.ts
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import * as import1 from "npm:@denotest/types-ambient";
|
||||||
|
import * as import2 from "npm:@denotest/types-ambient@1";
|
||||||
|
|
||||||
|
console.log(import1.Test);
|
||||||
|
console.log(import1.Test2); // should error
|
||||||
|
console.log(import2.Test);
|
||||||
|
console.log(import2.Test2); // should error
|
9
cli/tests/testdata/npm/types_ambient_module/main_import_map.out
vendored
Normal file
9
cli/tests/testdata/npm/types_ambient_module/main_import_map.out
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error: TS2551 [ERROR]: Property 'Test2' does not exist on type 'typeof import("@denotest/types-ambient")'. Did you mean 'Test'?
|
||||||
|
console.log(mod.Test2); // should error
|
||||||
|
~~~~~
|
||||||
|
at file:///[WILDCARD]/main_import_map.ts:4:17
|
||||||
|
|
||||||
|
'Test' is declared here.
|
||||||
|
class Test {
|
||||||
|
~~~~
|
||||||
|
at file:///[WILDCARD]/@denotest/types-ambient/1.0.0/index.d.ts:7:9
|
4
cli/tests/testdata/npm/types_ambient_module/main_import_map.ts
vendored
Normal file
4
cli/tests/testdata/npm/types_ambient_module/main_import_map.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import * as mod from "npm:@denotest/types-ambient";
|
||||||
|
|
||||||
|
console.log(mod.Test);
|
||||||
|
console.log(mod.Test2); // should error
|
|
@ -18,6 +18,7 @@ use crate::cache::TypeCheckCache;
|
||||||
use crate::diagnostics::Diagnostics;
|
use crate::diagnostics::Diagnostics;
|
||||||
use crate::graph_util::GraphData;
|
use crate::graph_util::GraphData;
|
||||||
use crate::graph_util::ModuleEntry;
|
use crate::graph_util::ModuleEntry;
|
||||||
|
use crate::npm::NpmPackageResolver;
|
||||||
use crate::tsc;
|
use crate::tsc;
|
||||||
use crate::tsc::Stats;
|
use crate::tsc::Stats;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
|
@ -57,6 +58,7 @@ pub fn check(
|
||||||
roots: &[(ModuleSpecifier, ModuleKind)],
|
roots: &[(ModuleSpecifier, ModuleKind)],
|
||||||
graph_data: Arc<RwLock<GraphData>>,
|
graph_data: Arc<RwLock<GraphData>>,
|
||||||
cache: &TypeCheckCache,
|
cache: &TypeCheckCache,
|
||||||
|
npm_resolver: NpmPackageResolver,
|
||||||
options: CheckOptions,
|
options: CheckOptions,
|
||||||
) -> Result<CheckResult, AnyError> {
|
) -> Result<CheckResult, AnyError> {
|
||||||
let check_js = options.ts_config.get_check_js();
|
let check_js = options.ts_config.get_check_js();
|
||||||
|
@ -106,6 +108,7 @@ pub fn check(
|
||||||
graph_data,
|
graph_data,
|
||||||
hash_data,
|
hash_data,
|
||||||
maybe_config_specifier: options.maybe_config_specifier,
|
maybe_config_specifier: options.maybe_config_specifier,
|
||||||
|
maybe_npm_resolver: Some(npm_resolver.clone()),
|
||||||
maybe_tsbuildinfo,
|
maybe_tsbuildinfo,
|
||||||
root_names,
|
root_names,
|
||||||
})?;
|
})?;
|
||||||
|
@ -114,6 +117,9 @@ pub fn check(
|
||||||
response.diagnostics.filter(|d| {
|
response.diagnostics.filter(|d| {
|
||||||
if let Some(file_name) = &d.file_name {
|
if let Some(file_name) = &d.file_name {
|
||||||
!file_name.starts_with("http")
|
!file_name.starts_with("http")
|
||||||
|
&& ModuleSpecifier::parse(file_name)
|
||||||
|
.map(|specifier| !npm_resolver.in_npm_package(&specifier))
|
||||||
|
.unwrap_or(true)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
132
cli/tsc.rs
132
cli/tsc.rs
|
@ -4,6 +4,12 @@ use crate::args::TsConfig;
|
||||||
use crate::diagnostics::Diagnostics;
|
use crate::diagnostics::Diagnostics;
|
||||||
use crate::graph_util::GraphData;
|
use crate::graph_util::GraphData;
|
||||||
use crate::graph_util::ModuleEntry;
|
use crate::graph_util::ModuleEntry;
|
||||||
|
use crate::node;
|
||||||
|
use crate::node::node_resolve_npm_reference;
|
||||||
|
use crate::node::NodeResolution;
|
||||||
|
use crate::node::NodeResolutionMode;
|
||||||
|
use crate::npm::NpmPackageReference;
|
||||||
|
use crate::npm::NpmPackageResolver;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
|
@ -28,6 +34,7 @@ use deno_core::RuntimeOptions;
|
||||||
use deno_core::Snapshot;
|
use deno_core::Snapshot;
|
||||||
use deno_graph::Resolved;
|
use deno_graph::Resolved;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -171,7 +178,7 @@ fn get_maybe_hash(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hash the URL so it can be sent to `tsc` in a supportable way
|
/// Hash the URL so it can be sent to `tsc` in a supportable way
|
||||||
fn hash_url(specifier: &ModuleSpecifier, media_type: &MediaType) -> String {
|
fn hash_url(specifier: &ModuleSpecifier, media_type: MediaType) -> String {
|
||||||
let hash = crate::checksum::gen(&[specifier.path().as_bytes()]);
|
let hash = crate::checksum::gen(&[specifier.path().as_bytes()]);
|
||||||
format!(
|
format!(
|
||||||
"{}:///{}{}",
|
"{}:///{}{}",
|
||||||
|
@ -187,7 +194,7 @@ fn hash_url(specifier: &ModuleSpecifier, media_type: &MediaType) -> String {
|
||||||
/// think a `.js` version exists, when it doesn't.
|
/// think a `.js` version exists, when it doesn't.
|
||||||
fn maybe_remap_specifier(
|
fn maybe_remap_specifier(
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
media_type: &MediaType,
|
media_type: MediaType,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
let path = if specifier.scheme() == "file" {
|
let path = if specifier.scheme() == "file" {
|
||||||
if let Ok(path) = specifier.to_file_path() {
|
if let Ok(path) = specifier.to_file_path() {
|
||||||
|
@ -279,6 +286,7 @@ pub struct Request {
|
||||||
pub graph_data: Arc<RwLock<GraphData>>,
|
pub graph_data: Arc<RwLock<GraphData>>,
|
||||||
pub hash_data: Vec<Vec<u8>>,
|
pub hash_data: Vec<Vec<u8>>,
|
||||||
pub maybe_config_specifier: Option<ModuleSpecifier>,
|
pub maybe_config_specifier: Option<ModuleSpecifier>,
|
||||||
|
pub maybe_npm_resolver: Option<NpmPackageResolver>,
|
||||||
pub maybe_tsbuildinfo: Option<String>,
|
pub maybe_tsbuildinfo: Option<String>,
|
||||||
/// A vector of strings that represent the root/entry point modules for the
|
/// A vector of strings that represent the root/entry point modules for the
|
||||||
/// program.
|
/// program.
|
||||||
|
@ -295,13 +303,14 @@ pub struct Response {
|
||||||
pub stats: Stats,
|
pub stats: Stats,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
struct State {
|
struct State {
|
||||||
hash_data: Vec<Vec<u8>>,
|
hash_data: Vec<Vec<u8>>,
|
||||||
graph_data: Arc<RwLock<GraphData>>,
|
graph_data: Arc<RwLock<GraphData>>,
|
||||||
maybe_config_specifier: Option<ModuleSpecifier>,
|
maybe_config_specifier: Option<ModuleSpecifier>,
|
||||||
maybe_tsbuildinfo: Option<String>,
|
maybe_tsbuildinfo: Option<String>,
|
||||||
maybe_response: Option<RespondArgs>,
|
maybe_response: Option<RespondArgs>,
|
||||||
|
maybe_npm_resolver: Option<NpmPackageResolver>,
|
||||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||||
root_map: HashMap<String, ModuleSpecifier>,
|
root_map: HashMap<String, ModuleSpecifier>,
|
||||||
}
|
}
|
||||||
|
@ -311,6 +320,7 @@ impl State {
|
||||||
graph_data: Arc<RwLock<GraphData>>,
|
graph_data: Arc<RwLock<GraphData>>,
|
||||||
hash_data: Vec<Vec<u8>>,
|
hash_data: Vec<Vec<u8>>,
|
||||||
maybe_config_specifier: Option<ModuleSpecifier>,
|
maybe_config_specifier: Option<ModuleSpecifier>,
|
||||||
|
maybe_npm_resolver: Option<NpmPackageResolver>,
|
||||||
maybe_tsbuildinfo: Option<String>,
|
maybe_tsbuildinfo: Option<String>,
|
||||||
root_map: HashMap<String, ModuleSpecifier>,
|
root_map: HashMap<String, ModuleSpecifier>,
|
||||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||||
|
@ -319,6 +329,7 @@ impl State {
|
||||||
hash_data,
|
hash_data,
|
||||||
graph_data,
|
graph_data,
|
||||||
maybe_config_specifier,
|
maybe_config_specifier,
|
||||||
|
maybe_npm_resolver,
|
||||||
maybe_tsbuildinfo,
|
maybe_tsbuildinfo,
|
||||||
maybe_response: None,
|
maybe_response: None,
|
||||||
remapped_specifiers,
|
remapped_specifiers,
|
||||||
|
@ -417,7 +428,7 @@ struct LoadArgs {
|
||||||
specifier: String,
|
specifier: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_ts_script_kind(media_type: &MediaType) -> i32 {
|
pub fn as_ts_script_kind(media_type: MediaType) -> i32 {
|
||||||
match media_type {
|
match media_type {
|
||||||
MediaType::JavaScript => 1,
|
MediaType::JavaScript => 1,
|
||||||
MediaType::Jsx => 2,
|
MediaType::Jsx => 2,
|
||||||
|
@ -431,7 +442,10 @@ pub fn as_ts_script_kind(media_type: &MediaType) -> i32 {
|
||||||
MediaType::Dcts => 3,
|
MediaType::Dcts => 3,
|
||||||
MediaType::Tsx => 4,
|
MediaType::Tsx => 4,
|
||||||
MediaType::Json => 6,
|
MediaType::Json => 6,
|
||||||
_ => 0,
|
MediaType::SourceMap
|
||||||
|
| MediaType::TsBuildInfo
|
||||||
|
| MediaType::Wasm
|
||||||
|
| MediaType::Unknown => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,19 +460,19 @@ fn op_load(state: &mut OpState, args: Value) -> Result<Value, AnyError> {
|
||||||
let mut media_type = MediaType::Unknown;
|
let mut media_type = MediaType::Unknown;
|
||||||
let graph_data = state.graph_data.read();
|
let graph_data = state.graph_data.read();
|
||||||
let data = if &v.specifier == "deno:///.tsbuildinfo" {
|
let data = if &v.specifier == "deno:///.tsbuildinfo" {
|
||||||
state.maybe_tsbuildinfo.as_deref()
|
state.maybe_tsbuildinfo.as_deref().map(Cow::Borrowed)
|
||||||
// in certain situations we return a "blank" module to tsc and we need to
|
// in certain situations we return a "blank" module to tsc and we need to
|
||||||
// handle the request for that module here.
|
// handle the request for that module here.
|
||||||
} else if &v.specifier == "deno:///missing_dependency.d.ts" {
|
} else if &v.specifier == "deno:///missing_dependency.d.ts" {
|
||||||
hash = Some("1".to_string());
|
hash = Some("1".to_string());
|
||||||
media_type = MediaType::Dts;
|
media_type = MediaType::Dts;
|
||||||
Some("declare const __: any;\nexport = __;\n")
|
Some(Cow::Borrowed("declare const __: any;\nexport = __;\n"))
|
||||||
} else if v.specifier.starts_with("asset:///") {
|
} else if v.specifier.starts_with("asset:///") {
|
||||||
let name = v.specifier.replace("asset:///", "");
|
let name = v.specifier.replace("asset:///", "");
|
||||||
let maybe_source = get_asset(&name);
|
let maybe_source = get_asset(&name);
|
||||||
hash = get_maybe_hash(maybe_source, &state.hash_data);
|
hash = get_maybe_hash(maybe_source, &state.hash_data);
|
||||||
media_type = MediaType::from(&v.specifier);
|
media_type = MediaType::from(&v.specifier);
|
||||||
maybe_source
|
maybe_source.map(Cow::Borrowed)
|
||||||
} else {
|
} else {
|
||||||
let specifier = if let Some(remapped_specifier) =
|
let specifier = if let Some(remapped_specifier) =
|
||||||
state.remapped_specifiers.get(&v.specifier)
|
state.remapped_specifiers.get(&v.specifier)
|
||||||
|
@ -477,18 +491,31 @@ fn op_load(state: &mut OpState, args: Value) -> Result<Value, AnyError> {
|
||||||
graph_data.get(&graph_data.follow_redirect(&specifier))
|
graph_data.get(&graph_data.follow_redirect(&specifier))
|
||||||
{
|
{
|
||||||
media_type = *mt;
|
media_type = *mt;
|
||||||
Some(code as &str)
|
Some(Cow::Borrowed(code as &str))
|
||||||
|
} else if state
|
||||||
|
.maybe_npm_resolver
|
||||||
|
.as_ref()
|
||||||
|
.map(|resolver| resolver.in_npm_package(&specifier))
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
media_type = MediaType::from(&specifier);
|
||||||
|
let file_path = specifier.to_file_path().unwrap();
|
||||||
|
let code = std::fs::read_to_string(&file_path)
|
||||||
|
.with_context(|| format!("Unable to load {}", file_path.display()))?;
|
||||||
|
Some(Cow::Owned(code))
|
||||||
} else {
|
} else {
|
||||||
media_type = MediaType::Unknown;
|
media_type = MediaType::Unknown;
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
hash = get_maybe_hash(maybe_source, &state.hash_data);
|
hash = get_maybe_hash(maybe_source.as_deref(), &state.hash_data);
|
||||||
maybe_source
|
maybe_source
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(
|
Ok(json!({
|
||||||
json!({ "data": data, "version": hash, "scriptKind": as_ts_script_kind(&media_type) }),
|
"data": data,
|
||||||
)
|
"version": hash,
|
||||||
|
"scriptKind": as_ts_script_kind(media_type),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
@ -550,17 +577,51 @@ fn op_resolve(
|
||||||
let types = graph_data.follow_redirect(specifier);
|
let types = graph_data.follow_redirect(specifier);
|
||||||
match graph_data.get(&types) {
|
match graph_data.get(&types) {
|
||||||
Some(ModuleEntry::Module { media_type, .. }) => {
|
Some(ModuleEntry::Module { media_type, .. }) => {
|
||||||
Some((types, media_type))
|
Some((types, *media_type))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Some((specifier, media_type)),
|
_ => Some((specifier, *media_type)),
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => {
|
||||||
|
// handle npm:<package> urls
|
||||||
|
if let Ok(npm_ref) =
|
||||||
|
NpmPackageReference::from_specifier(&specifier)
|
||||||
|
{
|
||||||
|
if let Some(npm_resolver) = &state.maybe_npm_resolver {
|
||||||
|
Some(resolve_npm_package_reference_types(
|
||||||
|
&npm_ref,
|
||||||
|
npm_resolver,
|
||||||
|
)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => {
|
||||||
|
state.maybe_npm_resolver.as_ref().and_then(|npm_resolver| {
|
||||||
|
if npm_resolver.in_npm_package(&referrer) {
|
||||||
|
// we're in an npm package, so use node resolution
|
||||||
|
Some(NodeResolution::into_specifier_and_media_type(
|
||||||
|
node::node_resolve(
|
||||||
|
specifier,
|
||||||
|
&referrer,
|
||||||
|
node::NodeResolutionMode::Types,
|
||||||
|
npm_resolver,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.flatten(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let result = match maybe_result {
|
let result = match maybe_result {
|
||||||
Some((specifier, media_type)) => {
|
Some((specifier, media_type)) => {
|
||||||
|
@ -599,6 +660,33 @@ fn op_resolve(
|
||||||
Ok(resolved)
|
Ok(resolved)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_npm_package_reference_types(
|
||||||
|
npm_ref: &NpmPackageReference,
|
||||||
|
npm_resolver: &NpmPackageResolver,
|
||||||
|
) -> Result<(ModuleSpecifier, MediaType), AnyError> {
|
||||||
|
let maybe_resolution = node_resolve_npm_reference(
|
||||||
|
npm_ref,
|
||||||
|
NodeResolutionMode::Types,
|
||||||
|
npm_resolver,
|
||||||
|
)?;
|
||||||
|
Ok(NodeResolution::into_specifier_and_media_type(
|
||||||
|
maybe_resolution,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_is_node_file(state: &mut OpState, path: String) -> bool {
|
||||||
|
let state = state.borrow::<State>();
|
||||||
|
match ModuleSpecifier::parse(&path) {
|
||||||
|
Ok(specifier) => state
|
||||||
|
.maybe_npm_resolver
|
||||||
|
.as_ref()
|
||||||
|
.map(|r| r.in_npm_package(&specifier))
|
||||||
|
.unwrap_or(false),
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Deserialize, Eq, PartialEq)]
|
||||||
struct RespondArgs {
|
struct RespondArgs {
|
||||||
pub diagnostics: Diagnostics,
|
pub diagnostics: Diagnostics,
|
||||||
|
@ -629,13 +717,13 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(s, mt)| match s.scheme() {
|
.map(|(s, mt)| match s.scheme() {
|
||||||
"data" | "blob" => {
|
"data" | "blob" => {
|
||||||
let specifier_str = hash_url(s, mt);
|
let specifier_str = hash_url(s, *mt);
|
||||||
remapped_specifiers.insert(specifier_str.clone(), s.clone());
|
remapped_specifiers.insert(specifier_str.clone(), s.clone());
|
||||||
specifier_str
|
specifier_str
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let ext_media_type = get_tsc_media_type(s);
|
let ext_media_type = get_tsc_media_type(s);
|
||||||
if mt != &ext_media_type {
|
if *mt != ext_media_type {
|
||||||
let new_specifier = format!("{}{}", s, mt.as_ts_extension());
|
let new_specifier = format!("{}{}", s, mt.as_ts_extension());
|
||||||
root_map.insert(new_specifier.clone(), s.clone());
|
root_map.insert(new_specifier.clone(), s.clone());
|
||||||
new_specifier
|
new_specifier
|
||||||
|
@ -653,6 +741,7 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
|
||||||
op_create_hash::decl(),
|
op_create_hash::decl(),
|
||||||
op_emit::decl(),
|
op_emit::decl(),
|
||||||
op_exists::decl(),
|
op_exists::decl(),
|
||||||
|
op_is_node_file::decl(),
|
||||||
op_load::decl(),
|
op_load::decl(),
|
||||||
op_resolve::decl(),
|
op_resolve::decl(),
|
||||||
op_respond::decl(),
|
op_respond::decl(),
|
||||||
|
@ -662,6 +751,7 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
|
||||||
request.graph_data.clone(),
|
request.graph_data.clone(),
|
||||||
request.hash_data.clone(),
|
request.hash_data.clone(),
|
||||||
request.maybe_config_specifier.clone(),
|
request.maybe_config_specifier.clone(),
|
||||||
|
request.maybe_npm_resolver.clone(),
|
||||||
request.maybe_tsbuildinfo.clone(),
|
request.maybe_tsbuildinfo.clone(),
|
||||||
root_map.clone(),
|
root_map.clone(),
|
||||||
remapped_specifiers.clone(),
|
remapped_specifiers.clone(),
|
||||||
|
@ -771,6 +861,7 @@ mod tests {
|
||||||
Arc::new(RwLock::new((&graph).into())),
|
Arc::new(RwLock::new((&graph).into())),
|
||||||
hash_data,
|
hash_data,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
maybe_tsbuildinfo,
|
maybe_tsbuildinfo,
|
||||||
HashMap::new(),
|
HashMap::new(),
|
||||||
HashMap::new(),
|
HashMap::new(),
|
||||||
|
@ -820,6 +911,7 @@ mod tests {
|
||||||
graph_data: Arc::new(RwLock::new((&graph).into())),
|
graph_data: Arc::new(RwLock::new((&graph).into())),
|
||||||
hash_data,
|
hash_data,
|
||||||
maybe_config_specifier: None,
|
maybe_config_specifier: None,
|
||||||
|
maybe_npm_resolver: None,
|
||||||
maybe_tsbuildinfo: None,
|
maybe_tsbuildinfo: None,
|
||||||
root_names: vec![(specifier.clone(), MediaType::TypeScript)],
|
root_names: vec![(specifier.clone(), MediaType::TypeScript)],
|
||||||
};
|
};
|
||||||
|
@ -865,7 +957,7 @@ mod tests {
|
||||||
"data:application/javascript,console.log(\"Hello%20Deno\");",
|
"data:application/javascript,console.log(\"Hello%20Deno\");",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(hash_url(&specifier, &MediaType::JavaScript), "data:///d300ea0796bd72b08df10348e0b70514c021f2e45bfe59cec24e12e97cd79c58.js");
|
assert_eq!(hash_url(&specifier, MediaType::JavaScript), "data:///d300ea0796bd72b08df10348e0b70514c021f2e45bfe59cec24e12e97cd79c58.js");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
384
cli/tsc/00_typescript.js
vendored
384
cli/tsc/00_typescript.js
vendored
|
@ -48949,12 +48949,23 @@ var ts;
|
||||||
var emitResolver = createResolver();
|
var emitResolver = createResolver();
|
||||||
var nodeBuilder = createNodeBuilder();
|
var nodeBuilder = createNodeBuilder();
|
||||||
var globals = ts.createSymbolTable();
|
var globals = ts.createSymbolTable();
|
||||||
|
var nodeGlobals = ts.createSymbolTable();
|
||||||
var undefinedSymbol = createSymbol(4 /* SymbolFlags.Property */, "undefined");
|
var undefinedSymbol = createSymbol(4 /* SymbolFlags.Property */, "undefined");
|
||||||
undefinedSymbol.declarations = [];
|
undefinedSymbol.declarations = [];
|
||||||
var globalThisSymbol = createSymbol(1536 /* SymbolFlags.Module */, "globalThis", 8 /* CheckFlags.Readonly */);
|
var globalThisSymbol = createSymbol(1536 /* SymbolFlags.Module */, "globalThis", 8 /* CheckFlags.Readonly */);
|
||||||
globalThisSymbol.exports = globals;
|
globalThisSymbol.exports = globals;
|
||||||
globalThisSymbol.declarations = [];
|
globalThisSymbol.declarations = [];
|
||||||
globals.set(globalThisSymbol.escapedName, globalThisSymbol);
|
globals.set(globalThisSymbol.escapedName, globalThisSymbol);
|
||||||
|
var denoContext = ts.deno.createDenoForkContext({
|
||||||
|
globals: globals,
|
||||||
|
nodeGlobals: nodeGlobals,
|
||||||
|
mergeSymbol: mergeSymbol,
|
||||||
|
ambientModuleSymbolRegex: ambientModuleSymbolRegex,
|
||||||
|
});
|
||||||
|
var nodeGlobalThisSymbol = createSymbol(1536 /* SymbolFlags.Module */, "globalThis", 8 /* CheckFlags.Readonly */);
|
||||||
|
nodeGlobalThisSymbol.exports = denoContext.combinedGlobals;
|
||||||
|
nodeGlobalThisSymbol.declarations = [];
|
||||||
|
nodeGlobals.set(nodeGlobalThisSymbol.escapedName, nodeGlobalThisSymbol);
|
||||||
var argumentsSymbol = createSymbol(4 /* SymbolFlags.Property */, "arguments");
|
var argumentsSymbol = createSymbol(4 /* SymbolFlags.Property */, "arguments");
|
||||||
var requireSymbol = createSymbol(4 /* SymbolFlags.Property */, "require");
|
var requireSymbol = createSymbol(4 /* SymbolFlags.Property */, "require");
|
||||||
/** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */
|
/** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */
|
||||||
|
@ -49464,6 +49475,7 @@ var ts;
|
||||||
var reverseMappedCache = new ts.Map();
|
var reverseMappedCache = new ts.Map();
|
||||||
var inInferTypeForHomomorphicMappedType = false;
|
var inInferTypeForHomomorphicMappedType = false;
|
||||||
var ambientModulesCache;
|
var ambientModulesCache;
|
||||||
|
var nodeAmbientModulesCache;
|
||||||
/**
|
/**
|
||||||
* List of every ambient module with a "*" wildcard.
|
* List of every ambient module with a "*" wildcard.
|
||||||
* Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches.
|
* Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches.
|
||||||
|
@ -49851,7 +49863,7 @@ var ts;
|
||||||
// Do not report an error when merging `var globalThis` with the built-in `globalThis`,
|
// Do not report an error when merging `var globalThis` with the built-in `globalThis`,
|
||||||
// as we will already report a "Declaration name conflicts..." error, and this error
|
// as we will already report a "Declaration name conflicts..." error, and this error
|
||||||
// won't make much sense.
|
// won't make much sense.
|
||||||
if (target !== globalThisSymbol) {
|
if (target !== globalThisSymbol && target !== nodeGlobalThisSymbol) {
|
||||||
error(source.declarations && ts.getNameOfDeclaration(source.declarations[0]), ts.Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target));
|
error(source.declarations && ts.getNameOfDeclaration(source.declarations[0]), ts.Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49950,7 +49962,7 @@ var ts;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ts.isGlobalScopeAugmentation(moduleAugmentation)) {
|
if (ts.isGlobalScopeAugmentation(moduleAugmentation)) {
|
||||||
mergeSymbolTable(globals, moduleAugmentation.symbol.exports);
|
denoContext.mergeGlobalSymbolTable(moduleAugmentation, moduleAugmentation.symbol.exports);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// find a module that about to be augmented
|
// find a module that about to be augmented
|
||||||
|
@ -50631,7 +50643,12 @@ var ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!excludeGlobals) {
|
if (!excludeGlobals) {
|
||||||
result = lookup(globals, name, meaning);
|
if (denoContext.hasNodeSourceFile(lastLocation)) {
|
||||||
|
result = lookup(nodeGlobals, name, meaning);
|
||||||
|
}
|
||||||
|
if (!result) {
|
||||||
|
result = lookup(globals, name, meaning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
@ -51888,6 +51905,24 @@ var ts;
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
function resolveExternalModule(location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation) {
|
function resolveExternalModule(location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation) {
|
||||||
|
var _a;
|
||||||
|
if (isForAugmentation === void 0) { isForAugmentation = false; }
|
||||||
|
var result = resolveExternalModuleInner(location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation);
|
||||||
|
// deno: attempt to resolve an npm package reference to its bare specifier w/ path ambient module
|
||||||
|
// when not found and the symbol has zero exports
|
||||||
|
if (moduleReference.startsWith("npm:") && (result == null || ((_a = result === null || result === void 0 ? void 0 : result.exports) === null || _a === void 0 ? void 0 : _a.size) === 0)) {
|
||||||
|
var npmPackageRef = ts.deno.tryParseNpmPackageReference(moduleReference);
|
||||||
|
if (npmPackageRef) {
|
||||||
|
var bareSpecifier = npmPackageRef.name + (npmPackageRef.subPath == null ? "" : "/" + npmPackageRef.subPath);
|
||||||
|
var ambientModule = tryFindAmbientModule(bareSpecifier, /*withAugmentations*/ true);
|
||||||
|
if (ambientModule) {
|
||||||
|
return ambientModule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function resolveExternalModuleInner(location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation) {
|
||||||
var _a, _b, _c, _d, _e, _f, _g, _h;
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
||||||
if (isForAugmentation === void 0) { isForAugmentation = false; }
|
if (isForAugmentation === void 0) { isForAugmentation = false; }
|
||||||
if (ts.startsWith(moduleReference, "@types/")) {
|
if (ts.startsWith(moduleReference, "@types/")) {
|
||||||
|
@ -52630,6 +52665,12 @@ var ts;
|
||||||
if (typeof state_2 === "object")
|
if (typeof state_2 === "object")
|
||||||
return state_2.value;
|
return state_2.value;
|
||||||
}
|
}
|
||||||
|
if (denoContext.hasNodeSourceFile(enclosingDeclaration)) {
|
||||||
|
result = callback(nodeGlobals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true);
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
return callback(globals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true);
|
return callback(globals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true);
|
||||||
}
|
}
|
||||||
function getQualifiedLeftMeaning(rightMeaning) {
|
function getQualifiedLeftMeaning(rightMeaning) {
|
||||||
|
@ -52713,7 +52754,11 @@ var ts;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// If there's no result and we're looking at the global symbol table, treat `globalThis` like an alias and try to lookup thru that
|
// If there's no result and we're looking at the global symbol table, treat `globalThis` like an alias and try to lookup thru that
|
||||||
return result || (symbols === globals ? getCandidateListForSymbol(globalThisSymbol, globalThisSymbol, ignoreQualification) : undefined);
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
var globalSymbol = symbols === nodeGlobals ? nodeGlobalThisSymbol : symbols === globals ? globalThisSymbol : undefined;
|
||||||
|
return globalSymbol != null ? getCandidateListForSymbol(globalSymbol, globalSymbol, ignoreQualification) : undefined;
|
||||||
}
|
}
|
||||||
function getCandidateListForSymbol(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification) {
|
function getCandidateListForSymbol(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification) {
|
||||||
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) {
|
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) {
|
||||||
|
@ -59159,7 +59204,7 @@ var ts;
|
||||||
var indexInfos;
|
var indexInfos;
|
||||||
if (symbol.exports) {
|
if (symbol.exports) {
|
||||||
members = getExportsOfSymbol(symbol);
|
members = getExportsOfSymbol(symbol);
|
||||||
if (symbol === globalThisSymbol) {
|
if (symbol === globalThisSymbol || symbol === nodeGlobalThisSymbol) {
|
||||||
var varsOnly_1 = new ts.Map();
|
var varsOnly_1 = new ts.Map();
|
||||||
members.forEach(function (p) {
|
members.forEach(function (p) {
|
||||||
var _a;
|
var _a;
|
||||||
|
@ -60321,7 +60366,7 @@ var ts;
|
||||||
if (ts.isExternalModuleNameRelative(moduleName)) {
|
if (ts.isExternalModuleNameRelative(moduleName)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
var symbol = getSymbol(globals, '"' + moduleName + '"', 512 /* SymbolFlags.ValueModule */);
|
var symbol = getSymbol(denoContext.combinedGlobals, '"' + moduleName + '"', 512 /* SymbolFlags.ValueModule */);
|
||||||
// merged symbol is module declaration symbol combined with all augmentations
|
// merged symbol is module declaration symbol combined with all augmentations
|
||||||
return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol;
|
return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol;
|
||||||
}
|
}
|
||||||
|
@ -62988,6 +63033,10 @@ var ts;
|
||||||
if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports.has(propName) && (globalThisSymbol.exports.get(propName).flags & 418 /* SymbolFlags.BlockScoped */)) {
|
if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports.has(propName) && (globalThisSymbol.exports.get(propName).flags & 418 /* SymbolFlags.BlockScoped */)) {
|
||||||
error(accessExpression, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.unescapeLeadingUnderscores(propName), typeToString(objectType));
|
error(accessExpression, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.unescapeLeadingUnderscores(propName), typeToString(objectType));
|
||||||
}
|
}
|
||||||
|
// deno: ensure condition and body match the above
|
||||||
|
else if (objectType.symbol === nodeGlobalThisSymbol && propName !== undefined && nodeGlobalThisSymbol.exports.has(propName) && (nodeGlobalThisSymbol.exports.get(propName).flags & 418 /* SymbolFlags.BlockScoped */)) {
|
||||||
|
error(accessExpression, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.unescapeLeadingUnderscores(propName), typeToString(objectType));
|
||||||
|
}
|
||||||
else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & 128 /* AccessFlags.SuppressNoImplicitAnyError */)) {
|
else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & 128 /* AccessFlags.SuppressNoImplicitAnyError */)) {
|
||||||
if (propName !== undefined && typeHasStaticProperty(propName, objectType)) {
|
if (propName !== undefined && typeHasStaticProperty(propName, objectType)) {
|
||||||
var typeName = typeToString(objectType);
|
var typeName = typeToString(objectType);
|
||||||
|
@ -71860,7 +71909,7 @@ var ts;
|
||||||
if (type.flags & 1048576 /* TypeFlags.Union */
|
if (type.flags & 1048576 /* TypeFlags.Union */
|
||||||
|| type.flags & 524288 /* TypeFlags.Object */ && declaredType !== type && !(declaredType === unknownType && isEmptyAnonymousObjectType(type))
|
|| type.flags & 524288 /* TypeFlags.Object */ && declaredType !== type && !(declaredType === unknownType && isEmptyAnonymousObjectType(type))
|
||||||
|| ts.isThisTypeParameter(type)
|
|| ts.isThisTypeParameter(type)
|
||||||
|| type.flags & 2097152 /* TypeFlags.Intersection */ && ts.every(type.types, function (t) { return t.symbol !== globalThisSymbol; })) {
|
|| type.flags & 2097152 /* TypeFlags.Intersection */ && ts.every(type.types, function (t) { return t.symbol !== globalThisSymbol && t.symbol !== nodeGlobalThisSymbol; })) {
|
||||||
return filterType(type, function (t) { return isTypePresencePossible(t, name, assumeTrue); });
|
return filterType(type, function (t) { return isTypePresencePossible(t, name, assumeTrue); });
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
|
@ -73019,6 +73068,9 @@ var ts;
|
||||||
return undefinedType;
|
return undefinedType;
|
||||||
}
|
}
|
||||||
else if (includeGlobalThis) {
|
else if (includeGlobalThis) {
|
||||||
|
if (denoContext.hasNodeSourceFile(container)) {
|
||||||
|
return getTypeOfSymbol(nodeGlobalThisSymbol);
|
||||||
|
}
|
||||||
return getTypeOfSymbol(globalThisSymbol);
|
return getTypeOfSymbol(globalThisSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75690,6 +75742,11 @@ var ts;
|
||||||
}
|
}
|
||||||
return anyType;
|
return anyType;
|
||||||
}
|
}
|
||||||
|
// deno: ensure condition matches above
|
||||||
|
if (leftType.symbol === nodeGlobalThisSymbol) {
|
||||||
|
// deno: don't bother with errors like above for simplicity
|
||||||
|
return anyType;
|
||||||
|
}
|
||||||
if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) {
|
if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) {
|
||||||
reportNonexistentProperty(right, ts.isThisTypeParameter(leftType) ? apparentType : leftType, isUncheckedJS);
|
reportNonexistentProperty(right, ts.isThisTypeParameter(leftType) ? apparentType : leftType, isUncheckedJS);
|
||||||
}
|
}
|
||||||
|
@ -75997,7 +76054,7 @@ var ts;
|
||||||
if (symbol)
|
if (symbol)
|
||||||
return symbol;
|
return symbol;
|
||||||
var candidates;
|
var candidates;
|
||||||
if (symbols === globals) {
|
if (symbols === globals || symbols === nodeGlobals) {
|
||||||
var primitives = ts.mapDefined(["string", "number", "boolean", "object", "bigint", "symbol"], function (s) { return symbols.has((s.charAt(0).toUpperCase() + s.slice(1)))
|
var primitives = ts.mapDefined(["string", "number", "boolean", "object", "bigint", "symbol"], function (s) { return symbols.has((s.charAt(0).toUpperCase() + s.slice(1)))
|
||||||
? createSymbol(524288 /* SymbolFlags.TypeAlias */, s)
|
? createSymbol(524288 /* SymbolFlags.TypeAlias */, s)
|
||||||
: undefined; });
|
: undefined; });
|
||||||
|
@ -86656,7 +86713,7 @@ var ts;
|
||||||
// find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases)
|
// find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases)
|
||||||
var symbol = resolveName(exportedName, exportedName.escapedText, 111551 /* SymbolFlags.Value */ | 788968 /* SymbolFlags.Type */ | 1920 /* SymbolFlags.Namespace */ | 2097152 /* SymbolFlags.Alias */,
|
var symbol = resolveName(exportedName, exportedName.escapedText, 111551 /* SymbolFlags.Value */ | 788968 /* SymbolFlags.Type */ | 1920 /* SymbolFlags.Namespace */ | 2097152 /* SymbolFlags.Alias */,
|
||||||
/*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
|
/*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
|
||||||
if (symbol && (symbol === undefinedSymbol || symbol === globalThisSymbol || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) {
|
if (symbol && (symbol === undefinedSymbol || symbol === globalThisSymbol || symbol === nodeGlobalThisSymbol || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) {
|
||||||
error(exportedName, ts.Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, ts.idText(exportedName));
|
error(exportedName, ts.Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, ts.idText(exportedName));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -87343,6 +87400,9 @@ var ts;
|
||||||
isStaticSymbol = ts.isStatic(location);
|
isStaticSymbol = ts.isStatic(location);
|
||||||
location = location.parent;
|
location = location.parent;
|
||||||
}
|
}
|
||||||
|
if (denoContext.hasNodeSourceFile(location)) {
|
||||||
|
copySymbols(nodeGlobals, meaning);
|
||||||
|
}
|
||||||
copySymbols(globals, meaning);
|
copySymbols(globals, meaning);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -88717,25 +88777,24 @@ var ts;
|
||||||
amalgamatedDuplicates = new ts.Map();
|
amalgamatedDuplicates = new ts.Map();
|
||||||
// Initialize global symbol table
|
// Initialize global symbol table
|
||||||
var augmentations;
|
var augmentations;
|
||||||
for (var _b = 0, _c = host.getSourceFiles(); _b < _c.length; _b++) {
|
var _loop_35 = function (file) {
|
||||||
var file = _c[_b];
|
|
||||||
if (file.redirectInfo) {
|
if (file.redirectInfo) {
|
||||||
continue;
|
return "continue";
|
||||||
}
|
}
|
||||||
if (!ts.isExternalOrCommonJsModule(file)) {
|
if (!ts.isExternalOrCommonJsModule(file)) {
|
||||||
// It is an error for a non-external-module (i.e. script) to declare its own `globalThis`.
|
// It is an error for a non-external-module (i.e. script) to declare its own `globalThis`.
|
||||||
// We can't use `builtinGlobals` for this due to synthetic expando-namespace generation in JS files.
|
// We can't use `builtinGlobals` for this due to synthetic expando-namespace generation in JS files.
|
||||||
var fileGlobalThisSymbol = file.locals.get("globalThis");
|
var fileGlobalThisSymbol = file.locals.get("globalThis");
|
||||||
if (fileGlobalThisSymbol === null || fileGlobalThisSymbol === void 0 ? void 0 : fileGlobalThisSymbol.declarations) {
|
if (fileGlobalThisSymbol === null || fileGlobalThisSymbol === void 0 ? void 0 : fileGlobalThisSymbol.declarations) {
|
||||||
for (var _d = 0, _e = fileGlobalThisSymbol.declarations; _d < _e.length; _d++) {
|
for (var _h = 0, _j = fileGlobalThisSymbol.declarations; _h < _j.length; _h++) {
|
||||||
var declaration = _e[_d];
|
var declaration = _j[_h];
|
||||||
diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis"));
|
diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mergeSymbolTable(globals, file.locals);
|
denoContext.mergeGlobalSymbolTable(file, file.locals);
|
||||||
}
|
}
|
||||||
if (file.jsGlobalAugmentations) {
|
if (file.jsGlobalAugmentations) {
|
||||||
mergeSymbolTable(globals, file.jsGlobalAugmentations);
|
denoContext.mergeGlobalSymbolTable(file, file.jsGlobalAugmentations);
|
||||||
}
|
}
|
||||||
if (file.patternAmbientModules && file.patternAmbientModules.length) {
|
if (file.patternAmbientModules && file.patternAmbientModules.length) {
|
||||||
patternAmbientModules = ts.concatenate(patternAmbientModules, file.patternAmbientModules);
|
patternAmbientModules = ts.concatenate(patternAmbientModules, file.patternAmbientModules);
|
||||||
|
@ -88746,12 +88805,18 @@ var ts;
|
||||||
if (file.symbol && file.symbol.globalExports) {
|
if (file.symbol && file.symbol.globalExports) {
|
||||||
// Merge in UMD exports with first-in-wins semantics (see #9771)
|
// Merge in UMD exports with first-in-wins semantics (see #9771)
|
||||||
var source = file.symbol.globalExports;
|
var source = file.symbol.globalExports;
|
||||||
|
var isNodeFile_1 = denoContext.hasNodeSourceFile(file);
|
||||||
source.forEach(function (sourceSymbol, id) {
|
source.forEach(function (sourceSymbol, id) {
|
||||||
if (!globals.has(id)) {
|
var envGlobals = isNodeFile_1 ? denoContext.getGlobalsForName(id) : globals;
|
||||||
globals.set(id, sourceSymbol);
|
if (!envGlobals.has(id)) {
|
||||||
|
envGlobals.set(id, sourceSymbol);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
for (var _b = 0, _c = host.getSourceFiles(); _b < _c.length; _b++) {
|
||||||
|
var file = _c[_b];
|
||||||
|
_loop_35(file);
|
||||||
}
|
}
|
||||||
// We do global augmentations separately from module augmentations (and before creating global types) because they
|
// We do global augmentations separately from module augmentations (and before creating global types) because they
|
||||||
// 1. Affect global types. We won't have the correct global types until global augmentations are merged. Also,
|
// 1. Affect global types. We won't have the correct global types until global augmentations are merged. Also,
|
||||||
|
@ -88762,10 +88827,10 @@ var ts;
|
||||||
if (augmentations) {
|
if (augmentations) {
|
||||||
// merge _global_ module augmentations.
|
// merge _global_ module augmentations.
|
||||||
// this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
|
// this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
|
||||||
for (var _f = 0, augmentations_1 = augmentations; _f < augmentations_1.length; _f++) {
|
for (var _d = 0, augmentations_1 = augmentations; _d < augmentations_1.length; _d++) {
|
||||||
var list = augmentations_1[_f];
|
var list = augmentations_1[_d];
|
||||||
for (var _g = 0, list_1 = list; _g < list_1.length; _g++) {
|
for (var _e = 0, list_1 = list; _e < list_1.length; _e++) {
|
||||||
var augmentation = list_1[_g];
|
var augmentation = list_1[_e];
|
||||||
if (!ts.isGlobalScopeAugmentation(augmentation.parent))
|
if (!ts.isGlobalScopeAugmentation(augmentation.parent))
|
||||||
continue;
|
continue;
|
||||||
mergeModuleAugmentation(augmentation);
|
mergeModuleAugmentation(augmentation);
|
||||||
|
@ -88778,6 +88843,7 @@ var ts;
|
||||||
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments", /*arity*/ 0, /*reportErrors*/ true);
|
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments", /*arity*/ 0, /*reportErrors*/ true);
|
||||||
getSymbolLinks(unknownSymbol).type = errorType;
|
getSymbolLinks(unknownSymbol).type = errorType;
|
||||||
getSymbolLinks(globalThisSymbol).type = createObjectType(16 /* ObjectFlags.Anonymous */, globalThisSymbol);
|
getSymbolLinks(globalThisSymbol).type = createObjectType(16 /* ObjectFlags.Anonymous */, globalThisSymbol);
|
||||||
|
getSymbolLinks(nodeGlobalThisSymbol).type = createObjectType(16 /* ObjectFlags.Anonymous */, nodeGlobalThisSymbol);
|
||||||
// Initialize special types
|
// Initialize special types
|
||||||
globalArrayType = getGlobalType("Array", /*arity*/ 1, /*reportErrors*/ true);
|
globalArrayType = getGlobalType("Array", /*arity*/ 1, /*reportErrors*/ true);
|
||||||
globalObjectType = getGlobalType("Object", /*arity*/ 0, /*reportErrors*/ true);
|
globalObjectType = getGlobalType("Object", /*arity*/ 0, /*reportErrors*/ true);
|
||||||
|
@ -88800,10 +88866,10 @@ var ts;
|
||||||
if (augmentations) {
|
if (augmentations) {
|
||||||
// merge _nonglobal_ module augmentations.
|
// merge _nonglobal_ module augmentations.
|
||||||
// this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
|
// this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
|
||||||
for (var _h = 0, augmentations_2 = augmentations; _h < augmentations_2.length; _h++) {
|
for (var _f = 0, augmentations_2 = augmentations; _f < augmentations_2.length; _f++) {
|
||||||
var list = augmentations_2[_h];
|
var list = augmentations_2[_f];
|
||||||
for (var _j = 0, list_2 = list; _j < list_2.length; _j++) {
|
for (var _g = 0, list_2 = list; _g < list_2.length; _g++) {
|
||||||
var augmentation = list_2[_j];
|
var augmentation = list_2[_g];
|
||||||
if (ts.isGlobalScopeAugmentation(augmentation.parent))
|
if (ts.isGlobalScopeAugmentation(augmentation.parent))
|
||||||
continue;
|
continue;
|
||||||
mergeModuleAugmentation(augmentation);
|
mergeModuleAugmentation(augmentation);
|
||||||
|
@ -90373,17 +90439,30 @@ var ts;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function getAmbientModules() {
|
function getAmbientModules(sourceFile) {
|
||||||
if (!ambientModulesCache) {
|
var isNode = denoContext.hasNodeSourceFile(sourceFile);
|
||||||
ambientModulesCache = [];
|
if (isNode) {
|
||||||
globals.forEach(function (global, sym) {
|
if (!nodeAmbientModulesCache) {
|
||||||
|
nodeAmbientModulesCache = getAmbientModules(denoContext.combinedGlobals);
|
||||||
|
}
|
||||||
|
return nodeAmbientModulesCache;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!ambientModulesCache) {
|
||||||
|
ambientModulesCache = getAmbientModules(globals);
|
||||||
|
}
|
||||||
|
return ambientModulesCache;
|
||||||
|
}
|
||||||
|
function getAmbientModules(envGlobals) {
|
||||||
|
var cache = [];
|
||||||
|
envGlobals.forEach(function (global, sym) {
|
||||||
// No need to `unescapeLeadingUnderscores`, an escaped symbol is never an ambient module.
|
// No need to `unescapeLeadingUnderscores`, an escaped symbol is never an ambient module.
|
||||||
if (ambientModuleSymbolRegex.test(sym)) {
|
if (ambientModuleSymbolRegex.test(sym)) {
|
||||||
ambientModulesCache.push(global);
|
cache.push(global);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return cache;
|
||||||
}
|
}
|
||||||
return ambientModulesCache;
|
|
||||||
}
|
}
|
||||||
function checkGrammarImportClause(node) {
|
function checkGrammarImportClause(node) {
|
||||||
var _a;
|
var _a;
|
||||||
|
@ -90562,6 +90641,234 @@ var ts;
|
||||||
}
|
}
|
||||||
ts.signatureHasLiteralTypes = signatureHasLiteralTypes;
|
ts.signatureHasLiteralTypes = signatureHasLiteralTypes;
|
||||||
})(ts || (ts = {}));
|
})(ts || (ts = {}));
|
||||||
|
/* @internal */
|
||||||
|
var ts;
|
||||||
|
(function (ts) {
|
||||||
|
var deno;
|
||||||
|
(function (deno) {
|
||||||
|
var isNodeSourceFile = function () { return false; };
|
||||||
|
function setIsNodeSourceFileCallback(callback) {
|
||||||
|
isNodeSourceFile = callback;
|
||||||
|
}
|
||||||
|
deno.setIsNodeSourceFileCallback = setIsNodeSourceFileCallback;
|
||||||
|
// When upgrading:
|
||||||
|
// 1. Inspect all usages of "globals" and "globalThisSymbol" in checker.ts
|
||||||
|
// - Beware that `globalThisType` might refer to the global `this` type
|
||||||
|
// and not the global `globalThis` type
|
||||||
|
// 2. Inspect the types in @types/node for anything that might need to go below
|
||||||
|
// as well.
|
||||||
|
var nodeOnlyGlobalNames = new ts.Set([
|
||||||
|
"NodeRequire",
|
||||||
|
"RequireResolve",
|
||||||
|
"RequireResolve",
|
||||||
|
"process",
|
||||||
|
"console",
|
||||||
|
"__filename",
|
||||||
|
"__dirname",
|
||||||
|
"require",
|
||||||
|
"module",
|
||||||
|
"exports",
|
||||||
|
"gc",
|
||||||
|
"BufferEncoding",
|
||||||
|
"BufferConstructor",
|
||||||
|
"WithImplicitCoercion",
|
||||||
|
"Buffer",
|
||||||
|
"Console",
|
||||||
|
"ImportMeta",
|
||||||
|
"setTimeout",
|
||||||
|
"setInterval",
|
||||||
|
"setImmediate",
|
||||||
|
"Global",
|
||||||
|
"AbortController",
|
||||||
|
"AbortSignal",
|
||||||
|
"Blob",
|
||||||
|
"BroadcastChannel",
|
||||||
|
"MessageChannel",
|
||||||
|
"MessagePort",
|
||||||
|
"Event",
|
||||||
|
"EventTarget",
|
||||||
|
"performance",
|
||||||
|
"TextDecoder",
|
||||||
|
"TextEncoder",
|
||||||
|
"URL",
|
||||||
|
"URLSearchParams",
|
||||||
|
]);
|
||||||
|
function createDenoForkContext(_a) {
|
||||||
|
var mergeSymbol = _a.mergeSymbol, globals = _a.globals, nodeGlobals = _a.nodeGlobals, ambientModuleSymbolRegex = _a.ambientModuleSymbolRegex;
|
||||||
|
return {
|
||||||
|
hasNodeSourceFile: hasNodeSourceFile,
|
||||||
|
getGlobalsForName: getGlobalsForName,
|
||||||
|
mergeGlobalSymbolTable: mergeGlobalSymbolTable,
|
||||||
|
combinedGlobals: createNodeGlobalsSymbolTable(),
|
||||||
|
};
|
||||||
|
function hasNodeSourceFile(node) {
|
||||||
|
if (!node)
|
||||||
|
return false;
|
||||||
|
var sourceFile = ts.getSourceFileOfNode(node);
|
||||||
|
return isNodeSourceFile(sourceFile);
|
||||||
|
}
|
||||||
|
function getGlobalsForName(id) {
|
||||||
|
// Node ambient modules are only accessible in the node code,
|
||||||
|
// so put them on the node globals
|
||||||
|
if (ambientModuleSymbolRegex.test(id))
|
||||||
|
return nodeGlobals;
|
||||||
|
return nodeOnlyGlobalNames.has(id) ? nodeGlobals : globals;
|
||||||
|
}
|
||||||
|
function mergeGlobalSymbolTable(node, source, unidirectional) {
|
||||||
|
if (unidirectional === void 0) { unidirectional = false; }
|
||||||
|
var sourceFile = ts.getSourceFileOfNode(node);
|
||||||
|
var isNodeFile = hasNodeSourceFile(sourceFile);
|
||||||
|
source.forEach(function (sourceSymbol, id) {
|
||||||
|
var target = isNodeFile ? getGlobalsForName(id) : globals;
|
||||||
|
var targetSymbol = target.get(id);
|
||||||
|
target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : sourceSymbol);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function createNodeGlobalsSymbolTable() {
|
||||||
|
return new Proxy(globals, {
|
||||||
|
get: function (target, prop, receiver) {
|
||||||
|
if (prop === "get") {
|
||||||
|
return function (key) {
|
||||||
|
var _a;
|
||||||
|
return (_a = nodeGlobals.get(key)) !== null && _a !== void 0 ? _a : globals.get(key);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (prop === "has") {
|
||||||
|
return function (key) {
|
||||||
|
return nodeGlobals.has(key) || globals.has(key);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (prop === "size") {
|
||||||
|
var i_2 = 0;
|
||||||
|
forEachEntry(function () {
|
||||||
|
i_2++;
|
||||||
|
});
|
||||||
|
return i_2;
|
||||||
|
}
|
||||||
|
else if (prop === "forEach") {
|
||||||
|
return function (action) {
|
||||||
|
forEachEntry(function (_a) {
|
||||||
|
var key = _a[0], value = _a[1];
|
||||||
|
action(value, key);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (prop === "entries") {
|
||||||
|
return function () {
|
||||||
|
return getEntries(function (kv) { return kv; });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (prop === "keys") {
|
||||||
|
return function () {
|
||||||
|
return getEntries(function (kv) { return kv[0]; });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (prop === "values") {
|
||||||
|
return function () {
|
||||||
|
return getEntries(function (kv) { return kv[1]; });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (prop === Symbol.iterator) {
|
||||||
|
return function () {
|
||||||
|
// Need to convert this to an array since typescript targets ES5
|
||||||
|
// and providing back the iterator won't work here. I don't want
|
||||||
|
// to change the target to ES6 because I'm not sure if that would
|
||||||
|
// surface any issues.
|
||||||
|
return ts.arrayFrom(getEntries(function (kv) { return kv; }))[Symbol.iterator]();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var value_3 = target[prop];
|
||||||
|
if (value_3 instanceof Function) {
|
||||||
|
return function () {
|
||||||
|
var args = [];
|
||||||
|
for (var _i = 0; _i < arguments.length; _i++) {
|
||||||
|
args[_i] = arguments[_i];
|
||||||
|
}
|
||||||
|
return value_3.apply(this === receiver ? target : this, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return value_3;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
function forEachEntry(action) {
|
||||||
|
var iterator = getEntries(function (entry) {
|
||||||
|
action(entry);
|
||||||
|
});
|
||||||
|
// drain the iterator to do the action
|
||||||
|
while (!iterator.next().done) { }
|
||||||
|
}
|
||||||
|
function getEntries(transform) {
|
||||||
|
var foundKeys, _i, _a, entries, next;
|
||||||
|
return __generator(this, function (_b) {
|
||||||
|
switch (_b.label) {
|
||||||
|
case 0:
|
||||||
|
foundKeys = new ts.Set();
|
||||||
|
_i = 0, _a = [nodeGlobals.entries(), globals.entries()];
|
||||||
|
_b.label = 1;
|
||||||
|
case 1:
|
||||||
|
if (!(_i < _a.length)) return [3 /*break*/, 6];
|
||||||
|
entries = _a[_i];
|
||||||
|
next = entries.next();
|
||||||
|
_b.label = 2;
|
||||||
|
case 2:
|
||||||
|
if (!!next.done) return [3 /*break*/, 5];
|
||||||
|
if (!!foundKeys.has(next.value[0])) return [3 /*break*/, 4];
|
||||||
|
return [4 /*yield*/, transform(next.value)];
|
||||||
|
case 3:
|
||||||
|
_b.sent();
|
||||||
|
foundKeys.add(next.value[0]);
|
||||||
|
_b.label = 4;
|
||||||
|
case 4:
|
||||||
|
next = entries.next();
|
||||||
|
return [3 /*break*/, 2];
|
||||||
|
case 5:
|
||||||
|
_i++;
|
||||||
|
return [3 /*break*/, 1];
|
||||||
|
case 6: return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deno.createDenoForkContext = createDenoForkContext;
|
||||||
|
function tryParseNpmPackageReference(text) {
|
||||||
|
try {
|
||||||
|
return parseNpmPackageReference(text);
|
||||||
|
}
|
||||||
|
catch (_a) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deno.tryParseNpmPackageReference = tryParseNpmPackageReference;
|
||||||
|
function parseNpmPackageReference(text) {
|
||||||
|
if (!text.startsWith("npm:")) {
|
||||||
|
throw new Error("Not an npm specifier: ".concat(text));
|
||||||
|
}
|
||||||
|
text = text.replace(/^npm:/, "");
|
||||||
|
var parts = text.split("/");
|
||||||
|
var namePartLen = text.startsWith("@") ? 2 : 1;
|
||||||
|
if (parts.length < namePartLen) {
|
||||||
|
throw new Error("Not a valid package: ".concat(text));
|
||||||
|
}
|
||||||
|
var nameParts = parts.slice(0, namePartLen);
|
||||||
|
var lastNamePart = nameParts.at(-1);
|
||||||
|
var lastAtIndex = lastNamePart.lastIndexOf("@");
|
||||||
|
var versionReq = undefined;
|
||||||
|
if (lastAtIndex > 0) {
|
||||||
|
versionReq = lastNamePart.substring(lastAtIndex + 1);
|
||||||
|
nameParts[nameParts.length - 1] = lastNamePart.substring(0, lastAtIndex);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: nameParts.join("/"),
|
||||||
|
versionReq: versionReq,
|
||||||
|
subPath: parts.length > nameParts.length ? parts.slice(nameParts.length).join("/") : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
deno.parseNpmPackageReference = parseNpmPackageReference;
|
||||||
|
})(deno = ts.deno || (ts.deno = {}));
|
||||||
|
})(ts || (ts = {}));
|
||||||
var ts;
|
var ts;
|
||||||
(function (ts) {
|
(function (ts) {
|
||||||
function visitNode(node, visitor, test, lift) {
|
function visitNode(node, visitor, test, lift) {
|
||||||
|
@ -121271,7 +121578,7 @@ var ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// From ambient modules
|
// From ambient modules
|
||||||
for (var _f = 0, _g = program.getTypeChecker().getAmbientModules(); _f < _g.length; _f++) {
|
for (var _f = 0, _g = program.getTypeChecker().getAmbientModules(sourceFile); _f < _g.length; _f++) {
|
||||||
var ambientModule = _g[_f];
|
var ambientModule = _g[_f];
|
||||||
if (ambientModule.declarations && ambientModule.declarations.length > 1) {
|
if (ambientModule.declarations && ambientModule.declarations.length > 1) {
|
||||||
addReferenceFromAmbientModule(ambientModule);
|
addReferenceFromAmbientModule(ambientModule);
|
||||||
|
@ -124123,7 +124430,7 @@ var ts;
|
||||||
});
|
});
|
||||||
// Sort by paths closest to importing file Name directory
|
// Sort by paths closest to importing file Name directory
|
||||||
var sortedPaths = [];
|
var sortedPaths = [];
|
||||||
var _loop_35 = function (directory) {
|
var _loop_36 = function (directory) {
|
||||||
var directoryStart = ts.ensureTrailingDirectorySeparator(directory);
|
var directoryStart = ts.ensureTrailingDirectorySeparator(directory);
|
||||||
var pathsInDirectory;
|
var pathsInDirectory;
|
||||||
allFileNames.forEach(function (_a, fileName) {
|
allFileNames.forEach(function (_a, fileName) {
|
||||||
|
@ -124147,7 +124454,7 @@ var ts;
|
||||||
};
|
};
|
||||||
var out_directory_1;
|
var out_directory_1;
|
||||||
for (var directory = ts.getDirectoryPath(importingFileName); allFileNames.size !== 0;) {
|
for (var directory = ts.getDirectoryPath(importingFileName); allFileNames.size !== 0;) {
|
||||||
var state_11 = _loop_35(directory);
|
var state_11 = _loop_36(directory);
|
||||||
directory = out_directory_1;
|
directory = out_directory_1;
|
||||||
if (state_11 === "break")
|
if (state_11 === "break")
|
||||||
break;
|
break;
|
||||||
|
@ -124218,7 +124525,7 @@ var ts;
|
||||||
}
|
}
|
||||||
function tryGetModuleNameFromPaths(relativeToBaseUrl, paths, allowedEndings, host, compilerOptions) {
|
function tryGetModuleNameFromPaths(relativeToBaseUrl, paths, allowedEndings, host, compilerOptions) {
|
||||||
for (var key in paths) {
|
for (var key in paths) {
|
||||||
var _loop_36 = function (patternText_1) {
|
var _loop_37 = function (patternText_1) {
|
||||||
var pattern = ts.normalizePath(patternText_1);
|
var pattern = ts.normalizePath(patternText_1);
|
||||||
var indexOfStar = pattern.indexOf("*");
|
var indexOfStar = pattern.indexOf("*");
|
||||||
// In module resolution, if `pattern` itself has an extension, a file with that extension is looked up directly,
|
// In module resolution, if `pattern` itself has an extension, a file with that extension is looked up directly,
|
||||||
|
@ -124285,7 +124592,7 @@ var ts;
|
||||||
};
|
};
|
||||||
for (var _i = 0, _a = paths[key]; _i < _a.length; _i++) {
|
for (var _i = 0, _a = paths[key]; _i < _a.length; _i++) {
|
||||||
var patternText_1 = _a[_i];
|
var patternText_1 = _a[_i];
|
||||||
var state_12 = _loop_36(patternText_1);
|
var state_12 = _loop_37(patternText_1);
|
||||||
if (typeof state_12 === "object")
|
if (typeof state_12 === "object")
|
||||||
return state_12.value;
|
return state_12.value;
|
||||||
}
|
}
|
||||||
|
@ -137638,7 +137945,8 @@ var ts;
|
||||||
if (globalSymbol && checker.getTypeOfSymbolAtLocation(globalSymbol, sourceFile) === type) {
|
if (globalSymbol && checker.getTypeOfSymbolAtLocation(globalSymbol, sourceFile) === type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var globalThisSymbol = checker.resolveName("globalThis", /*location*/ undefined, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ false);
|
// deno: provide sourceFile so that it can figure out if it's a node or deno globalThis
|
||||||
|
var globalThisSymbol = checker.resolveName("globalThis", /*location*/ sourceFile, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ false);
|
||||||
if (globalThisSymbol && checker.getTypeOfSymbolAtLocation(globalThisSymbol, sourceFile) === type) {
|
if (globalThisSymbol && checker.getTypeOfSymbolAtLocation(globalThisSymbol, sourceFile) === type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ delete Object.prototype.__proto__;
|
||||||
// This map stores that relationship, and the original can be restored by the
|
// This map stores that relationship, and the original can be restored by the
|
||||||
// normalized specifier.
|
// normalized specifier.
|
||||||
// See: https://github.com/denoland/deno/issues/9277#issuecomment-769653834
|
// See: https://github.com/denoland/deno/issues/9277#issuecomment-769653834
|
||||||
|
/** @type {Map<string, string>} */
|
||||||
const normalizedToOriginalMap = new Map();
|
const normalizedToOriginalMap = new Map();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +41,16 @@ delete Object.prototype.__proto__;
|
||||||
"languageVersion" in value;
|
"languageVersion" in value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ts.ScriptTarget | ts.CreateSourceFileOptions | undefined} versionOrOptions
|
||||||
|
* @returns {ts.CreateSourceFileOptions}
|
||||||
|
*/
|
||||||
|
function getCreateSourceFileOptions(versionOrOptions) {
|
||||||
|
return isCreateSourceFileOptions(versionOrOptions)
|
||||||
|
? versionOrOptions
|
||||||
|
: { languageVersion: versionOrOptions ?? ts.ScriptTarget.ESNext };
|
||||||
|
}
|
||||||
|
|
||||||
function setLogDebug(debug, source) {
|
function setLogDebug(debug, source) {
|
||||||
logDebug = debug;
|
logDebug = debug;
|
||||||
if (source) {
|
if (source) {
|
||||||
|
@ -119,8 +130,23 @@ delete Object.prototype.__proto__;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the case of the LSP, this is initialized with the assets
|
class SpecifierIsCjsCache {
|
||||||
// when snapshotting and never added to or removed after that.
|
/** @type {Set<string>} */
|
||||||
|
#cache = new Set();
|
||||||
|
|
||||||
|
/** @param {[string, ts.Extension]} param */
|
||||||
|
add([specifier, ext]) {
|
||||||
|
if (ext === ".cjs" || ext === ".d.cts" || ext === ".cts") {
|
||||||
|
this.#cache.add(specifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
has(specifier) {
|
||||||
|
return this.#cache.has(specifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the case of the LSP, this will only ever contain the assets.
|
||||||
/** @type {Map<string, ts.SourceFile>} */
|
/** @type {Map<string, ts.SourceFile>} */
|
||||||
const sourceFileCache = new Map();
|
const sourceFileCache = new Map();
|
||||||
|
|
||||||
|
@ -130,6 +156,181 @@ delete Object.prototype.__proto__;
|
||||||
/** @type {Map<string, string>} */
|
/** @type {Map<string, string>} */
|
||||||
const scriptVersionCache = new Map();
|
const scriptVersionCache = new Map();
|
||||||
|
|
||||||
|
/** @type {Map<string, boolean>} */
|
||||||
|
const isNodeSourceFileCache = new Map();
|
||||||
|
|
||||||
|
const isCjsCache = new SpecifierIsCjsCache();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ts.CompilerOptions | ts.MinimalResolutionCacheHost} settingsOrHost
|
||||||
|
* @returns {ts.CompilerOptions}
|
||||||
|
*/
|
||||||
|
function getCompilationSettings(settingsOrHost) {
|
||||||
|
if (typeof settingsOrHost.getCompilationSettings === "function") {
|
||||||
|
return settingsOrHost.getCompilationSettings();
|
||||||
|
}
|
||||||
|
return /** @type {ts.CompilerOptions} */ (settingsOrHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to use a custom document registry in order to provide source files
|
||||||
|
// with an impliedNodeFormat to the ts language service
|
||||||
|
|
||||||
|
/** @type {Map<string, ts.SourceFile} */
|
||||||
|
const documentRegistrySourceFileCache = new Map();
|
||||||
|
const { getKeyForCompilationSettings } = ts.createDocumentRegistry(); // reuse this code
|
||||||
|
/** @type {ts.DocumentRegistry} */
|
||||||
|
const documentRegistry = {
|
||||||
|
acquireDocument(
|
||||||
|
fileName,
|
||||||
|
compilationSettingsOrHost,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptKind,
|
||||||
|
sourceFileOptions,
|
||||||
|
) {
|
||||||
|
const key = getKeyForCompilationSettings(
|
||||||
|
getCompilationSettings(compilationSettingsOrHost),
|
||||||
|
);
|
||||||
|
return this.acquireDocumentWithKey(
|
||||||
|
fileName,
|
||||||
|
/** @type {ts.Path} */ (fileName),
|
||||||
|
compilationSettingsOrHost,
|
||||||
|
key,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptKind,
|
||||||
|
sourceFileOptions,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
acquireDocumentWithKey(
|
||||||
|
fileName,
|
||||||
|
path,
|
||||||
|
_compilationSettingsOrHost,
|
||||||
|
key,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptKind,
|
||||||
|
sourceFileOptions,
|
||||||
|
) {
|
||||||
|
const mapKey = path + key;
|
||||||
|
let sourceFile = documentRegistrySourceFileCache.get(mapKey);
|
||||||
|
if (!sourceFile || sourceFile.version !== version) {
|
||||||
|
sourceFile = ts.createLanguageServiceSourceFile(
|
||||||
|
fileName,
|
||||||
|
scriptSnapshot,
|
||||||
|
{
|
||||||
|
...getCreateSourceFileOptions(sourceFileOptions),
|
||||||
|
impliedNodeFormat: isCjsCache.has(fileName)
|
||||||
|
? ts.ModuleKind.CommonJS
|
||||||
|
: ts.ModuleKind.ESNext,
|
||||||
|
},
|
||||||
|
version,
|
||||||
|
true,
|
||||||
|
scriptKind,
|
||||||
|
);
|
||||||
|
documentRegistrySourceFileCache.set(mapKey, sourceFile);
|
||||||
|
}
|
||||||
|
return sourceFile;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDocument(
|
||||||
|
fileName,
|
||||||
|
compilationSettingsOrHost,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptKind,
|
||||||
|
sourceFileOptions,
|
||||||
|
) {
|
||||||
|
const key = getKeyForCompilationSettings(
|
||||||
|
getCompilationSettings(compilationSettingsOrHost),
|
||||||
|
);
|
||||||
|
return this.updateDocumentWithKey(
|
||||||
|
fileName,
|
||||||
|
/** @type {ts.Path} */ (fileName),
|
||||||
|
compilationSettingsOrHost,
|
||||||
|
key,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptKind,
|
||||||
|
sourceFileOptions,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDocumentWithKey(
|
||||||
|
fileName,
|
||||||
|
path,
|
||||||
|
compilationSettingsOrHost,
|
||||||
|
key,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptKind,
|
||||||
|
sourceFileOptions,
|
||||||
|
) {
|
||||||
|
const mapKey = path + key;
|
||||||
|
let sourceFile = documentRegistrySourceFileCache.get(mapKey) ??
|
||||||
|
this.acquireDocumentWithKey(
|
||||||
|
fileName,
|
||||||
|
path,
|
||||||
|
compilationSettingsOrHost,
|
||||||
|
key,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptKind,
|
||||||
|
sourceFileOptions,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sourceFile.version !== version) {
|
||||||
|
sourceFile = ts.updateLanguageServiceSourceFile(
|
||||||
|
sourceFile,
|
||||||
|
scriptSnapshot,
|
||||||
|
version,
|
||||||
|
scriptSnapshot.getChangeRange(sourceFile.scriptSnapShot),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return sourceFile;
|
||||||
|
},
|
||||||
|
|
||||||
|
getKeyForCompilationSettings(settings) {
|
||||||
|
return getKeyForCompilationSettings(settings);
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseDocument(
|
||||||
|
fileName,
|
||||||
|
compilationSettings,
|
||||||
|
scriptKind,
|
||||||
|
impliedNodeFormat,
|
||||||
|
) {
|
||||||
|
const key = getKeyForCompilationSettings(compilationSettings);
|
||||||
|
return this.releaseDocumentWithKey(
|
||||||
|
/** @type {ts.Path} */ (fileName),
|
||||||
|
key,
|
||||||
|
scriptKind,
|
||||||
|
impliedNodeFormat,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseDocumentWithKey(path, key, _scriptKind, _impliedNodeFormat) {
|
||||||
|
const mapKey = path + key;
|
||||||
|
documentRegistrySourceFileCache.remove(mapKey);
|
||||||
|
},
|
||||||
|
|
||||||
|
reportStats() {
|
||||||
|
return "[]";
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
ts.deno.setIsNodeSourceFileCallback((sourceFile) => {
|
||||||
|
const fileName = sourceFile.fileName;
|
||||||
|
let isNodeSourceFile = isNodeSourceFileCache.get(fileName);
|
||||||
|
if (isNodeSourceFile == null) {
|
||||||
|
const result = ops.op_is_node_file(fileName);
|
||||||
|
isNodeSourceFile = /** @type {boolean} */ (result);
|
||||||
|
isNodeSourceFileCache.set(fileName, isNodeSourceFile);
|
||||||
|
}
|
||||||
|
return isNodeSourceFile;
|
||||||
|
});
|
||||||
|
|
||||||
/** @param {ts.DiagnosticRelatedInformation} diagnostic */
|
/** @param {ts.DiagnosticRelatedInformation} diagnostic */
|
||||||
function fromRelatedInformation({
|
function fromRelatedInformation({
|
||||||
start,
|
start,
|
||||||
|
@ -189,6 +390,10 @@ delete Object.prototype.__proto__;
|
||||||
/** Diagnostics that are intentionally ignored when compiling TypeScript in
|
/** Diagnostics that are intentionally ignored when compiling TypeScript in
|
||||||
* Deno, as they provide misleading or incorrect information. */
|
* Deno, as they provide misleading or incorrect information. */
|
||||||
const IGNORED_DIAGNOSTICS = [
|
const IGNORED_DIAGNOSTICS = [
|
||||||
|
// TS1452: 'resolution-mode' assertions are only supported when `moduleResolution` is `node16` or `nodenext`.
|
||||||
|
// We specify the resolution mode to be CommonJS for some npm files and this
|
||||||
|
// diagnostic gets generated even though we're using custom module resolution.
|
||||||
|
1452,
|
||||||
// TS2306: File '.../index.d.ts' is not a module.
|
// TS2306: File '.../index.d.ts' is not a module.
|
||||||
// We get this for `x-typescript-types` declaration files which don't export
|
// We get this for `x-typescript-types` declaration files which don't export
|
||||||
// anything. We prefer to treat these as modules with no exports.
|
// anything. We prefer to treat these as modules with no exports.
|
||||||
|
@ -228,10 +433,12 @@ delete Object.prototype.__proto__;
|
||||||
target: ts.ScriptTarget.ESNext,
|
target: ts.ScriptTarget.ESNext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// todo(dsherret): can we remove this and just use ts.OperationCanceledException?
|
||||||
/** Error thrown on cancellation. */
|
/** Error thrown on cancellation. */
|
||||||
class OperationCanceledError extends Error {
|
class OperationCanceledError extends Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo(dsherret): we should investigate if throttling is really necessary
|
||||||
/**
|
/**
|
||||||
* Inspired by ThrottledCancellationToken in ts server.
|
* Inspired by ThrottledCancellationToken in ts server.
|
||||||
*
|
*
|
||||||
|
@ -291,13 +498,10 @@ delete Object.prototype.__proto__;
|
||||||
_onError,
|
_onError,
|
||||||
_shouldCreateNewSourceFile,
|
_shouldCreateNewSourceFile,
|
||||||
) {
|
) {
|
||||||
|
const createOptions = getCreateSourceFileOptions(languageVersion);
|
||||||
debug(
|
debug(
|
||||||
`host.getSourceFile("${specifier}", ${
|
`host.getSourceFile("${specifier}", ${
|
||||||
ts.ScriptTarget[
|
ts.ScriptTarget[createOptions.languageVersion]
|
||||||
isCreateSourceFileOptions(languageVersion)
|
|
||||||
? languageVersion.languageVersion
|
|
||||||
: languageVersion
|
|
||||||
]
|
|
||||||
})`,
|
})`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -320,7 +524,12 @@ delete Object.prototype.__proto__;
|
||||||
sourceFile = ts.createSourceFile(
|
sourceFile = ts.createSourceFile(
|
||||||
specifier,
|
specifier,
|
||||||
data,
|
data,
|
||||||
languageVersion,
|
{
|
||||||
|
...createOptions,
|
||||||
|
impliedNodeFormat: isCjsCache.has(specifier)
|
||||||
|
? ts.ModuleKind.CommonJS
|
||||||
|
: ts.ModuleKind.ESNext,
|
||||||
|
},
|
||||||
false,
|
false,
|
||||||
scriptKind,
|
scriptKind,
|
||||||
);
|
);
|
||||||
|
@ -355,6 +564,50 @@ delete Object.prototype.__proto__;
|
||||||
getNewLine() {
|
getNewLine() {
|
||||||
return "\n";
|
return "\n";
|
||||||
},
|
},
|
||||||
|
resolveTypeReferenceDirectives(
|
||||||
|
typeDirectiveNames,
|
||||||
|
containingFilePath,
|
||||||
|
redirectedReference,
|
||||||
|
options,
|
||||||
|
containingFileMode,
|
||||||
|
) {
|
||||||
|
return typeDirectiveNames.map((arg) => {
|
||||||
|
/** @type {ts.FileReference} */
|
||||||
|
const fileReference = typeof arg === "string"
|
||||||
|
? {
|
||||||
|
pos: -1,
|
||||||
|
end: -1,
|
||||||
|
fileName: arg,
|
||||||
|
}
|
||||||
|
: arg;
|
||||||
|
if (fileReference.fileName.startsWith("npm:")) {
|
||||||
|
/** @type {[string, ts.Extension] | undefined} */
|
||||||
|
const resolved = ops.op_resolve({
|
||||||
|
specifiers: [fileReference.fileName],
|
||||||
|
base: containingFilePath,
|
||||||
|
})?.[0];
|
||||||
|
if (resolved) {
|
||||||
|
isCjsCache.add(resolved);
|
||||||
|
return {
|
||||||
|
primary: true,
|
||||||
|
resolvedFileName: resolved[0],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ts.resolveTypeReferenceDirective(
|
||||||
|
fileReference.fileName,
|
||||||
|
containingFilePath,
|
||||||
|
options,
|
||||||
|
host,
|
||||||
|
redirectedReference,
|
||||||
|
undefined,
|
||||||
|
containingFileMode ?? fileReference.resolutionMode,
|
||||||
|
).resolvedTypeReferenceDirective;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
resolveModuleNames(specifiers, base) {
|
resolveModuleNames(specifiers, base) {
|
||||||
debug(`host.resolveModuleNames()`);
|
debug(`host.resolveModuleNames()`);
|
||||||
debug(` base: ${base}`);
|
debug(` base: ${base}`);
|
||||||
|
@ -367,7 +620,12 @@ delete Object.prototype.__proto__;
|
||||||
if (resolved) {
|
if (resolved) {
|
||||||
const result = resolved.map((item) => {
|
const result = resolved.map((item) => {
|
||||||
if (item) {
|
if (item) {
|
||||||
|
isCjsCache.add(item);
|
||||||
const [resolvedFileName, extension] = item;
|
const [resolvedFileName, extension] = item;
|
||||||
|
if (resolvedFileName.startsWith("node:")) {
|
||||||
|
// probably means the user doesn't have @types/node, so resolve to undefined
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
resolvedFileName,
|
resolvedFileName,
|
||||||
extension,
|
extension,
|
||||||
|
@ -444,6 +702,23 @@ delete Object.prototype.__proto__;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// override the npm install @types package diagnostics to be deno specific
|
||||||
|
ts.setLocalizedDiagnosticMessages((() => {
|
||||||
|
const nodeMessage = "Cannot find name '{0}'."; // don't offer any suggestions
|
||||||
|
const jqueryMessage =
|
||||||
|
"Cannot find name '{0}'. Did you mean to import jQuery? Try adding `import $ from \"npm:jquery\";`.";
|
||||||
|
return {
|
||||||
|
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashno_2580":
|
||||||
|
nodeMessage,
|
||||||
|
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashno_2591":
|
||||||
|
nodeMessage,
|
||||||
|
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slash_2581":
|
||||||
|
jqueryMessage,
|
||||||
|
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slash_2592":
|
||||||
|
jqueryMessage,
|
||||||
|
};
|
||||||
|
})());
|
||||||
|
|
||||||
/** @type {Array<[string, number]>} */
|
/** @type {Array<[string, number]>} */
|
||||||
const stats = [];
|
const stats = [];
|
||||||
let statsStart = 0;
|
let statsStart = 0;
|
||||||
|
@ -557,7 +832,25 @@ delete Object.prototype.__proto__;
|
||||||
...program.getOptionsDiagnostics(),
|
...program.getOptionsDiagnostics(),
|
||||||
...program.getGlobalDiagnostics(),
|
...program.getGlobalDiagnostics(),
|
||||||
...program.getSemanticDiagnostics(),
|
...program.getSemanticDiagnostics(),
|
||||||
].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code));
|
].filter((diagnostic) => {
|
||||||
|
if (IGNORED_DIAGNOSTICS.includes(diagnostic.code)) {
|
||||||
|
return false;
|
||||||
|
} else if (
|
||||||
|
diagnostic.code === 1259 &&
|
||||||
|
typeof diagnostic.messageText === "string" &&
|
||||||
|
diagnostic.messageText.startsWith(
|
||||||
|
"Module '\"deno:///missing_dependency.d.ts\"' can only be default-imported using the 'allowSyntheticDefaultImports' flag",
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// For now, ignore diagnostics like:
|
||||||
|
// > TS1259 [ERROR]: Module '"deno:///missing_dependency.d.ts"' can only be default-imported using the 'allowSyntheticDefaultImports' flag
|
||||||
|
// This diagnostic has surfaced due to supporting node cjs imports because this module does `export =`.
|
||||||
|
// See discussion in https://github.com/microsoft/TypeScript/pull/51136
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// emit the tsbuildinfo file
|
// emit the tsbuildinfo file
|
||||||
// @ts-ignore: emitBuildInfo is not exposed (https://github.com/microsoft/TypeScript/issues/49871)
|
// @ts-ignore: emitBuildInfo is not exposed (https://github.com/microsoft/TypeScript/issues/49871)
|
||||||
|
@ -922,13 +1215,14 @@ delete Object.prototype.__proto__;
|
||||||
}
|
}
|
||||||
hasStarted = true;
|
hasStarted = true;
|
||||||
cwd = rootUri;
|
cwd = rootUri;
|
||||||
languageService = ts.createLanguageService(host);
|
languageService = ts.createLanguageService(host, documentRegistry);
|
||||||
setLogDebug(debugFlag, "TSLS");
|
setLogDebug(debugFlag, "TSLS");
|
||||||
debug("serverInit()");
|
debug("serverInit()");
|
||||||
}
|
}
|
||||||
|
|
||||||
function serverRestart() {
|
function serverRestart() {
|
||||||
languageService = ts.createLanguageService(host);
|
languageService = ts.createLanguageService(host, documentRegistry);
|
||||||
|
isNodeSourceFileCache.clear();
|
||||||
debug("serverRestart()");
|
debug("serverRestart()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
cli/tsc/compiler.d.ts
vendored
7
cli/tsc/compiler.d.ts
vendored
|
@ -12,6 +12,7 @@ declare global {
|
||||||
var normalizePath: (path: string) => string;
|
var normalizePath: (path: string) => string;
|
||||||
interface SourceFile {
|
interface SourceFile {
|
||||||
version?: string;
|
version?: string;
|
||||||
|
fileName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CompilerHost {
|
interface CompilerHost {
|
||||||
|
@ -24,6 +25,12 @@ declare global {
|
||||||
}
|
}
|
||||||
|
|
||||||
var performance: Performance;
|
var performance: Performance;
|
||||||
|
|
||||||
|
namespace deno {
|
||||||
|
function setIsNodeSourceFileCallback(
|
||||||
|
callback: (sourceFile: SourceFile) => boolean,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ts {
|
namespace ts {
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub use resolution::package_imports_resolve;
|
||||||
pub use resolution::package_resolve;
|
pub use resolution::package_resolve;
|
||||||
pub use resolution::NodeModuleKind;
|
pub use resolution::NodeModuleKind;
|
||||||
pub use resolution::DEFAULT_CONDITIONS;
|
pub use resolution::DEFAULT_CONDITIONS;
|
||||||
|
pub use resolution::TYPES_CONDITIONS;
|
||||||
|
|
||||||
pub trait NodePermissions {
|
pub trait NodePermissions {
|
||||||
fn check_read(&mut self, path: &Path) -> Result<(), AnyError>;
|
fn check_read(&mut self, path: &Path) -> Result<(), AnyError>;
|
||||||
|
@ -38,6 +39,7 @@ pub trait RequireNpmResolver {
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &Path,
|
referrer: &Path,
|
||||||
|
conditions: &[&str],
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, AnyError>;
|
||||||
|
|
||||||
fn resolve_package_folder_from_path(
|
fn resolve_package_folder_from_path(
|
||||||
|
@ -304,6 +306,7 @@ fn op_require_resolve_deno_dir(
|
||||||
.resolve_package_folder_from_package(
|
.resolve_package_folder_from_package(
|
||||||
&request,
|
&request,
|
||||||
&PathBuf::from(parent_filename),
|
&PathBuf::from(parent_filename),
|
||||||
|
DEFAULT_CONDITIONS,
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
.map(|p| p.to_string_lossy().to_string())
|
||||||
|
|
|
@ -50,6 +50,12 @@ impl PackageJson {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
) -> Result<PackageJson, AnyError> {
|
) -> Result<PackageJson, AnyError> {
|
||||||
resolver.ensure_read_permission(&path)?;
|
resolver.ensure_read_permission(&path)?;
|
||||||
|
Self::load_skip_read_permission(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_skip_read_permission(
|
||||||
|
path: PathBuf,
|
||||||
|
) -> Result<PackageJson, AnyError> {
|
||||||
let source = match std::fs::read_to_string(&path) {
|
let source = match std::fs::read_to_string(&path) {
|
||||||
Ok(source) => source,
|
Ok(source) => source,
|
||||||
Err(err) if err.kind() == ErrorKind::NotFound => {
|
Err(err) if err.kind() == ErrorKind::NotFound => {
|
||||||
|
|
|
@ -19,6 +19,7 @@ use crate::RequireNpmResolver;
|
||||||
|
|
||||||
pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"];
|
pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"];
|
||||||
pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"];
|
pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"];
|
||||||
|
pub static TYPES_CONDITIONS: &[&str] = &["types"];
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum NodeModuleKind {
|
pub enum NodeModuleKind {
|
||||||
|
@ -251,13 +252,17 @@ fn resolve_package_target_string(
|
||||||
};
|
};
|
||||||
let package_json_url =
|
let package_json_url =
|
||||||
ModuleSpecifier::from_file_path(package_json_path).unwrap();
|
ModuleSpecifier::from_file_path(package_json_path).unwrap();
|
||||||
return package_resolve(
|
return match package_resolve(
|
||||||
&export_target,
|
&export_target,
|
||||||
&package_json_url,
|
&package_json_url,
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
conditions,
|
conditions,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
);
|
) {
|
||||||
|
Ok(Some(path)) => Ok(path),
|
||||||
|
Ok(None) => Err(generic_error("not found")),
|
||||||
|
Err(err) => Err(err),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(throw_invalid_package_target(
|
return Err(throw_invalid_package_target(
|
||||||
|
@ -593,7 +598,7 @@ pub fn package_resolve(
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
npm_resolver: &dyn RequireNpmResolver,
|
npm_resolver: &dyn RequireNpmResolver,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<Option<PathBuf>, AnyError> {
|
||||||
let (package_name, package_subpath, _is_scoped) =
|
let (package_name, package_subpath, _is_scoped) =
|
||||||
parse_package_name(specifier, referrer)?;
|
parse_package_name(specifier, referrer)?;
|
||||||
|
|
||||||
|
@ -611,13 +616,15 @@ pub fn package_resolve(
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
conditions,
|
conditions,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
);
|
)
|
||||||
|
.map(Some);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let package_dir_path = npm_resolver.resolve_package_folder_from_package(
|
let package_dir_path = npm_resolver.resolve_package_folder_from_package(
|
||||||
&package_name,
|
&package_name,
|
||||||
&referrer.to_file_path().unwrap(),
|
&referrer.to_file_path().unwrap(),
|
||||||
|
conditions,
|
||||||
)?;
|
)?;
|
||||||
let package_json_path = package_dir_path.join("package.json");
|
let package_json_path = package_dir_path.join("package.json");
|
||||||
|
|
||||||
|
@ -645,13 +652,16 @@ pub fn package_resolve(
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
conditions,
|
conditions,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
);
|
)
|
||||||
|
.map(Some);
|
||||||
}
|
}
|
||||||
if package_subpath == "." {
|
if package_subpath == "." {
|
||||||
return legacy_main_resolve(&package_json, referrer_kind);
|
return legacy_main_resolve(&package_json, referrer_kind, conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(package_json.path.parent().unwrap().join(&package_subpath))
|
Ok(Some(
|
||||||
|
package_json.path.parent().unwrap().join(&package_subpath),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_package_scope_config(
|
pub fn get_package_scope_config(
|
||||||
|
@ -706,41 +716,40 @@ fn file_exists(path: &Path) -> bool {
|
||||||
pub fn legacy_main_resolve(
|
pub fn legacy_main_resolve(
|
||||||
package_json: &PackageJson,
|
package_json: &PackageJson,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
) -> Result<PathBuf, AnyError> {
|
conditions: &[&str],
|
||||||
let maybe_main = package_json.main(referrer_kind);
|
) -> Result<Option<PathBuf>, AnyError> {
|
||||||
|
let is_types = conditions == TYPES_CONDITIONS;
|
||||||
|
let maybe_main = if is_types {
|
||||||
|
package_json.types.as_ref()
|
||||||
|
} else {
|
||||||
|
package_json.main(referrer_kind)
|
||||||
|
};
|
||||||
let mut guess;
|
let mut guess;
|
||||||
|
|
||||||
if let Some(main) = maybe_main {
|
if let Some(main) = maybe_main {
|
||||||
guess = package_json.path.parent().unwrap().join(main).clean();
|
guess = package_json.path.parent().unwrap().join(main).clean();
|
||||||
if file_exists(&guess) {
|
if file_exists(&guess) {
|
||||||
return Ok(guess);
|
return Ok(Some(guess));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
// todo(dsherret): investigate exactly how node handles this
|
// todo(dsherret): investigate exactly how node and typescript handles this
|
||||||
let endings = match referrer_kind {
|
let endings = if is_types {
|
||||||
NodeModuleKind::Cjs => vec![
|
match referrer_kind {
|
||||||
".js",
|
NodeModuleKind::Cjs => {
|
||||||
".cjs",
|
vec![".d.ts", ".d.cts", "/index.d.ts", "/index.d.cts"]
|
||||||
".json",
|
}
|
||||||
".node",
|
NodeModuleKind::Esm => vec![
|
||||||
"/index.js",
|
".d.ts",
|
||||||
"/index.cjs",
|
".d.mts",
|
||||||
"/index.json",
|
"/index.d.ts",
|
||||||
"/index.node",
|
"/index.d.mts",
|
||||||
],
|
".d.cts",
|
||||||
NodeModuleKind::Esm => vec![
|
"/index.d.cts",
|
||||||
".js",
|
],
|
||||||
".mjs",
|
}
|
||||||
".json",
|
} else {
|
||||||
".node",
|
vec![".js", "/index.js"]
|
||||||
"/index.js",
|
|
||||||
"/index.mjs",
|
|
||||||
".cjs",
|
|
||||||
"/index.cjs",
|
|
||||||
"/index.json",
|
|
||||||
"/index.node",
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
for ending in endings {
|
for ending in endings {
|
||||||
guess = package_json
|
guess = package_json
|
||||||
|
@ -757,21 +766,18 @@ pub fn legacy_main_resolve(
|
||||||
|
|
||||||
if found {
|
if found {
|
||||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||||
return Ok(guess);
|
return Ok(Some(guess));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let index_file_names = match referrer_kind {
|
let index_file_names = if is_types {
|
||||||
NodeModuleKind::Cjs => {
|
// todo(dsherret): investigate exactly how typescript does this
|
||||||
vec!["index.js", "index.cjs", "index.json", "index.node"]
|
match referrer_kind {
|
||||||
|
NodeModuleKind::Cjs => vec!["index.d.ts", "index.d.cts"],
|
||||||
|
NodeModuleKind::Esm => vec!["index.d.ts", "index.d.mts", "index.d.cts"],
|
||||||
}
|
}
|
||||||
NodeModuleKind::Esm => vec![
|
} else {
|
||||||
"index.js",
|
vec!["index.js"]
|
||||||
"index.mjs",
|
|
||||||
"index.cjs",
|
|
||||||
"index.json",
|
|
||||||
"index.node",
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
for index_file_name in index_file_names {
|
for index_file_name in index_file_names {
|
||||||
guess = package_json
|
guess = package_json
|
||||||
|
@ -782,11 +788,11 @@ pub fn legacy_main_resolve(
|
||||||
.clean();
|
.clean();
|
||||||
if file_exists(&guess) {
|
if file_exists(&guess) {
|
||||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||||
return Ok(guess);
|
return Ok(Some(guess));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(generic_error("not found"))
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -35,6 +35,7 @@ tar = "0.4.38"
|
||||||
tokio = { version = "1.21", features = ["full"] }
|
tokio = { version = "1.21", features = ["full"] }
|
||||||
tokio-rustls = "0.23"
|
tokio-rustls = "0.23"
|
||||||
tokio-tungstenite = "0.16"
|
tokio-tungstenite = "0.16"
|
||||||
|
url = { version = "2.3.1", features = ["serde", "expose_internals"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
pty = "0.2.2"
|
pty = "0.2.2"
|
||||||
|
|
|
@ -49,6 +49,7 @@ use tokio::net::TcpStream;
|
||||||
use tokio_rustls::rustls;
|
use tokio_rustls::rustls;
|
||||||
use tokio_rustls::TlsAcceptor;
|
use tokio_rustls::TlsAcceptor;
|
||||||
use tokio_tungstenite::accept_async;
|
use tokio_tungstenite::accept_async;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod assertions;
|
pub mod assertions;
|
||||||
pub mod lsp;
|
pub mod lsp;
|
||||||
|
@ -120,10 +121,19 @@ pub fn napi_tests_path() -> PathBuf {
|
||||||
root_path().join("test_napi")
|
root_path().join("test_napi")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test server registry url.
|
||||||
|
pub fn npm_registry_url() -> String {
|
||||||
|
"http://localhost:4545/npm/registry/".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn std_path() -> PathBuf {
|
pub fn std_path() -> PathBuf {
|
||||||
root_path().join("test_util").join("std")
|
root_path().join("test_util").join("std")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn std_file_url() -> String {
|
||||||
|
Url::from_directory_path(std_path()).unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn target_dir() -> PathBuf {
|
pub fn target_dir() -> PathBuf {
|
||||||
let current_exe = std::env::current_exe().unwrap();
|
let current_exe = std::env::current_exe().unwrap();
|
||||||
let target_dir = current_exe.parent().unwrap().parent().unwrap();
|
let target_dir = current_exe.parent().unwrap().parent().unwrap();
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use crate::npm_registry_url;
|
||||||
|
use crate::std_file_url;
|
||||||
|
|
||||||
use super::new_deno_dir;
|
use super::new_deno_dir;
|
||||||
use super::TempDir;
|
use super::TempDir;
|
||||||
|
|
||||||
|
@ -230,6 +233,8 @@ impl LspClient {
|
||||||
let mut command = Command::new(deno_exe);
|
let mut command = Command::new(deno_exe);
|
||||||
command
|
command
|
||||||
.env("DENO_DIR", deno_dir.path())
|
.env("DENO_DIR", deno_dir.path())
|
||||||
|
.env("DENO_NODE_COMPAT_URL", std_file_url())
|
||||||
|
.env("DENO_NPM_REGISTRY", npm_registry_url())
|
||||||
.arg("lsp")
|
.arg("lsp")
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped());
|
.stdout(Stdio::piped());
|
||||||
|
|
Loading…
Reference in a new issue