summaryrefslogtreecommitdiff
path: root/cli/lsp
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp')
-rw-r--r--cli/lsp/diagnostics.rs49
-rw-r--r--cli/lsp/documents.rs178
-rw-r--r--cli/lsp/language_server.rs50
-rw-r--r--cli/lsp/tsc.rs27
4 files changed, 232 insertions, 72 deletions
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs
index aef5ae889..aac6e5862 100644
--- a/cli/lsp/diagnostics.rs
+++ b/cli/lsp/diagnostics.rs
@@ -458,6 +458,13 @@ async fn generate_lint_diagnostics(
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();
diagnostics_vec.push((
document.specifier().clone(),
@@ -597,6 +604,8 @@ pub enum DenoDiagnostic {
NoCacheBlob,
/// A data module was not found in the cache.
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.
NoLocal(ModuleSpecifier),
/// The specifier resolved to a remote specifier that was redirected to
@@ -622,6 +631,7 @@ impl DenoDiagnostic {
Self::NoCache(_) => "no-cache",
Self::NoCacheBlob => "no-cache-blob",
Self::NoCacheData(_) => "no-cache-data",
+ Self::NoCacheNpm(_, _) => "no-cache-npm",
Self::NoLocal(_) => "no-local",
Self::Redirect { .. } => "redirect",
Self::ResolutionError(err) => match err {
@@ -690,16 +700,17 @@ impl DenoDiagnostic {
}),
..Default::default()
},
- "no-cache" | "no-cache-data" => {
+ "no-cache" | "no-cache-data" | "no-cache-npm" => {
let data = diagnostic
.data
.clone()
.ok_or_else(|| anyhow!("Diagnostic is missing data"))?;
let data: DiagnosticDataSpecifier = serde_json::from_value(data)?;
- let title = if code == "no-cache" {
- format!("Cache \"{}\" and its dependencies.", data.specifier)
- } else {
- "Cache the data URL and its dependencies.".to_string()
+ let title = match code.as_str() {
+ "no-cache" | "no-cache-npm" => {
+ format!("Cache \"{}\" and its dependencies.", data.specifier)
+ }
+ _ => "Cache the data URL and its dependencies.".to_string(),
};
lsp::CodeAction {
title,
@@ -757,6 +768,7 @@ impl DenoDiagnostic {
code.as_str(),
"import-map-remap"
| "no-cache"
+ | "no-cache-npm"
| "no-cache-data"
| "no-assert-type"
| "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::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::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::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),
@@ -847,8 +860,20 @@ fn diagnose_resolved(
.push(DenoDiagnostic::NoAssertType.to_lsp_diagnostic(&range)),
}
}
- } else if NpmPackageReference::from_specifier(specifier).is_ok() {
- // ignore npm specifiers for now
+ } else if let Ok(pkg_ref) = NpmPackageReference::from_specifier(specifier)
+ {
+ 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 {
// 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
@@ -882,6 +907,12 @@ fn diagnose_dependency(
dependency_key: &str,
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 Resolved::Ok {
specifier, range, ..
@@ -938,8 +969,8 @@ async fn generate_deno_diagnostics(
&mut diagnostics,
snapshot,
specifier,
- &dependency_key,
- &dependency,
+ dependency_key,
+ dependency,
);
}
}
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs
index 61db899e5..57216eecb 100644
--- a/cli/lsp/documents.rs
+++ b/cli/lsp/documents.rs
@@ -12,6 +12,13 @@ use crate::file_fetcher::SUPPORTED_SCHEMES;
use crate::fs_util::specifier_to_file_path;
use crate::http_cache;
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::JsxResolver;
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 =
Option<Result<deno_graph::Module, deno_graph::ModuleGraphError>>;
type MaybeParsedSourceResult =
@@ -217,7 +247,7 @@ type MaybeParsedSourceResult =
#[derive(Debug, Clone)]
struct DocumentInner {
/// 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,
line_index: Arc<LineIndex>,
maybe_language_id: Option<LanguageId>,
@@ -249,12 +279,9 @@ impl Document {
maybe_headers,
maybe_resolver,
);
- let dependencies = if let Some(Ok(module)) = &maybe_module {
- Arc::new(module.dependencies.clone())
- } else {
- Arc::new(BTreeMap::new())
- };
- // todo(dsherret): retrieve this from the parsed source if it
+ let dependencies =
+ Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
+ // todo(dsherret): retrieve this from the parsed source if it exists
let text_info = SourceTextInfo::new(content);
let line_index = Arc::new(LineIndex::new(text_info.text_str()));
Self(Arc::new(DocumentInner {
@@ -289,11 +316,8 @@ impl Document {
} else {
(None, None)
};
- let dependencies = if let Some(Ok(module)) = &maybe_module {
- Arc::new(module.dependencies.clone())
- } else {
- Arc::new(BTreeMap::new())
- };
+ let dependencies =
+ Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
let source = SourceTextInfo::new(content);
let line_index = Arc::new(LineIndex::new(source.text_str()));
Self(Arc::new(DocumentInner {
@@ -355,9 +379,9 @@ impl Document {
(None, None)
};
let dependencies = if let Some(Ok(module)) = &maybe_module {
- Arc::new(module.dependencies.clone())
+ Arc::new(DocumentDependencies::from_module(module))
} else {
- self.0.dependencies.clone()
+ self.0.dependencies.clone() // use the last known good
};
let text_info = SourceTextInfo::new(content);
let line_index = if index_valid == IndexValid::All {
@@ -435,15 +459,9 @@ impl Document {
}
pub fn maybe_types_dependency(&self) -> deno_graph::Resolved {
- let module_result = match self.0.maybe_module.as_ref() {
- Some(module_result) => module_result,
- _ => 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() {
+ if let Some((_, maybe_dep)) =
+ self.0.dependencies.maybe_types_dependency.as_ref()
+ {
maybe_dep.clone()
} else {
deno_graph::Resolved::None
@@ -479,13 +497,8 @@ impl Document {
self.0.maybe_navigation_tree.clone()
}
- pub fn dependencies(&self) -> Vec<(String, deno_graph::Dependency)> {
- self
- .0
- .dependencies
- .iter()
- .map(|(s, d)| (s.clone(), d.clone()))
- .collect()
+ pub fn dependencies(&self) -> &BTreeMap<String, deno_graph::Dependency> {
+ &self.0.dependencies.deps
}
/// If the supplied position is within a dependency range, return the resolved
@@ -698,6 +711,8 @@ pub struct Documents {
maybe_import_map: Option<ImportMapResolver>,
/// The optional JSX resolver, which is used when JSX imports are configured.
maybe_jsx_resolver: Option<JsxResolver>,
+ /// The npm package requirements.
+ npm_reqs: HashSet<NpmPackageReq>,
/// Resolves a specifier to its final redirected to specifier.
specifier_resolver: Arc<SpecifierResolver>,
}
@@ -713,6 +728,7 @@ impl Documents {
imports: Default::default(),
maybe_import_map: None,
maybe_jsx_resolver: None,
+ npm_reqs: HashSet::new(),
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.
pub fn get(&self, original_specifier: &ModuleSpecifier) -> Option<Document> {
let specifier = self.specifier_resolver.resolve(original_specifier)?;
@@ -921,10 +943,28 @@ impl Documents {
&self,
specifiers: Vec<String>,
referrer: &ModuleSpecifier,
+ maybe_npm_resolver: Option<&NpmPackageResolver>,
) -> Option<Vec<Option<(ModuleSpecifier, MediaType)>>> {
let dependencies = self.get(referrer)?.0.dependencies.clone();
let mut results = Vec::new();
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 let Ok(specifier) = ModuleSpecifier::parse(&specifier) {
let media_type = MediaType::from(&specifier);
@@ -932,11 +972,11 @@ impl Documents {
} else {
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 {
- results.push(self.resolve_dependency(specifier));
+ results.push(self.resolve_dependency(specifier, maybe_npm_resolver));
} 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 {
results.push(None);
}
@@ -945,7 +985,19 @@ impl Documents {
{
// clone here to avoid double borrow of self
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 {
results.push(None);
}
@@ -1038,32 +1090,36 @@ impl Documents {
// 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());
for (specifier, doc) in documents {
- if let Some(Ok(module)) = doc.maybe_module() {
- for dependency in module.dependencies.values() {
- if let Some(dep) = dependency.get_code() {
- dependents_map
- .entry(dep.clone())
- .or_default()
- .insert(specifier.clone());
- }
- if let Some(dep) = dependency.get_type() {
- dependents_map
- .entry(dep.clone())
- .or_default()
- .insert(specifier.clone());
- }
+ for dependency in doc.dependencies().values() {
+ if let Some(dep) = dependency.get_code() {
+ dependents_map
+ .entry(dep.clone())
+ .or_default()
+ .insert(specifier.clone());
}
- if let Some((_, Resolved::Ok { specifier: dep, .. })) =
- &module.maybe_types_dependency
- {
+ if let Some(dep) = dependency.get_type() {
dependents_map
.entry(dep.clone())
.or_default()
.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.npm_reqs = npm_reqs;
self.dirty = false;
file_system_docs.dirty = false;
}
@@ -1079,7 +1135,21 @@ impl Documents {
fn resolve_dependency(
&self,
specifier: &ModuleSpecifier,
+ maybe_npm_resolver: Option<&NpmPackageResolver>,
) -> 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 maybe_module = doc.maybe_module().and_then(|r| r.as_ref().ok());
let maybe_types_dependency = maybe_module.and_then(|m| {
@@ -1088,7 +1158,7 @@ impl Documents {
.map(|(_, resolved)| resolved.clone())
});
if let Some(Resolved::Ok { specifier, .. }) = maybe_types_dependency {
- self.resolve_dependency(&specifier)
+ self.resolve_dependency(&specifier, maybe_npm_resolver)
} else {
let media_type = doc.media_type();
Some((specifier.clone(), media_type))
@@ -1113,12 +1183,12 @@ impl 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 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(
&mut self,
specifier: &ModuleSpecifier,
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 27d69127c..a3f516615 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -66,10 +66,15 @@ use crate::args::LintConfig;
use crate::args::TsConfig;
use crate::deno_dir;
use crate::file_fetcher::get_source_from_data_url;
+use crate::file_fetcher::CacheSetting;
use crate::fs_util;
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::ProcState;
+use crate::progress_bar::ProgressBar;
use crate::tools::fmt::format_file;
use crate::tools::fmt::format_parsed_source;
@@ -87,6 +92,7 @@ pub struct StateSnapshot {
pub documents: Documents,
pub maybe_import_map: Option<Arc<ImportMap>>,
pub root_uri: Option<Url>,
+ pub maybe_npm_resolver: Option<NpmPackageResolver>,
}
#[derive(Debug)]
@@ -125,6 +131,8 @@ pub struct Inner {
pub maybe_lint_config: Option<LintConfig>,
/// A lazily create "server" for handling test run requests.
maybe_testing_server: Option<testing::TestServer>,
+ /// Resolver for npm packages.
+ npm_resolver: NpmPackageResolver,
/// A collection of measurements which instrument that performance of the LSP.
performance: Arc<Performance>,
/// A memoized version of fixable diagnostic codes retrieved from TypeScript.
@@ -250,6 +258,26 @@ impl Inner {
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 {
assets,
@@ -267,6 +295,7 @@ impl Inner {
maybe_testing_server: None,
module_registries,
module_registries_location,
+ npm_resolver,
performance,
ts_fixable_diagnostics: Default::default(),
ts_server,
@@ -435,6 +464,7 @@ impl Inner {
cache_metadata: self.cache_metadata.clone(),
documents: self.documents.clone(),
maybe_import_map: self.maybe_import_map.clone(),
+ maybe_npm_resolver: Some(self.npm_resolver.snapshotted()),
root_uri: self.config.root_uri.clone(),
})
}
@@ -828,7 +858,7 @@ impl Inner {
if let Err(err) =
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;
@@ -891,6 +921,7 @@ impl Inner {
) {
Ok(document) => {
if document.is_diagnosable() {
+ self.refresh_npm_specifiers().await;
self
.diagnostics_server
.invalidate(&self.documents.dependents(&specifier));
@@ -903,6 +934,13 @@ impl Inner {
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) {
let mark = self.performance.mark("did_close", Some(&params));
if params.text_document.uri.scheme() == "deno" {
@@ -917,6 +955,7 @@ impl Inner {
error!("{}", err);
}
if self.is_diagnosable(&specifier) {
+ self.refresh_npm_specifiers().await;
let mut specifiers = self.documents.dependents(&specifier);
specifiers.push(specifier.clone());
self.diagnostics_server.invalidate(&specifiers);
@@ -1135,7 +1174,7 @@ impl Inner {
Ok(None) => Some(Vec::new()),
Err(err) => {
// TODO(lucacasonato): handle error properly
- warn!("Format error: {}", err);
+ warn!("Format error: {:#}", err);
None
}
}
@@ -2476,6 +2515,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
let has_specifier_settings =
inner.config.has_specifier_settings(&specifier);
if document.is_diagnosable() {
+ inner.refresh_npm_specifiers().await;
let specifiers = inner.documents.dependents(&specifier);
inner.diagnostics_server.invalidate(&specifiers);
// don't send diagnostics yet if we don't have the specifier settings
@@ -2834,7 +2874,7 @@ impl Inner {
.collect::<HashMap<_, _>>();
let ps = ProcState::from_options(Arc::new(cli_options)).await?;
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,
open_docs: &open_docs,
};
@@ -2870,6 +2910,9 @@ impl Inner {
ca_stores: None,
ca_file: 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()
},
self.maybe_config_file.clone(),
@@ -2892,6 +2935,7 @@ impl Inner {
// For that we're invalidating all the existing diagnostics and restarting
// the language server for TypeScript (as it might hold to some stale
// documents).
+ self.refresh_npm_specifiers().await;
self.diagnostics_server.invalidate_all();
let _: bool = self
.ts_server
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index 6c2136990..bed06e088 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -2679,6 +2679,20 @@ fn op_is_cancelled(state: &mut OpState) -> bool {
}
#[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]
fn op_load(
state: &mut OpState,
args: SpecifierArgs,
@@ -2692,7 +2706,7 @@ fn op_load(
Some(doc) => {
json!({
"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),
})
}
@@ -2709,11 +2723,11 @@ fn op_resolve(
let mark = state.performance.mark("op_resolve", Some(&args));
let referrer = state.normalize_specifier(&args.base)?;
- let result = if let Some(resolved) = state
- .state_snapshot
- .documents
- .resolve(args.specifiers, &referrer)
- {
+ let result = if let Some(resolved) = state.state_snapshot.documents.resolve(
+ args.specifiers,
+ &referrer,
+ state.state_snapshot.maybe_npm_resolver.as_ref(),
+ ) {
Ok(
resolved
.into_iter()
@@ -2789,6 +2803,7 @@ fn init_extension(performance: Arc<Performance>) -> Extension {
.ops(vec![
op_exists::decl(),
op_is_cancelled::decl(),
+ op_is_node_file::decl(),
op_load::decl(),
op_resolve::decl(),
op_respond::decl(),