1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00
David Sherret 2024-05-28 14:58:43 -04:00 committed by GitHub
parent cd8f5f53f7
commit 448fe67b7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
141 changed files with 1163 additions and 493 deletions

30
Cargo.lock generated
View file

@ -1250,11 +1250,10 @@ dependencies = [
[[package]] [[package]]
name = "deno_cache_dir" name = "deno_cache_dir"
version = "0.7.1" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cf517bddfd22d79d0f284500318e3f9aea193536c2b61cbf6ce7b50a85f1b6a" checksum = "4036ac8ce97244e2a66df7b97412592acaf14671900460d28415703ad790cd70"
dependencies = [ dependencies = [
"anyhow",
"deno_media_type", "deno_media_type",
"indexmap", "indexmap",
"log", "log",
@ -1386,9 +1385,9 @@ dependencies = [
[[package]] [[package]]
name = "deno_doc" name = "deno_doc"
version = "0.135.0" version = "0.137.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2c39bbe2769f6e8bfba1a99d7656e6994474c48fd2085ed82b59556e9d398dd" checksum = "57f13d6254b2e05b014e8464647025fa28ef2f385c9c102744a27bd788eb3ebe"
dependencies = [ dependencies = [
"ammonia", "ammonia",
"anyhow", "anyhow",
@ -1411,9 +1410,9 @@ dependencies = [
[[package]] [[package]]
name = "deno_emit" name = "deno_emit"
version = "0.40.3" version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80b80fef2bf1b6e14712633975f7f39a3b29b95a5769cafcb959ffa1a84b7680" checksum = "ebe4b6c67f21a73901e962e92d51065f3c1bb42d2195bca8c2fef9f1808c4c2d"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.21.7", "base64 0.21.7",
@ -1479,9 +1478,9 @@ dependencies = [
[[package]] [[package]]
name = "deno_graph" name = "deno_graph"
version = "0.75.2" version = "0.77.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a68ddc87ce88c0a2568277ee6caabf37890128710910416c09cd6f6a8931dba6" checksum = "e94a8739bb6087061f8419e4c1719459a144ef477ab649dca597a0603290ec82"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1606,13 +1605,12 @@ dependencies = [
[[package]] [[package]]
name = "deno_lockfile" name = "deno_lockfile"
version = "0.19.0" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835418ae924f25ab20f508bf6240193b22d893519d44432b670a27b8fb1efeb" checksum = "23120f905aec2deed858820113e089551025b74e261c5c404812cd8e61421379"
dependencies = [ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2",
"thiserror", "thiserror",
] ]
@ -1735,9 +1733,9 @@ dependencies = [
[[package]] [[package]]
name = "deno_npm" name = "deno_npm"
version = "0.20.2" version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab92fbe02da596534ae84e2efca2f7dc5e26ca5fc972bf17701f0899784c2a8f" checksum = "b99fac4a31098e2466f97576b53a9860d8e7ad1df2792a22d5b3209ca3bd2924"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -2540,9 +2538,9 @@ dependencies = [
[[package]] [[package]]
name = "eszip" name = "eszip"
version = "0.69.0" version = "0.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f606daca1ce18c69ccdabc59aa1c7e077356b8ffcd74e12c7646f545320a2fd" checksum = "e5f9947a8dd5ba292461c84a5bf142497e2840c4165994c5c3b3ae4954d38fef"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.21.7", "base64 0.21.7",

View file

@ -47,7 +47,7 @@ deno_ast = { version = "=0.38.2", features = ["transpiling"] }
deno_core = { version = "0.283.0" } deno_core = { version = "0.283.0" }
deno_bench_util = { version = "0.147.0", path = "./bench_util" } deno_bench_util = { version = "0.147.0", path = "./bench_util" }
deno_lockfile = "0.19.0" deno_lockfile = "0.20.0"
deno_media_type = { version = "0.1.4", features = ["module_specifier"] } deno_media_type = { version = "0.1.4", features = ["module_specifier"] }
deno_permissions = { version = "0.13.0", path = "./runtime/permissions" } deno_permissions = { version = "0.13.0", path = "./runtime/permissions" }
deno_runtime = { version = "0.161.0", path = "./runtime" } deno_runtime = { version = "0.161.0", path = "./runtime" }
@ -100,7 +100,7 @@ chrono = { version = "0.4", default-features = false, features = ["std", "serde"
console_static_text = "=0.8.1" console_static_text = "=0.8.1"
data-encoding = "2.3.3" data-encoding = "2.3.3"
data-url = "=0.3.0" data-url = "=0.3.0"
deno_cache_dir = "=0.7.1" deno_cache_dir = "=0.10.0"
dlopen2 = "0.6.1" dlopen2 = "0.6.1"
ecb = "=0.1.2" ecb = "=0.1.2"
elliptic-curve = { version = "0.13.4", features = ["alloc", "arithmetic", "ecdh", "std", "pem"] } elliptic-curve = { version = "0.13.4", features = ["alloc", "arithmetic", "ecdh", "std", "pem"] }

View file

@ -67,17 +67,17 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposa
deno_cache_dir = { workspace = true } deno_cache_dir = { workspace = true }
deno_config = "=0.16.3" deno_config = "=0.16.3"
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] } deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_doc = { version = "=0.135.0", features = ["html", "syntect"] } deno_doc = { version = "=0.137.0", features = ["html", "syntect"] }
deno_emit = "=0.40.3" deno_emit = "=0.41.0"
deno_graph = { version = "=0.75.2", features = ["tokio_executor"] } deno_graph = { version = "=0.77.0", features = ["tokio_executor"] }
deno_lint = { version = "=0.58.4", features = ["docs"] } deno_lint = { version = "=0.58.4", features = ["docs"] }
deno_lockfile.workspace = true deno_lockfile.workspace = true
deno_npm = "=0.20.2" deno_npm = "=0.21.0"
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] } deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_semver = "=0.5.4" deno_semver = "=0.5.4"
deno_task_shell = "=0.16.1" deno_task_shell = "=0.16.1"
deno_terminal.workspace = true deno_terminal.workspace = true
eszip = "=0.69.0" eszip = "=0.70.1"
napi_sym.workspace = true napi_sym.workspace = true
async-trait.workspace = true async-trait.workspace = true

View file

@ -2,10 +2,13 @@
use std::path::PathBuf; use std::path::PathBuf;
use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_runtime::deno_node::PackageJson; use deno_runtime::deno_node::PackageJson;
use crate::args::ConfigFile; use crate::args::ConfigFile;
use crate::cache;
use crate::util::fs::atomic_write_file;
use crate::Flags; use crate::Flags;
use super::DenoSubcommand; use super::DenoSubcommand;
@ -13,7 +16,6 @@ use super::InstallFlags;
use super::InstallKind; use super::InstallKind;
pub use deno_lockfile::Lockfile; pub use deno_lockfile::Lockfile;
pub use deno_lockfile::LockfileError;
pub fn discover( pub fn discover(
flags: &Flags, flags: &Flags,
@ -54,6 +56,34 @@ pub fn discover(
}, },
}; };
let lockfile = Lockfile::new(filename, flags.lock_write)?; let lockfile = if flags.lock_write {
Lockfile::new_empty(filename, true)
} else {
read_lockfile_at_path(filename)?
};
Ok(Some(lockfile)) Ok(Some(lockfile))
} }
pub fn read_lockfile_at_path(filename: PathBuf) -> Result<Lockfile, AnyError> {
match std::fs::read_to_string(&filename) {
Ok(text) => Ok(Lockfile::with_lockfile_content(filename, &text, false)?),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
Ok(Lockfile::new_empty(filename, false))
}
Err(err) => Err(err).with_context(|| {
format!("Failed reading lockfile '{}'", filename.display())
}),
}
}
pub fn write_lockfile_if_has_changes(
lockfile: &Lockfile,
) -> Result<(), AnyError> {
let Some(bytes) = lockfile.resolve_write_bytes() else {
return Ok(()); // nothing to do
};
// do an atomic write to reduce the chance of multiple deno
// processes corrupting the file
atomic_write_file(&lockfile.filename, bytes, cache::CACHE_PERM)
.context("Failed writing lockfile.")
}

View file

@ -34,8 +34,9 @@ pub use deno_config::TsConfigType;
pub use deno_config::TsTypeLib; pub use deno_config::TsTypeLib;
pub use deno_config::WorkspaceConfig; pub use deno_config::WorkspaceConfig;
pub use flags::*; pub use flags::*;
pub use lockfile::read_lockfile_at_path;
pub use lockfile::write_lockfile_if_has_changes;
pub use lockfile::Lockfile; pub use lockfile::Lockfile;
pub use lockfile::LockfileError;
pub use package_json::PackageJsonDepsProvider; pub use package_json::PackageJsonDepsProvider;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;

2
cli/cache/mod.rs vendored
View file

@ -228,7 +228,7 @@ impl Loader for FetchCacher {
LoaderCacheSetting::Reload => { LoaderCacheSetting::Reload => {
if matches!(file_fetcher.cache_setting(), CacheSetting::Only) { if matches!(file_fetcher.cache_setting(), CacheSetting::Only) {
return Err(deno_core::anyhow::anyhow!( return Err(deno_core::anyhow::anyhow!(
"Failed to resolve version constraint. Try running again without --cached-only" "Could not resolve version constraint using only cached data. Try running again without --cached-only"
)); ));
} }
Some(CacheSetting::ReloadAll) Some(CacheSetting::ReloadAll)

View file

@ -150,8 +150,9 @@ pub struct ModuleInfoCacheModuleAnalyzer<'a> {
parser: &'a dyn ModuleParser, parser: &'a dyn ModuleParser,
} }
#[async_trait::async_trait(?Send)]
impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> { impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> {
fn analyze( async fn analyze(
&self, &self,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
source: Arc<str>, source: Arc<str>,
@ -176,8 +177,9 @@ impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> {
} }
// otherwise, get the module info from the parsed source cache // otherwise, get the module info from the parsed source cache
// todo(23858): take advantage of this being async
let analyzer = ParserModuleAnalyzer::new(self.parser); let analyzer = ParserModuleAnalyzer::new(self.parser);
let module_info = analyzer.analyze(specifier, source, media_type)?; let module_info = analyzer.analyze(specifier, source, media_type).await?;
// then attempt to cache it // then attempt to cache it
if let Err(err) = self.module_info_cache.set_module_info( if let Err(err) = self.module_info_cache.set_module_info(

View file

@ -14,6 +14,7 @@ use deno_core::error::AnyError;
use deno_graph::source::ResolveError; use deno_graph::source::ResolveError;
use deno_graph::ModuleError; use deno_graph::ModuleError;
use deno_graph::ModuleGraphError; use deno_graph::ModuleGraphError;
use deno_graph::ModuleLoadError;
use deno_graph::ResolutionError; use deno_graph::ResolutionError;
use import_map::ImportMapError; use import_map::ImportMapError;
use std::fmt::Write; use std::fmt::Write;
@ -27,24 +28,56 @@ fn get_diagnostic_class(_: &ParseDiagnostic) -> &'static str {
} }
fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str { fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str {
use deno_graph::JsrLoadError;
use deno_graph::NpmLoadError;
use deno_graph::WorkspaceLoadError;
match err { match err {
ModuleGraphError::ModuleError(err) => match err {
ModuleError::LoadingErr(_, _, err) => get_error_class_name(err.as_ref()),
ModuleError::InvalidTypeAssertion { .. } => "SyntaxError",
ModuleError::ParseErr(_, diagnostic) => get_diagnostic_class(diagnostic),
ModuleError::UnsupportedMediaType { .. }
| ModuleError::UnsupportedImportAttributeType { .. } => "TypeError",
ModuleError::Missing(_, _)
| ModuleError::MissingDynamic(_, _)
| ModuleError::MissingWorkspaceMemberExports { .. }
| ModuleError::UnknownExport { .. }
| ModuleError::UnknownPackage { .. }
| ModuleError::UnknownPackageReq { .. } => "NotFound",
},
ModuleGraphError::ResolutionError(err) ModuleGraphError::ResolutionError(err)
| ModuleGraphError::TypesResolutionError(err) => { | ModuleGraphError::TypesResolutionError(err) => {
get_resolution_error_class(err) get_resolution_error_class(err)
} }
ModuleGraphError::ModuleError(err) => match err {
ModuleError::InvalidTypeAssertion { .. } => "SyntaxError",
ModuleError::ParseErr(_, diagnostic) => get_diagnostic_class(diagnostic),
ModuleError::UnsupportedMediaType { .. }
| ModuleError::UnsupportedImportAttributeType { .. } => "TypeError",
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
"NotFound"
}
ModuleError::LoadingErr(_, _, err) => match err {
ModuleLoadError::Loader(err) => get_error_class_name(err.as_ref()),
ModuleLoadError::HttpsChecksumIntegrity(_)
| ModuleLoadError::TooManyRedirects => "Error",
ModuleLoadError::NodeUnknownBuiltinModule(_) => "NotFound",
ModuleLoadError::Decode(_) => "TypeError",
ModuleLoadError::Npm(err) => match err {
NpmLoadError::NotSupportedEnvironment
| NpmLoadError::PackageReqResolution(_)
| NpmLoadError::RegistryInfo(_) => "Error",
NpmLoadError::PackageReqReferenceParse(_) => "TypeError",
},
ModuleLoadError::Jsr(err) => match err {
JsrLoadError::UnsupportedManifestChecksum
| JsrLoadError::PackageFormat(_) => "TypeError",
JsrLoadError::ContentLoadExternalSpecifier
| JsrLoadError::ContentLoad(_)
| JsrLoadError::ContentChecksumIntegrity(_)
| JsrLoadError::PackageManifestLoad(_, _)
| JsrLoadError::PackageVersionManifestChecksumIntegrity(..)
| JsrLoadError::PackageVersionManifestLoad(_, _)
| JsrLoadError::RedirectInPackage(_) => "Error",
JsrLoadError::PackageNotFound(_)
| JsrLoadError::PackageReqNotFound(_)
| JsrLoadError::PackageVersionNotFound(_)
| JsrLoadError::UnknownExport { .. } => "NotFound",
},
ModuleLoadError::Workspace(err) => match err {
WorkspaceLoadError::MemberInvalidExportPath { .. } => "TypeError",
WorkspaceLoadError::MissingMemberExports { .. } => "NotFound",
},
},
},
} }
} }

View file

@ -665,7 +665,6 @@ impl CliFactory {
self.options.clone(), self.options.clone(),
self.npm_resolver().await?.clone(), self.npm_resolver().await?.clone(),
self.module_graph_builder().await?.clone(), self.module_graph_builder().await?.clone(),
self.maybe_lockfile().clone(),
self.type_checker().await?.clone(), self.type_checker().await?.clone(),
))) )))
}) })

View file

@ -253,15 +253,30 @@ impl FileFetcher {
deno_core::resolve_import(redirect_to, specifier.as_str())?; deno_core::resolve_import(redirect_to, specifier.as_str())?;
return Ok(Some(FileOrRedirect::Redirect(redirect))); return Ok(Some(FileOrRedirect::Redirect(redirect)));
} }
let Some(bytes) = self.http_cache.read_file_bytes( let result = self.http_cache.read_file_bytes(
&cache_key, &cache_key,
maybe_checksum maybe_checksum
.as_ref() .as_ref()
.map(|c| deno_cache_dir::Checksum::new(c.as_str())), .map(|c| deno_cache_dir::Checksum::new(c.as_str())),
deno_cache_dir::GlobalToLocalCopy::Allow, deno_cache_dir::GlobalToLocalCopy::Allow,
)? );
else { let bytes = match result {
return Ok(None); Ok(Some(bytes)) => bytes,
Ok(None) => return Ok(None),
Err(err) => match err {
deno_cache_dir::CacheReadFileError::Io(err) => return Err(err.into()),
deno_cache_dir::CacheReadFileError::ChecksumIntegrity(err) => {
// convert to the equivalent deno_graph error so that it
// enhances it if this is passed to deno_graph
return Err(
deno_graph::source::ChecksumIntegrityError {
actual: err.actual,
expected: err.expected,
}
.into(),
);
}
},
}; };
Ok(Some(FileOrRedirect::File(File { Ok(Some(FileOrRedirect::File(File {

View file

@ -18,6 +18,9 @@ use crate::tools::check;
use crate::tools::check::TypeChecker; use crate::tools::check::TypeChecker;
use crate::util::file_watcher::WatcherCommunicator; use crate::util::file_watcher::WatcherCommunicator;
use crate::util::fs::canonicalize_path; use crate::util::fs::canonicalize_path;
use deno_emit::LoaderChecksum;
use deno_graph::JsrLoadError;
use deno_graph::ModuleLoadError;
use deno_runtime::fs_util::specifier_to_file_path; use deno_runtime::fs_util::specifier_to_file_path;
use deno_config::WorkspaceMemberConfig; use deno_config::WorkspaceMemberConfig;
@ -51,6 +54,9 @@ pub struct GraphValidOptions {
pub check_js: bool, pub check_js: bool,
pub follow_type_only: bool, pub follow_type_only: bool,
pub is_vendoring: bool, pub is_vendoring: bool,
/// Whether to exit the process for lockfile errors.
/// Otherwise, surfaces lockfile errors as errors.
pub exit_lockfile_errors: bool,
} }
/// Check if `roots` and their deps are available. Returns `Ok(())` if /// Check if `roots` and their deps are available. Returns `Ok(())` if
@ -62,10 +68,14 @@ pub struct GraphValidOptions {
/// for the CLI. /// for the CLI.
pub fn graph_valid( pub fn graph_valid(
graph: &ModuleGraph, graph: &ModuleGraph,
fs: Arc<dyn FileSystem>, fs: &Arc<dyn FileSystem>,
roots: &[ModuleSpecifier], roots: &[ModuleSpecifier],
options: GraphValidOptions, options: GraphValidOptions,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
if options.exit_lockfile_errors {
graph_exit_lock_errors(graph);
}
let mut errors = graph let mut errors = graph
.walk( .walk(
roots, roots,
@ -95,8 +105,10 @@ pub fn graph_valid(
enhanced_resolution_error_message(resolution_error) enhanced_resolution_error_message(resolution_error)
) )
} }
ModuleGraphError::ModuleError(e) => { ModuleGraphError::ModuleError(error) => {
enhanced_module_error_message(fs.clone(), e) enhanced_lockfile_error_message(error)
.or_else(|| enhanced_sloppy_imports_error_message(fs, error))
.unwrap_or_else(|| format!("{}", error))
} }
}; };
@ -152,40 +164,16 @@ pub fn graph_valid(
} }
} }
/// Checks the lockfile against the graph and exits on errors. pub fn graph_exit_lock_errors(graph: &ModuleGraph) {
pub fn graph_lock_or_exit(graph: &ModuleGraph, lockfile: &mut Lockfile) { for error in graph.module_errors() {
for module in graph.modules() { exit_for_lockfile_error(error);
let source = match module { }
Module::Js(module) if module.media_type.is_declaration() => continue, // skip declaration files }
Module::Js(module) => &module.source,
Module::Json(module) => &module.source,
Module::Node(_) | Module::Npm(_) | Module::External(_) => continue,
};
// skip over any specifiers in JSR packages because those fn exit_for_lockfile_error(err: &ModuleError) {
// are enforced via the integrity if let Some(err_message) = enhanced_lockfile_error_message(err) {
if deno_graph::source::recommended_registry_package_url_to_nv( log::error!("{} {}", colors::red("error:"), err_message);
jsr_url(), std::process::exit(10);
module.specifier(),
)
.is_some()
{
continue;
}
if !lockfile.check_or_insert_remote(module.specifier().as_str(), source) {
let err = format!(
concat!(
"The source code is invalid, as it does not match the expected hash in the lock file.\n",
" Specifier: {}\n",
" Lock file: {}",
),
module.specifier(),
lockfile.filename.display(),
);
log::error!("{} {}", colors::red("error:"), err);
std::process::exit(10);
}
} }
} }
@ -201,7 +189,6 @@ pub struct ModuleGraphCreator {
options: Arc<CliOptions>, options: Arc<CliOptions>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: Arc<dyn CliNpmResolver>,
module_graph_builder: Arc<ModuleGraphBuilder>, module_graph_builder: Arc<ModuleGraphBuilder>,
lockfile: Option<Arc<Mutex<Lockfile>>>,
type_checker: Arc<TypeChecker>, type_checker: Arc<TypeChecker>,
} }
@ -210,13 +197,11 @@ impl ModuleGraphCreator {
options: Arc<CliOptions>, options: Arc<CliOptions>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: Arc<dyn CliNpmResolver>,
module_graph_builder: Arc<ModuleGraphBuilder>, module_graph_builder: Arc<ModuleGraphBuilder>,
lockfile: Option<Arc<Mutex<Lockfile>>>,
type_checker: Arc<TypeChecker>, type_checker: Arc<TypeChecker>,
) -> Self { ) -> Self {
Self { Self {
options, options,
npm_resolver, npm_resolver,
lockfile,
module_graph_builder, module_graph_builder,
type_checker, type_checker,
} }
@ -317,9 +302,6 @@ impl ModuleGraphCreator {
.await?; .await?;
self.graph_valid(&graph)?; self.graph_valid(&graph)?;
if let Some(lockfile) = &self.lockfile {
graph_lock_or_exit(&graph, &mut lockfile.lock());
}
if self.options.type_check_mode().is_true() { if self.options.type_check_mode().is_true() {
// provide the graph to the type checker, then get it back after it's done // provide the graph to the type checker, then get it back after it's done
@ -426,6 +408,67 @@ impl ModuleGraphBuilder {
} }
} }
struct LockfileLocker<'a>(&'a Mutex<Lockfile>);
impl<'a> deno_graph::source::Locker for LockfileLocker<'a> {
fn get_remote_checksum(
&self,
specifier: &deno_ast::ModuleSpecifier,
) -> Option<LoaderChecksum> {
self
.0
.lock()
.remote()
.get(specifier.as_str())
.map(|s| LoaderChecksum::new(s.clone()))
}
fn has_remote_checksum(
&self,
specifier: &deno_ast::ModuleSpecifier,
) -> bool {
self.0.lock().remote().contains_key(specifier.as_str())
}
fn set_remote_checksum(
&mut self,
specifier: &deno_ast::ModuleSpecifier,
checksum: LoaderChecksum,
) {
self
.0
.lock()
.insert_remote(specifier.to_string(), checksum.into_string())
}
fn get_pkg_manifest_checksum(
&self,
package_nv: &PackageNv,
) -> Option<LoaderChecksum> {
self
.0
.lock()
.content
.packages
.jsr
.get(&package_nv.to_string())
.map(|s| LoaderChecksum::new(s.integrity.clone()))
}
fn set_pkg_manifest_checksum(
&mut self,
package_nv: &PackageNv,
checksum: LoaderChecksum,
) {
// a value would only exist in here if two workers raced
// to insert the same package manifest checksum
self
.0
.lock()
.insert_package(package_nv.to_string(), checksum.into_string());
}
}
let maybe_imports = self.options.to_maybe_imports()?; let maybe_imports = self.options.to_maybe_imports()?;
let parser = self.parsed_source_cache.as_capturing_parser(); let parser = self.parsed_source_cache.as_capturing_parser();
let analyzer = self.module_info_cache.as_module_analyzer(&parser); let analyzer = self.module_info_cache.as_module_analyzer(&parser);
@ -442,6 +485,10 @@ impl ModuleGraphBuilder {
.map(|r| r.as_reporter()); .map(|r| r.as_reporter());
let workspace_members = let workspace_members =
self.options.resolve_deno_graph_workspace_members()?; self.options.resolve_deno_graph_workspace_members()?;
let mut locker = self
.lockfile
.as_ref()
.map(|lockfile| LockfileLocker(lockfile));
self self
.build_graph_with_npm_resolution_and_build_options( .build_graph_with_npm_resolution_and_build_options(
graph, graph,
@ -459,6 +506,7 @@ impl ModuleGraphBuilder {
module_analyzer: &analyzer, module_analyzer: &analyzer,
reporter: maybe_file_watcher_reporter, reporter: maybe_file_watcher_reporter,
resolver: Some(graph_resolver), resolver: Some(graph_resolver),
locker: locker.as_mut().map(|l| l as _),
}, },
) )
.await .await
@ -468,7 +516,7 @@ impl ModuleGraphBuilder {
&self, &self,
graph: &mut ModuleGraph, graph: &mut ModuleGraph,
roots: Vec<ModuleSpecifier>, roots: Vec<ModuleSpecifier>,
loader: &mut dyn deno_graph::source::Loader, loader: &'a mut dyn deno_graph::source::Loader,
options: deno_graph::BuildOptions<'a>, options: deno_graph::BuildOptions<'a>,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
// ensure an "npm install" is done if the user has explicitly // ensure an "npm install" is done if the user has explicitly
@ -479,8 +527,10 @@ impl ModuleGraphBuilder {
} }
} }
// add the lockfile redirects to the graph if it's the first time executing // fill the graph with the information from the lockfile
if graph.redirects.is_empty() { let is_first_execution = graph.roots.is_empty();
if is_first_execution {
// populate the information from the lockfile
if let Some(lockfile) = &self.lockfile { if let Some(lockfile) = &self.lockfile {
let lockfile = lockfile.lock(); let lockfile = lockfile.lock();
for (from, to) in &lockfile.content.redirects { for (from, to) in &lockfile.content.redirects {
@ -492,13 +542,6 @@ impl ModuleGraphBuilder {
} }
} }
} }
}
}
// add the jsr specifiers to the graph if it's the first time executing
if graph.packages.is_empty() {
if let Some(lockfile) = &self.lockfile {
let lockfile = lockfile.lock();
for (key, value) in &lockfile.content.packages.specifiers { for (key, value) in &lockfile.content.packages.specifiers {
if let Some(key) = key if let Some(key) = key
.strip_prefix("jsr:") .strip_prefix("jsr:")
@ -512,60 +555,16 @@ impl ModuleGraphBuilder {
} }
} }
} }
for (nv, value) in &lockfile.content.packages.jsr {
if let Ok(nv) = PackageNv::from_str(nv) {
graph
.packages
.add_manifest_checksum(nv, value.integrity.clone())
.map_err(|err| deno_lockfile::IntegrityCheckFailedError {
package_display_id: format!("jsr:{}", err.nv),
actual: err.actual,
expected: err.expected,
filename: lockfile.filename.display().to_string(),
})?;
}
}
} }
} }
let initial_redirects_len = graph.redirects.len();
let initial_package_deps_len = graph.packages.package_deps_sum();
let initial_package_mappings_len = graph.packages.mappings().len();
let initial_npm_packages = graph.npm_packages.len();
graph.build(roots, loader, options).await; graph.build(roots, loader, options).await;
// add the redirects in the graph to the lockfile
if !graph.redirects.is_empty() {
if let Some(lockfile) = &self.lockfile {
let graph_redirects = graph.redirects.iter().filter(|(from, _)| {
!matches!(from.scheme(), "npm" | "file" | "deno")
});
let mut lockfile = lockfile.lock();
for (from, to) in graph_redirects {
lockfile.insert_redirect(from.to_string(), to.to_string());
}
}
}
// add the jsr specifiers in the graph to the lockfile
if !graph.packages.is_empty() {
if let Some(lockfile) = &self.lockfile {
let mappings = graph.packages.mappings();
let mut lockfile = lockfile.lock();
for (from, to) in mappings {
lockfile.insert_package_specifier(
format!("jsr:{}", from),
format!("jsr:{}", to),
);
}
for (name, checksum, deps) in
graph.packages.packages_with_checksum_and_deps()
{
lockfile.insert_package(
name.to_string(),
checksum.clone(),
deps.map(|s| s.to_string()),
);
}
}
}
if let Some(npm_resolver) = self.npm_resolver.as_managed() { if let Some(npm_resolver) = self.npm_resolver.as_managed() {
// ensure that the top level package.json is installed if a // ensure that the top level package.json is installed if a
// specifier was matched in the package.json // specifier was matched in the package.json
@ -578,6 +577,53 @@ impl ModuleGraphBuilder {
npm_resolver.resolve_pending().await?; npm_resolver.resolve_pending().await?;
} }
let has_redirects_changed = graph.redirects.len() != initial_redirects_len;
let has_jsr_package_deps_changed =
graph.packages.package_deps_sum() != initial_package_deps_len;
let has_jsr_package_mappings_changed =
graph.packages.mappings().len() != initial_package_mappings_len;
let has_npm_packages_changed =
graph.npm_packages.len() != initial_npm_packages;
if has_redirects_changed
|| has_jsr_package_deps_changed
|| has_jsr_package_mappings_changed
|| has_npm_packages_changed
{
if let Some(lockfile) = &self.lockfile {
let mut lockfile = lockfile.lock();
// https redirects
if has_redirects_changed {
let graph_redirects = graph.redirects.iter().filter(|(from, _)| {
!matches!(from.scheme(), "npm" | "file" | "deno")
});
for (from, to) in graph_redirects {
lockfile.insert_redirect(from.to_string(), to.to_string());
}
}
// jsr package mappings
if has_jsr_package_mappings_changed {
for (from, to) in graph.packages.mappings() {
lockfile.insert_package_specifier(
format!("jsr:{}", from),
format!("jsr:{}", to),
);
}
}
// jsr packages
if has_jsr_package_deps_changed {
for (name, deps) in graph.packages.packages_with_deps() {
lockfile
.add_package_deps(&name.to_string(), deps.map(|s| s.to_string()));
}
}
// npm packages
if has_npm_packages_changed {
self.npm_resolver.as_managed().unwrap().lock(&mut lockfile);
}
}
}
Ok(()) Ok(())
} }
@ -658,12 +704,13 @@ impl ModuleGraphBuilder {
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
graph_valid( graph_valid(
graph, graph,
self.fs.clone(), &self.fs,
roots, roots,
GraphValidOptions { GraphValidOptions {
is_vendoring: false, is_vendoring: false,
follow_type_only: self.options.type_check_mode().is_true(), follow_type_only: self.options.type_check_mode().is_true(),
check_js: self.options.check_js(), check_js: self.options.check_js(),
exit_lockfile_errors: true,
}, },
) )
} }
@ -701,28 +748,99 @@ pub fn enhanced_resolution_error_message(error: &ResolutionError) -> String {
message message
} }
pub fn enhanced_module_error_message( fn enhanced_sloppy_imports_error_message(
fs: Arc<dyn FileSystem>, fs: &Arc<dyn FileSystem>,
error: &ModuleError, error: &ModuleError,
) -> String { ) -> Option<String> {
let additional_message = match error { match error {
ModuleError::LoadingErr(specifier, _, _) // ex. "Is a directory" error ModuleError::LoadingErr(specifier, _, ModuleLoadError::Loader(_)) // ex. "Is a directory" error
| ModuleError::Missing(specifier, _) => { | ModuleError::Missing(specifier, _) => {
SloppyImportsResolver::new(fs).resolve( let additional_message = SloppyImportsResolver::new(fs.clone())
specifier, .resolve(specifier, ResolutionMode::Execution)
ResolutionMode::Execution, .as_suggestion_message()?;
) Some(format!(
.as_suggestion_message() "{} {} or run with --unstable-sloppy-imports",
error,
additional_message,
))
}
_ => None,
}
}
fn enhanced_lockfile_error_message(err: &ModuleError) -> Option<String> {
match err {
ModuleError::LoadingErr(
specifier,
_,
ModuleLoadError::Jsr(JsrLoadError::ContentChecksumIntegrity(
checksum_err,
)),
) => {
Some(format!(
concat!(
"Integrity check failed in package. The package may have been tampered with.\n\n",
" Specifier: {}\n",
" Actual: {}\n",
" Expected: {}\n\n",
"If you modified your global cache, run again with the --reload flag to restore ",
"its state. If you want to modify dependencies locally run again with the ",
"--vendor flag or specify `\"vendor\": true` in a deno.json then modify the contents ",
"of the vendor/ folder."
),
specifier,
checksum_err.actual,
checksum_err.expected,
))
}
ModuleError::LoadingErr(
_specifier,
_,
ModuleLoadError::Jsr(
JsrLoadError::PackageVersionManifestChecksumIntegrity(
package_nv,
checksum_err,
),
),
) => {
Some(format!(
concat!(
"Integrity check failed for package. The source code is invalid, as it does not match the expected hash in the lock file.\n\n",
" Package: {}\n",
" Actual: {}\n",
" Expected: {}\n\n",
"This could be caused by:\n",
" * the lock file may be corrupt\n",
" * the source itself may be corrupt\n\n",
"Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server."
),
package_nv,
checksum_err.actual,
checksum_err.expected,
))
}
ModuleError::LoadingErr(
specifier,
_,
ModuleLoadError::HttpsChecksumIntegrity(checksum_err),
) => {
Some(format!(
concat!(
"Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.\n\n",
" Specifier: {}\n",
" Actual: {}\n",
" Expected: {}\n\n",
"This could be caused by:\n",
" * the lock file may be corrupt\n",
" * the source itself may be corrupt\n\n",
"Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server."
),
specifier,
checksum_err.actual,
checksum_err.expected,
))
} }
_ => None, _ => None,
};
if let Some(message) = additional_message {
format!(
"{} {} or run with --unstable-sloppy-imports",
error, message
)
} else {
format!("{}", error)
} }
} }

View file

@ -1,6 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use super::logging::lsp_log; use super::logging::lsp_log;
use crate::args::read_lockfile_at_path;
use crate::args::ConfigFile; use crate::args::ConfigFile;
use crate::args::FmtOptions; use crate::args::FmtOptions;
use crate::args::LintOptions; use crate::args::LintOptions;
@ -1685,7 +1686,7 @@ fn resolve_node_modules_dir(
} }
fn resolve_lockfile_from_path(lockfile_path: PathBuf) -> Option<Lockfile> { fn resolve_lockfile_from_path(lockfile_path: PathBuf) -> Option<Lockfile> {
match Lockfile::new(lockfile_path, false) { match read_lockfile_at_path(lockfile_path) {
Ok(value) => { Ok(value) => {
if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename) { if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename) {
lsp_log!(" Resolved lockfile: \"{}\"", specifier); lsp_log!(" Resolved lockfile: \"{}\"", specifier);

View file

@ -310,7 +310,7 @@ impl Document {
let (maybe_parsed_source, maybe_module) = let (maybe_parsed_source, maybe_module) =
if media_type_is_diagnosable(media_type) { if media_type_is_diagnosable(media_type) {
parse_and_analyze_module( parse_and_analyze_module(
&specifier, specifier.clone(),
text_info.clone(), text_info.clone(),
maybe_headers.as_ref(), maybe_headers.as_ref(),
media_type, media_type,
@ -370,10 +370,13 @@ impl Document {
let maybe_parsed_source; let maybe_parsed_source;
let maybe_test_module_fut; let maybe_test_module_fut;
if media_type != self.media_type { if media_type != self.media_type {
let parsed_source_result = let parsed_source_result = parse_source(
parse_source(&self.specifier, self.text_info.clone(), media_type); self.specifier.clone(),
self.text_info.clone(),
media_type,
);
let maybe_module = analyze_module( let maybe_module = analyze_module(
&self.specifier, self.specifier.clone(),
&parsed_source_result, &parsed_source_result,
self.maybe_headers.as_ref(), self.maybe_headers.as_ref(),
self.file_referrer.as_ref(), self.file_referrer.as_ref(),
@ -481,7 +484,7 @@ impl Document {
.unwrap_or(false) .unwrap_or(false)
{ {
parse_and_analyze_module( parse_and_analyze_module(
&self.specifier, self.specifier.clone(),
text_info.clone(), text_info.clone(),
self.maybe_headers.as_ref(), self.maybe_headers.as_ref(),
media_type, media_type,
@ -1455,14 +1458,15 @@ impl<'a> deno_graph::source::Loader for OpenDocumentsGraphLoader<'a> {
} }
fn parse_and_analyze_module( fn parse_and_analyze_module(
specifier: &ModuleSpecifier, specifier: ModuleSpecifier,
text_info: SourceTextInfo, text_info: SourceTextInfo,
maybe_headers: Option<&HashMap<String, String>>, maybe_headers: Option<&HashMap<String, String>>,
media_type: MediaType, media_type: MediaType,
file_referrer: Option<&ModuleSpecifier>, file_referrer: Option<&ModuleSpecifier>,
resolver: &LspResolver, resolver: &LspResolver,
) -> (Option<ParsedSourceResult>, Option<ModuleResult>) { ) -> (Option<ParsedSourceResult>, Option<ModuleResult>) {
let parsed_source_result = parse_source(specifier, text_info, media_type); let parsed_source_result =
parse_source(specifier.clone(), text_info, media_type);
let module_result = analyze_module( let module_result = analyze_module(
specifier, specifier,
&parsed_source_result, &parsed_source_result,
@ -1474,12 +1478,12 @@ fn parse_and_analyze_module(
} }
fn parse_source( fn parse_source(
specifier: &ModuleSpecifier, specifier: ModuleSpecifier,
text_info: SourceTextInfo, text_info: SourceTextInfo,
media_type: MediaType, media_type: MediaType,
) -> ParsedSourceResult { ) -> ParsedSourceResult {
deno_ast::parse_module(deno_ast::ParseParams { deno_ast::parse_module(deno_ast::ParseParams {
specifier: specifier.clone(), specifier,
text_info, text_info,
media_type, media_type,
capture_tokens: true, capture_tokens: true,
@ -1489,7 +1493,7 @@ fn parse_source(
} }
fn analyze_module( fn analyze_module(
specifier: &ModuleSpecifier, specifier: ModuleSpecifier,
parsed_source_result: &ParsedSourceResult, parsed_source_result: &ParsedSourceResult,
maybe_headers: Option<&HashMap<String, String>>, maybe_headers: Option<&HashMap<String, String>>,
file_referrer: Option<&ModuleSpecifier>, file_referrer: Option<&ModuleSpecifier>,
@ -1511,7 +1515,7 @@ fn analyze_module(
}, },
)), )),
Err(err) => Err(deno_graph::ModuleGraphError::ModuleError( Err(err) => Err(deno_graph::ModuleGraphError::ModuleError(
deno_graph::ModuleError::ParseErr(specifier.clone(), err.clone()), deno_graph::ModuleError::ParseErr(specifier, err.clone()),
)), )),
} }
} }

View file

@ -85,6 +85,7 @@ use super::tsc::TsServer;
use super::urls; use super::urls;
use crate::args::create_default_npmrc; use crate::args::create_default_npmrc;
use crate::args::get_root_cert_store; use crate::args::get_root_cert_store;
use crate::args::write_lockfile_if_has_changes;
use crate::args::CaData; use crate::args::CaData;
use crate::args::CacheSetting; use crate::args::CacheSetting;
use crate::args::CliOptions; use crate::args::CliOptions;
@ -247,12 +248,13 @@ impl LanguageServer {
.await?; .await?;
graph_util::graph_valid( graph_util::graph_valid(
&graph, &graph,
factory.fs().clone(), factory.fs(),
&roots, &roots,
graph_util::GraphValidOptions { graph_util::GraphValidOptions {
is_vendoring: false, is_vendoring: false,
follow_type_only: true, follow_type_only: true,
check_js: false, check_js: false,
exit_lockfile_errors: false,
}, },
)?; )?;
@ -260,8 +262,8 @@ impl LanguageServer {
// found after caching // found after caching
if let Some(lockfile) = cli_options.maybe_lockfile() { if let Some(lockfile) = cli_options.maybe_lockfile() {
let lockfile = lockfile.lock(); let lockfile = lockfile.lock();
if let Err(err) = lockfile.write() { if let Err(err) = write_lockfile_if_has_changes(&lockfile) {
lsp_warn!("Error writing lockfile: {:#}", err); lsp_warn!("{:#}", err);
} }
} }

View file

@ -280,11 +280,6 @@ fn exit_for_error(error: AnyError) -> ! {
if let Some(e) = error.downcast_ref::<JsError>() { if let Some(e) = error.downcast_ref::<JsError>() {
error_string = format_js_error(e); error_string = format_js_error(e);
} else if let Some(args::LockfileError::IntegrityCheckFailed(e)) =
error.downcast_ref::<args::LockfileError>()
{
error_string = e.to_string();
error_code = 10;
} else if let Some(SnapshotFromLockfileError::IntegrityCheckFailed(e)) = } else if let Some(SnapshotFromLockfileError::IntegrityCheckFailed(e)) =
error.downcast_ref::<SnapshotFromLockfileError>() error.downcast_ref::<SnapshotFromLockfileError>()
{ {

View file

@ -9,6 +9,7 @@ use std::str;
use std::sync::Arc; use std::sync::Arc;
use crate::args::jsr_url; use crate::args::jsr_url;
use crate::args::write_lockfile_if_has_changes;
use crate::args::CliOptions; use crate::args::CliOptions;
use crate::args::DenoSubcommand; use crate::args::DenoSubcommand;
use crate::args::TsTypeLib; use crate::args::TsTypeLib;
@ -20,7 +21,6 @@ use crate::factory::CliFactory;
use crate::graph_container::MainModuleGraphContainer; use crate::graph_container::MainModuleGraphContainer;
use crate::graph_container::ModuleGraphContainer; use crate::graph_container::ModuleGraphContainer;
use crate::graph_container::ModuleGraphUpdatePermit; use crate::graph_container::ModuleGraphUpdatePermit;
use crate::graph_util::graph_lock_or_exit;
use crate::graph_util::CreateGraphOptions; use crate::graph_util::CreateGraphOptions;
use crate::graph_util::ModuleGraphBuilder; use crate::graph_util::ModuleGraphBuilder;
use crate::node; use crate::node;
@ -173,13 +173,9 @@ impl ModuleLoadPreparer {
self.module_graph_builder.graph_roots_valid(graph, roots)?; self.module_graph_builder.graph_roots_valid(graph, roots)?;
// If there is a lockfile... // write the lockfile if there is one
if let Some(lockfile) = &self.lockfile { if let Some(lockfile) = &self.lockfile {
let mut lockfile = lockfile.lock(); write_lockfile_if_has_changes(&lockfile.lock())?;
// validate the integrity of all the modules
graph_lock_or_exit(graph, &mut lockfile);
// update it with anything new
lockfile.write().context("Failed writing lockfile.")?;
} }
drop(_pb_clear_guard); drop(_pb_clear_guard);

View file

@ -370,9 +370,8 @@ impl ManagedCliNpmResolver {
self.fs_resolver.cache_packages().await?; self.fs_resolver.cache_packages().await?;
// If there's a lock file, update it with all discovered npm packages // If there's a lock file, update it with all discovered npm packages
if let Some(lockfile_mutex) = &self.maybe_lockfile { if let Some(lockfile) = &self.maybe_lockfile {
let mut lockfile = lockfile_mutex.lock(); self.lock(&mut lockfile.lock());
self.lock(&mut lockfile)?;
} }
Ok(()) Ok(())
@ -401,7 +400,7 @@ impl ManagedCliNpmResolver {
.serialized_valid_snapshot_for_system(system_info) .serialized_valid_snapshot_for_system(system_info)
} }
pub fn lock(&self, lockfile: &mut Lockfile) -> Result<(), AnyError> { pub fn lock(&self, lockfile: &mut Lockfile) {
self.resolution.lock(lockfile) self.resolution.lock(lockfile)
} }

View file

@ -292,7 +292,7 @@ impl NpmResolution {
.as_valid_serialized_for_system(system_info) .as_valid_serialized_for_system(system_info)
} }
pub fn lock(&self, lockfile: &mut Lockfile) -> Result<(), AnyError> { pub fn lock(&self, lockfile: &mut Lockfile) {
let snapshot = self.snapshot.read(); let snapshot = self.snapshot.read();
populate_lockfile_from_snapshot(lockfile, &snapshot) populate_lockfile_from_snapshot(lockfile, &snapshot)
} }
@ -345,7 +345,7 @@ async fn add_package_reqs_to_snapshot(
if let Some(lockfile_mutex) = maybe_lockfile { if let Some(lockfile_mutex) = maybe_lockfile {
let mut lockfile = lockfile_mutex.lock(); let mut lockfile = lockfile_mutex.lock();
populate_lockfile_from_snapshot(&mut lockfile, &snapshot)?; populate_lockfile_from_snapshot(&mut lockfile, &snapshot);
} }
Ok(snapshot) Ok(snapshot)
@ -369,7 +369,7 @@ fn get_npm_pending_resolver(
fn populate_lockfile_from_snapshot( fn populate_lockfile_from_snapshot(
lockfile: &mut Lockfile, lockfile: &mut Lockfile,
snapshot: &NpmResolutionSnapshot, snapshot: &NpmResolutionSnapshot,
) -> Result<(), AnyError> { ) {
for (package_req, nv) in snapshot.package_reqs() { for (package_req, nv) in snapshot.package_reqs() {
lockfile.insert_package_specifier( lockfile.insert_package_specifier(
format!("npm:{}", package_req), format!("npm:{}", package_req),
@ -384,10 +384,8 @@ fn populate_lockfile_from_snapshot(
); );
} }
for package in snapshot.all_packages_for_every_system() { for package in snapshot.all_packages_for_every_system() {
lockfile lockfile.insert_npm_package(npm_package_to_lockfile_info(package));
.check_or_insert_npm_package(npm_package_to_lockfile_info(package))?;
} }
Ok(())
} }
fn npm_package_to_lockfile_info( fn npm_package_to_lockfile_info(
@ -403,7 +401,6 @@ fn npm_package_to_lockfile_info(
.collect(); .collect();
NpmPackageLockfileInfo { NpmPackageLockfileInfo {
display_id: pkg.id.nv.to_string(),
serialized_id: pkg.id.as_serialized(), serialized_id: pkg.id.as_serialized(),
integrity: pkg.dist.integrity().for_lockfile(), integrity: pkg.dist.integrity().for_lockfile(),
dependencies, dependencies,

View file

@ -180,7 +180,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
if original_specifier.scheme() == "data" { if original_specifier.scheme() == "data" {
let data_url_text = let data_url_text =
match deno_graph::source::RawDataUrl::parse(original_specifier) match deno_graph::source::RawDataUrl::parse(original_specifier)
.and_then(|url| url.decode().map_err(|err| err.into())) .and_then(|url| url.decode())
{ {
Ok(response) => response, Ok(response) => response,
Err(err) => { Err(err) => {

View file

@ -8,7 +8,7 @@ use crate::colors;
use crate::display::write_json_to_stdout; use crate::display::write_json_to_stdout;
use crate::display::write_to_stdout_ignore_sigpipe; use crate::display::write_to_stdout_ignore_sigpipe;
use crate::factory::CliFactory; use crate::factory::CliFactory;
use crate::graph_util::graph_lock_or_exit; use crate::graph_util::graph_exit_lock_errors;
use crate::tsc::get_types_declaration_file_text; use crate::tsc::get_types_declaration_file_text;
use crate::util::fs::collect_specifiers; use crate::util::fs::collect_specifiers;
use deno_ast::diagnostics::Diagnostic; use deno_ast::diagnostics::Diagnostic;
@ -62,6 +62,7 @@ async fn generate_doc_nodes_for_builtin_types(
executor: Default::default(), executor: Default::default(),
file_system: &NullFileSystem, file_system: &NullFileSystem,
jsr_url_provider: Default::default(), jsr_url_provider: Default::default(),
locker: None,
module_analyzer: analyzer, module_analyzer: analyzer,
npm_resolver: None, npm_resolver: None,
reporter: None, reporter: None,
@ -121,8 +122,8 @@ pub async fn doc(flags: Flags, doc_flags: DocFlags) -> Result<(), AnyError> {
.create_graph(GraphKind::TypesOnly, module_specifiers.clone()) .create_graph(GraphKind::TypesOnly, module_specifiers.clone())
.await?; .await?;
if let Some(lockfile) = maybe_lockfile { if maybe_lockfile.is_some() {
graph_lock_or_exit(&graph, &mut lockfile.lock()); graph_exit_lock_errors(&graph);
} }
let doc_parser = doc::DocParser::new( let doc_parser = doc::DocParser::new(

View file

@ -7,7 +7,6 @@ use std::fmt::Write;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail; use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::resolve_url_or_path; use deno_core::resolve_url_or_path;
use deno_core::serde_json; use deno_core::serde_json;
@ -26,11 +25,12 @@ use deno_semver::npm::NpmPackageReqReference;
use deno_semver::package::PackageNv; use deno_semver::package::PackageNv;
use deno_terminal::colors; use deno_terminal::colors;
use crate::args::write_lockfile_if_has_changes;
use crate::args::Flags; use crate::args::Flags;
use crate::args::InfoFlags; use crate::args::InfoFlags;
use crate::display; use crate::display;
use crate::factory::CliFactory; use crate::factory::CliFactory;
use crate::graph_util::graph_lock_or_exit; use crate::graph_util::graph_exit_lock_errors;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::npm::ManagedCliNpmResolver; use crate::npm::ManagedCliNpmResolver;
use crate::util::checksum; use crate::util::checksum;
@ -68,13 +68,10 @@ pub async fn info(flags: Flags, info_flags: InfoFlags) -> Result<(), AnyError> {
.create_graph_with_loader(GraphKind::All, vec![specifier], &mut loader) .create_graph_with_loader(GraphKind::All, vec![specifier], &mut loader)
.await?; .await?;
// If there is a lockfile... // write out the lockfile if there is one
if let Some(lockfile) = &maybe_lockfile { if let Some(lockfile) = &maybe_lockfile {
let mut lockfile = lockfile.lock(); graph_exit_lock_errors(&graph);
// validate the integrity of all the modules write_lockfile_if_has_changes(&lockfile.lock())?;
graph_lock_or_exit(&graph, &mut lockfile);
// update it with anything new
lockfile.write().context("Failed writing lockfile.")?;
} }
if info_flags.json { if info_flags.json {
@ -669,18 +666,6 @@ impl<'a> GraphDisplayContext<'a> {
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => { ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
self.build_error_msg(specifier, "(missing)") self.build_error_msg(specifier, "(missing)")
} }
ModuleError::MissingWorkspaceMemberExports { .. } => {
self.build_error_msg(specifier, "(missing exports)")
}
ModuleError::UnknownExport { .. } => {
self.build_error_msg(specifier, "(unknown export)")
}
ModuleError::UnknownPackage { .. } => {
self.build_error_msg(specifier, "(unknown package)")
}
ModuleError::UnknownPackageReq { .. } => {
self.build_error_msg(specifier, "(unknown package constraint)")
}
} }
} }

View file

@ -1,6 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use crate::args::resolve_no_prompt; use crate::args::resolve_no_prompt;
use crate::args::write_lockfile_if_has_changes;
use crate::args::AddFlags; use crate::args::AddFlags;
use crate::args::CaData; use crate::args::CaData;
use crate::args::Flags; use crate::args::Flags;
@ -266,7 +267,7 @@ async fn install_local(
crate::module_loader::load_top_level_deps(&factory).await?; crate::module_loader::load_top_level_deps(&factory).await?;
if let Some(lockfile) = factory.cli_options().maybe_lockfile() { if let Some(lockfile) = factory.cli_options().maybe_lockfile() {
lockfile.lock().write()?; write_lockfile_if_has_changes(&lockfile.lock())?;
} }
Ok(()) Ok(())

View file

@ -59,8 +59,8 @@ impl GraphDiagnosticsCollector {
let maybe_version = graph let maybe_version = graph
.packages .packages
.mappings() .mappings()
.find(|(req, _)| *req == jsr_req_ref.req()) .get(jsr_req_ref.req())
.map(|(_, nv)| nv.version.clone()); .map(|nv| nv.version.clone());
diagnostics_collector.push( diagnostics_collector.push(
PublishDiagnostic::MissingConstraint { PublishDiagnostic::MissingConstraint {
specifier: resolution.specifier.clone(), specifier: resolution.specifier.clone(),

View file

@ -9,7 +9,6 @@ use deno_core::anyhow::bail;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::future::LocalBoxFuture; use deno_core::futures::future::LocalBoxFuture;
use deno_core::parking_lot::Mutex;
use deno_graph::source::ResolutionMode; use deno_graph::source::ResolutionMode;
use deno_graph::JsModule; use deno_graph::JsModule;
use deno_graph::Module; use deno_graph::Module;
@ -19,10 +18,8 @@ use import_map::ImportMap;
use import_map::SpecifierMap; use import_map::SpecifierMap;
use crate::args::JsxImportSourceConfig; use crate::args::JsxImportSourceConfig;
use crate::args::Lockfile;
use crate::cache::ParsedSourceCache; use crate::cache::ParsedSourceCache;
use crate::graph_util; use crate::graph_util;
use crate::graph_util::graph_lock_or_exit;
use crate::tools::vendor::import_map::BuildImportMapInput; use crate::tools::vendor::import_map::BuildImportMapInput;
use super::analyze::has_default_export; use super::analyze::has_default_export;
@ -62,7 +59,6 @@ pub struct BuildInput<
pub parsed_source_cache: &'a ParsedSourceCache, pub parsed_source_cache: &'a ParsedSourceCache,
pub output_dir: &'a Path, pub output_dir: &'a Path,
pub maybe_original_import_map: Option<&'a ImportMap>, pub maybe_original_import_map: Option<&'a ImportMap>,
pub maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
pub maybe_jsx_import_source: Option<&'a JsxImportSourceConfig>, pub maybe_jsx_import_source: Option<&'a JsxImportSourceConfig>,
pub resolver: &'a dyn deno_graph::source::Resolver, pub resolver: &'a dyn deno_graph::source::Resolver,
pub environment: &'a TEnvironment, pub environment: &'a TEnvironment,
@ -86,7 +82,6 @@ pub async fn build<
parsed_source_cache, parsed_source_cache,
output_dir, output_dir,
maybe_original_import_map: original_import_map, maybe_original_import_map: original_import_map,
maybe_lockfile,
maybe_jsx_import_source: jsx_import_source, maybe_jsx_import_source: jsx_import_source,
resolver, resolver,
environment, environment,
@ -118,20 +113,17 @@ pub async fn build<
let graph = build_graph(entry_points).await?; let graph = build_graph(entry_points).await?;
// check the lockfile
if let Some(lockfile) = maybe_lockfile {
graph_lock_or_exit(&graph, &mut lockfile.lock());
}
// surface any errors // surface any errors
let real_fs = Arc::new(deno_fs::RealFs) as Arc<dyn deno_fs::FileSystem>;
graph_util::graph_valid( graph_util::graph_valid(
&graph, &graph,
Arc::new(deno_fs::RealFs), &real_fs,
&graph.roots, &graph.roots,
graph_util::GraphValidOptions { graph_util::GraphValidOptions {
is_vendoring: true, is_vendoring: true,
check_js: true, check_js: true,
follow_type_only: true, follow_type_only: true,
exit_lockfile_errors: true,
}, },
)?; )?;

View file

@ -65,7 +65,6 @@ pub async fn vendor(
parsed_source_cache: factory.parsed_source_cache(), parsed_source_cache: factory.parsed_source_cache(),
output_dir: &output_dir, output_dir: &output_dir,
maybe_original_import_map: factory.maybe_import_map().await?.as_deref(), maybe_original_import_map: factory.maybe_import_map().await?.as_deref(),
maybe_lockfile: factory.maybe_lockfile().clone(),
maybe_jsx_import_source: jsx_import_source.as_ref(), maybe_jsx_import_source: jsx_import_source.as_ref(),
resolver: factory.resolver().await?.as_graph_resolver(), resolver: factory.resolver().await?.as_graph_resolver(),
environment: &build::RealVendorEnvironment, environment: &build::RealVendorEnvironment,

View file

@ -258,7 +258,6 @@ impl VendorTestBuilder {
parsed_source_cache: &parsed_source_cache, parsed_source_cache: &parsed_source_cache,
output_dir: &output_dir, output_dir: &output_dir,
maybe_original_import_map: self.original_import_map.as_ref(), maybe_original_import_map: self.original_import_map.as_ref(),
maybe_lockfile: None,
maybe_jsx_import_source: self.jsx_import_source_config.as_ref(), maybe_jsx_import_source: self.jsx_import_source_config.as_ref(),
resolver: resolver.as_graph_resolver(), resolver: resolver.as_graph_resolver(),
environment: &self.environment, environment: &self.environment,

View file

@ -7,7 +7,6 @@ use std::sync::Arc;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail; use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::FutureExt; use deno_core::futures::FutureExt;
use deno_core::parking_lot::Mutex; use deno_core::parking_lot::Mutex;
@ -48,6 +47,7 @@ use deno_terminal::colors;
use tokio::select; use tokio::select;
use crate::args::package_json::PackageJsonDeps; use crate::args::package_json::PackageJsonDeps;
use crate::args::write_lockfile_if_has_changes;
use crate::args::DenoSubcommand; use crate::args::DenoSubcommand;
use crate::args::StorageKeyResolver; use crate::args::StorageKeyResolver;
use crate::errors; use crate::errors;
@ -533,10 +533,7 @@ impl CliMainWorkerFactory {
// For npm binary commands, ensure that the lockfile gets updated // For npm binary commands, ensure that the lockfile gets updated
// so that we can re-use the npm resolution the next time it runs // so that we can re-use the npm resolution the next time it runs
// for better performance // for better performance
lockfile write_lockfile_if_has_changes(&lockfile.lock())?;
.lock()
.write()
.context("Failed writing lockfile.")?;
} }
(node_resolution.into_url(), is_main_cjs) (node_resolution.into_url(), is_main_cjs)

View file

@ -416,13 +416,6 @@ fn bundle_json_module_escape_sub() {
); );
} }
itest!(lockfile_check_error {
args: "bundle --lock=bundle/lockfile/check_error.json http://127.0.0.1:4545/subdir/mod1.ts",
output: "bundle/lockfile/check_error.out",
exit_code: 10,
http_server: true,
});
itest!(bundle { itest!(bundle {
args: "bundle subdir/mod1.ts", args: "bundle subdir/mod1.ts",
output: "bundle/bundle.test.out", output: "bundle/bundle.test.out",

View file

@ -141,7 +141,12 @@ console.log(version);"#,
.assert_matches_text("0.1.1\n"); .assert_matches_text("0.1.1\n");
let lockfile_path = temp_dir.path().join("deno.lock"); let lockfile_path = temp_dir.path().join("deno.lock");
let mut lockfile = Lockfile::new(lockfile_path.to_path_buf(), false).unwrap(); let mut lockfile = Lockfile::with_lockfile_content(
lockfile_path.to_path_buf(),
&lockfile_path.read_to_string(),
false,
)
.unwrap();
*lockfile *lockfile
.content .content
.packages .packages
@ -214,7 +219,7 @@ fn reload_info_not_found_cache_but_exists_remote() {
.args("run --cached-only main.ts") .args("run --cached-only main.ts")
.run(); .run();
output.assert_exit_code(1); output.assert_exit_code(1);
output.assert_matches_text("error: Failed to resolve version constraint. Try running again without --cached-only output.assert_matches_text("error: JSR package manifest for '@denotest/add' failed to load. Could not resolve version constraint using only cached data. Try running again without --cached-only
at file:///[WILDCARD]main.ts:1:21 at file:///[WILDCARD]main.ts:1:21
"); ");
@ -251,7 +256,12 @@ console.log(version);"#,
.assert_matches_text("0.1.1\n"); .assert_matches_text("0.1.1\n");
let lockfile_path = temp_dir.path().join("deno.lock"); let lockfile_path = temp_dir.path().join("deno.lock");
let mut lockfile = Lockfile::new(lockfile_path.to_path_buf(), false).unwrap(); let mut lockfile = Lockfile::with_lockfile_content(
lockfile_path.to_path_buf(),
&lockfile_path.read_to_string(),
false,
)
.unwrap();
let pkg_name = "@denotest/no-module-graph@0.1.1"; let pkg_name = "@denotest/no-module-graph@0.1.1";
let original_integrity = get_lockfile_pkg_integrity(&lockfile, pkg_name); let original_integrity = get_lockfile_pkg_integrity(&lockfile, pkg_name);
set_lockfile_pkg_integrity(&mut lockfile, pkg_name, "bad_integrity"); set_lockfile_pkg_integrity(&mut lockfile, pkg_name, "bad_integrity");
@ -259,18 +269,24 @@ console.log(version);"#,
let actual_integrity = let actual_integrity =
test_context.get_jsr_package_integrity("@denotest/no-module-graph/0.1.1"); test_context.get_jsr_package_integrity("@denotest/no-module-graph/0.1.1");
let integrity_check_failed_msg = format!("error: Integrity check failed for http://127.0.0.1:4250/@denotest/no-module-graph/0.1.1_meta.json let integrity_check_failed_msg = format!("[WILDCARD]Integrity check failed for package. The source code is invalid, as it does not match the expected hash in the lock file.
Actual: {} Package: @denotest/no-module-graph@0.1.1
Expected: bad_integrity Actual: {}
at file:///[WILDCARD]/main.ts:1:21 Expected: bad_integrity
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.
", actual_integrity); ", actual_integrity);
test_context test_context
.new_command() .new_command()
.args("run --quiet main.ts") .args("run --quiet main.ts")
.run() .run()
.assert_matches_text(&integrity_check_failed_msg) .assert_matches_text(&integrity_check_failed_msg)
.assert_exit_code(1); .assert_exit_code(10);
// now try with a vendor folder // now try with a vendor folder
temp_dir temp_dir
@ -284,7 +300,7 @@ Expected: bad_integrity
.args("run --quiet main.ts") .args("run --quiet main.ts")
.run() .run()
.assert_matches_text(&integrity_check_failed_msg) .assert_matches_text(&integrity_check_failed_msg)
.assert_exit_code(1); .assert_exit_code(10);
// now update to the correct integrity // now update to the correct integrity
set_lockfile_pkg_integrity(&mut lockfile, pkg_name, &original_integrity); set_lockfile_pkg_integrity(&mut lockfile, pkg_name, &original_integrity);
@ -318,7 +334,7 @@ Expected: bad_integrity
.args("run --quiet main.ts") .args("run --quiet main.ts")
.run() .run()
.assert_matches_text(&integrity_check_failed_msg) .assert_matches_text(&integrity_check_failed_msg)
.assert_exit_code(1); .assert_exit_code(10);
} }
#[test] #[test]
@ -335,39 +351,39 @@ console.log(add);"#,
// test it properly checks the checksum on download // test it properly checks the checksum on download
test_context test_context
.new_command() .new_command()
.args("run main.ts") .args("run main.ts")
.run() .run()
.assert_matches_text( .assert_matches_text(
"Download http://127.0.0.1:4250/@denotest/bad-manifest-checksum/meta.json "Download http://127.0.0.1:4250/@denotest/bad-manifest-checksum/meta.json
Download http://127.0.0.1:4250/@denotest/bad-manifest-checksum/1.0.0_meta.json Download http://127.0.0.1:4250/@denotest/bad-manifest-checksum/1.0.0_meta.json
Download http://127.0.0.1:4250/@denotest/bad-manifest-checksum/1.0.0/mod.ts Download http://127.0.0.1:4250/@denotest/bad-manifest-checksum/1.0.0/mod.ts
error: Integrity check failed. error: Integrity check failed in package. The package may have been tampered with.
Actual: 9a30ac96b5d5c1b67eca69e1e2cf0798817d9578c8d7d904a81a67b983b35cba Specifier: http://127.0.0.1:4250/@denotest/bad-manifest-checksum/1.0.0/mod.ts
Expected: bad-checksum Actual: 9a30ac96b5d5c1b67eca69e1e2cf0798817d9578c8d7d904a81a67b983b35cba
at file:///[WILDCARD]main.ts:1:21 Expected: bad-checksum
If you modified your global cache, run again with the --reload flag to restore its state. If you want to modify dependencies locally run again with the --vendor flag or specify `\"vendor\": true` in a deno.json then modify the contents of the vendor/ folder.
", ",
) )
.assert_exit_code(1); .assert_exit_code(10);
// test it properly checks the checksum when loading from the cache // test it properly checks the checksum when loading from the cache
test_context test_context
.new_command() .new_command()
.args("run main.ts") .args("run main.ts")
.run() .run()
.assert_matches_text( .assert_matches_text(
// ideally the two error messages would be the same... this one comes from "error: Integrity check failed in package. The package may have been tampered with.
// deno_cache and the one above comes from deno_graph. The thing is, in deno_cache
// (source of this error) it makes sense to include the url in the error message
// because it's not always used in the context of deno_graph
"error: Integrity check failed for http://127.0.0.1:4250/@denotest/bad-manifest-checksum/1.0.0/mod.ts
Actual: 9a30ac96b5d5c1b67eca69e1e2cf0798817d9578c8d7d904a81a67b983b35cba Specifier: http://127.0.0.1:4250/@denotest/bad-manifest-checksum/1.0.0/mod.ts
Expected: bad-checksum Actual: 9a30ac96b5d5c1b67eca69e1e2cf0798817d9578c8d7d904a81a67b983b35cba
at file:///[WILDCARD]main.ts:1:21 Expected: bad-checksum
If you modified your global cache, run again with the --reload flag to restore its state. If you want to modify dependencies locally run again with the --vendor flag or specify `\"vendor\": true` in a deno.json then modify the contents of the vendor/ folder.
", ",
) )
.assert_exit_code(1); .assert_exit_code(10);
} }
fn get_lockfile_pkg_integrity(lockfile: &Lockfile, pkg_name: &str) -> String { fn get_lockfile_pkg_integrity(lockfile: &Lockfile, pkg_name: &str) -> String {

View file

@ -214,19 +214,11 @@ itest!(cached_only {
}); });
itest!(import_map { itest!(import_map {
args: "run --allow-read --allow-env --import-map npm/import_map/import_map.json npm/import_map/main.js", args: "run --allow-read --allow-env --import-map npm/import_map/import_map.json npm/import_map/main.js",
output: "npm/import_map/main.out", output: "npm/import_map/main.out",
envs: env_vars_for_npm_tests(), envs: env_vars_for_npm_tests(),
http_server: true, http_server: true,
}); });
itest!(lock_file_integrity_failure {
args: "run --allow-read --allow-env --lock npm/lock_file/lock.json npm/lock_file/main.js",
output: "npm/lock_file/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 10,
});
itest!(sub_paths { itest!(sub_paths {
args: "run -A --quiet npm/sub_paths/main.jsx", args: "run -A --quiet npm/sub_paths/main.jsx",
@ -1518,7 +1510,7 @@ This could be caused by:
* the lock file may be corrupt * the lock file may be corrupt
* the source itself may be corrupt * the source itself may be corrupt
Use "--lock-write" flag to regenerate the lockfile at "[WILDCARD]deno.lock". Use the --lock-write flag to regenerate the lockfile at "[WILDCARD]deno.lock".
"#) "#)
.assert_exit_code(10); .assert_exit_code(10);
} }

View file

@ -821,40 +821,6 @@ itest!(lock_check_ok2 {
http_server: true, http_server: true,
}); });
itest!(lock_dynamic_imports {
args: "run --lock=run/lock_dynamic_imports.json --allow-read --allow-net http://127.0.0.1:4545/run/013_dynamic_import.ts",
output: "run/lock_dynamic_imports.out",
exit_code: 10,
http_server: true,
});
itest!(lock_check_err {
args: "run --lock=run/lock_check_err.json http://127.0.0.1:4545/run/003_relative_import.ts",
output: "run/lock_check_err.out",
exit_code: 10,
http_server: true,
});
itest!(lock_check_err2 {
args: "run --lock=run/lock_check_err2.json run/019_media_types.ts",
output: "run/lock_check_err2.out",
exit_code: 10,
http_server: true,
});
itest!(config_file_lock_path {
args: "run --config=run/config_file_lock_path.json run/019_media_types.ts",
output: "run/config_file_lock_path.out",
exit_code: 10,
http_server: true,
});
itest!(lock_flag_overrides_config_file_lock_path {
args: "run --lock=run/lock_check_ok2.json --config=run/config_file_lock_path.json run/019_media_types.ts",
output: "run/019_media_types.ts.out",
http_server: true,
});
itest!(lock_v2_check_ok { itest!(lock_v2_check_ok {
args: args:
"run --quiet --lock=run/lock_v2_check_ok.json http://127.0.0.1:4545/run/003_relative_import.ts", "run --quiet --lock=run/lock_v2_check_ok.json http://127.0.0.1:4545/run/003_relative_import.ts",
@ -868,33 +834,6 @@ itest!(lock_v2_check_ok2 {
http_server: true, http_server: true,
}); });
itest!(lock_v2_dynamic_imports {
args: "run --lock=run/lock_v2_dynamic_imports.json --allow-read --allow-net http://127.0.0.1:4545/run/013_dynamic_import.ts",
output: "run/lock_v2_dynamic_imports.out",
exit_code: 10,
http_server: true,
});
itest!(lock_v2_check_err {
args: "run --lock=run/lock_v2_check_err.json http://127.0.0.1:4545/run/003_relative_import.ts",
output: "run/lock_v2_check_err.out",
exit_code: 10,
http_server: true,
});
itest!(lock_v2_check_err2 {
args: "run --lock=run/lock_v2_check_err2.json run/019_media_types.ts",
output: "run/lock_v2_check_err2.out",
exit_code: 10,
http_server: true,
});
itest!(lock_only_http_and_https {
args: "run --lock=run/lock_only_http_and_https/deno.lock run/lock_only_http_and_https/main.ts",
output: "run/lock_only_http_and_https/main.out",
http_server: true,
});
#[test] #[test]
fn lock_no_declaration_files() { fn lock_no_declaration_files() {
let context = TestContextBuilder::new() let context = TestContextBuilder::new()
@ -4562,13 +4501,6 @@ async fn websocket_server_idletimeout() {
assert_eq!(child.wait().unwrap().code(), Some(123)); assert_eq!(child.wait().unwrap().code(), Some(123));
} }
itest!(auto_discover_lockfile {
args: "run run/auto_discover_lockfile/main.ts",
output: "run/auto_discover_lockfile/main.out",
http_server: true,
exit_code: 10,
});
itest!(no_lock_flag { itest!(no_lock_flag {
args: "run --no-lock run/no_lock_flag/main.ts", args: "run --no-lock run/no_lock_flag/main.ts",
output: "run/no_lock_flag/main.out", output: "run/no_lock_flag/main.out",
@ -4576,20 +4508,6 @@ itest!(no_lock_flag {
exit_code: 0, exit_code: 0,
}); });
itest!(config_file_lock_false {
args: "run --config=run/config_file_lock_boolean/false.json run/config_file_lock_boolean/main.ts",
output: "run/config_file_lock_boolean/false.main.out",
http_server: true,
exit_code: 0,
});
itest!(config_file_lock_true {
args: "run --config=run/config_file_lock_boolean/true.json run/config_file_lock_boolean/main.ts",
output: "run/config_file_lock_boolean/true.main.out",
http_server: true,
exit_code: 10,
});
itest!(permission_args { itest!(permission_args {
args: "run run/001_hello.js --allow-net", args: "run run/001_hello.js --allow-net",
output: "run/permission_args.out", output: "run/permission_args.out",
@ -4812,21 +4730,17 @@ console.log(returnsHi());"#,
.join("mod1.ts"); .join("mod1.ts");
mod1_file.write("export function returnsHi() { return 'bye bye bye'; }"); mod1_file.write("export function returnsHi() { return 'bye bye bye'; }");
// won't match the lockfile now // this is fine with a lockfile because users are supposed to be able
deno_run_cmd // to modify the vendor folder
.run() deno_run_cmd.run().assert_matches_text("bye bye bye\n");
.assert_matches_text(r#"error: The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://localhost:4545/subdir/mod1.ts
Lock file: [WILDCARD]deno.lock
"#)
.assert_exit_code(10);
// try updating by deleting the lockfile // try updating by deleting the lockfile
let lockfile = temp_dir.path().join("deno.lock"); let lockfile = temp_dir.path().join("deno.lock");
lockfile.remove_file(); lockfile.remove_file();
cache_command.run(); cache_command.run();
// now it should run // should still run and the lockfile should be recreated
// (though with the checksum from the vendor folder)
deno_run_cmd.run().assert_matches_text("bye bye bye\n"); deno_run_cmd.run().assert_matches_text("bye bye bye\n");
assert!(lockfile.exists()); assert!(lockfile.exists());

View file

@ -0,0 +1 @@
export * from "jsr:@denotest/add@1";

View file

@ -0,0 +1 @@
export * from "jsr:@denotest/subtract@1";

View file

@ -0,0 +1,6 @@
{
"exports": {
"./add": "./add.ts",
"./subtract": "./subtract.ts"
}
}

View file

@ -0,0 +1,5 @@
{
"versions": {
"1.0.0": {}
}
}

View file

@ -0,0 +1,3 @@
export function subtract(a: number, b: number): number {
return a - b;
}

View file

@ -0,0 +1,8 @@
{
"exports": {
".": "./mod.ts"
},
"moduleGraph1": {
"/mod.ts": {}
}
}

View file

@ -0,0 +1,5 @@
{
"versions": {
"1.0.0": {}
}
}

View file

@ -0,0 +1 @@
export function add(a: number, b: number): number;

View file

@ -0,0 +1 @@
module.exports.add = (a, b) => a + b;

View file

@ -0,0 +1,4 @@
{
"name": "@denotest/add",
"version": "1.0.0"
}

View file

@ -0,0 +1 @@
export function subtract(a: number, b: number): number;

View file

@ -0,0 +1 @@
module.exports.subtract = (a, b) => a - b;

View file

@ -0,0 +1,4 @@
{
"name": "@denotest/subtract",
"version": "1.0.0"
}

View file

@ -0,0 +1,5 @@
{
"args": "bundle --lock=check_error.json http://127.0.0.1:4545/subdir/mod1.ts",
"output": "check_error.out",
"exitCode": 10
}

View file

@ -0,0 +1,12 @@
[WILDCARD]
error: Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://127.0.0.1:4545/subdir/subdir2/mod2.ts
Actual: 8b3b670d25d238dfa72df119140406b96766a00fee635f3606429fe065b18fd1
Expected: bad
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.

View file

@ -1,3 +1,3 @@
[WILDCARD] [WILDCARD]
error: Integrity check failed for package: "npm:@denotest/esm-basic@1.0.0".[WILDCARD] error: Integrity check failed for package: "npm:@denotest/esm-basic@1.0.0".[WILDCARD]
Use "--lock-write" flag to regenerate the lockfile at [WILDCARD] Use the --lock-write flag to regenerate the lockfile at [WILDCARD]

View file

@ -1,5 +1,4 @@
Download http://127.0.0.1:4250/@denotest/deps/meta.json Download http://127.0.0.1:4250/@denotest/deps/meta.json
Download http://127.0.0.1:4250/@denotest/deps/meta.json Download http://127.0.0.1:4250/@denotest/deps/meta.json
error: Could not find constraint in the list of versions: @denotest/deps@0.1.4 error: Could not find version of '@denotest/deps' that matches specified version constraint '0.1.4'
Specifier: jsr:@denotest/deps@0.1.4/mod.ts
at file:///[WILDCARD]/version_not_found/main.ts:1:19 at file:///[WILDCARD]/version_not_found/main.ts:1:19

View file

@ -0,0 +1,16 @@
{
"tempDir": true,
"steps": [{
"args": "run add.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock01.out"
}, {
"args": "run subtract.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock02.out"
}]
}

View file

@ -0,0 +1 @@
import "add";

View file

@ -0,0 +1,9 @@
{
"tasks": {
"cat": "cat"
},
"imports": {
"add": "jsr:@denotest/add@1",
"subtract": "jsr:@denotest/subtract@1"
}
}

View file

@ -0,0 +1,20 @@
{
"version": "3",
"packages": {
"specifiers": {
"jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0"
},
"jsr": {
"@denotest/add@1.0.0": {
"integrity": "[WILDLINE]"
}
}
},
"remote": {},
"workspace": {
"dependencies": [
"jsr:@denotest/add@1",
"jsr:@denotest/subtract@1"
]
}
}

View file

@ -0,0 +1,24 @@
{
"version": "3",
"packages": {
"specifiers": {
"jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0",
"jsr:@denotest/subtract@1": "jsr:@denotest/subtract@1.0.0"
},
"jsr": {
"@denotest/add@1.0.0": {
"integrity": "[WILDLINE]"
},
"@denotest/subtract@1.0.0": {
"integrity": "[WILDLINE]"
}
}
},
"remote": {},
"workspace": {
"dependencies": [
"jsr:@denotest/add@1",
"jsr:@denotest/subtract@1"
]
}
}

View file

@ -0,0 +1 @@
import "subtract";

View file

@ -0,0 +1,16 @@
{
"tempDir": true,
"steps": [{
"args": "run add.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock01.out"
}, {
"args": "run subtract.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock02.out"
}]
}

View file

@ -0,0 +1 @@
import "different-deps-per-export/add";

View file

@ -0,0 +1,8 @@
{
"tasks": {
"cat": "cat"
},
"imports": {
"different-deps-per-export": "jsr:@denotest/different-deps-per-export@1"
}
}

View file

@ -0,0 +1,26 @@
{
"version": "3",
"packages": {
"specifiers": {
"jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0",
"jsr:@denotest/different-deps-per-export@1": "jsr:@denotest/different-deps-per-export@1.0.0"
},
"jsr": {
"@denotest/add@1.0.0": {
"integrity": "[WILDLINE]"
},
"@denotest/different-deps-per-export@1.0.0": {
"integrity": "[WILDLINE]",
"dependencies": [
"jsr:@denotest/add@1"
]
}
}
},
"remote": {},
"workspace": {
"dependencies": [
"jsr:@denotest/different-deps-per-export@1"
]
}
}

View file

@ -0,0 +1,31 @@
{
"version": "3",
"packages": {
"specifiers": {
"jsr:@denotest/add@1": "jsr:@denotest/add@1.0.0",
"jsr:@denotest/different-deps-per-export@1": "jsr:@denotest/different-deps-per-export@1.0.0",
"jsr:@denotest/subtract@1": "jsr:@denotest/subtract@1.0.0"
},
"jsr": {
"@denotest/add@1.0.0": {
"integrity": "[WILDLINE]"
},
"@denotest/different-deps-per-export@1.0.0": {
"integrity": "[WILDLINE]",
"dependencies": [
"jsr:@denotest/add@1",
"jsr:@denotest/subtract@1"
]
},
"@denotest/subtract@1.0.0": {
"integrity": "[WILDLINE]"
}
}
},
"remote": {},
"workspace": {
"dependencies": [
"jsr:@denotest/different-deps-per-export@1"
]
}
}

View file

@ -0,0 +1 @@
import "different-deps-per-export/subtract";

View file

@ -0,0 +1,16 @@
{
"tempDir": true,
"steps": [{
"args": "run add.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock01.out"
}, {
"args": "run subtract.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock02.out"
}]
}

View file

@ -0,0 +1 @@
import "add";

View file

@ -0,0 +1,9 @@
{
"tasks": {
"cat": "cat"
},
"imports": {
"add": "npm:@denotest/add@1",
"subtract": "npm:@denotest/subtract@1"
}
}

View file

@ -0,0 +1,21 @@
{
"version": "3",
"packages": {
"specifiers": {
"npm:@denotest/add@1": "npm:@denotest/add@1.0.0"
},
"npm": {
"@denotest/add@1.0.0": {
"integrity": "[WILDLINE]",
"dependencies": {}
}
}
},
"remote": {},
"workspace": {
"dependencies": [
"npm:@denotest/add@1",
"npm:@denotest/subtract@1"
]
}
}

View file

@ -0,0 +1,26 @@
{
"version": "3",
"packages": {
"specifiers": {
"npm:@denotest/add@1": "npm:@denotest/add@1.0.0",
"npm:@denotest/subtract@1": "npm:@denotest/subtract@1.0.0"
},
"npm": {
"@denotest/add@1.0.0": {
"integrity": "[WILDLINE]",
"dependencies": {}
},
"@denotest/subtract@1.0.0": {
"integrity": "[WILDLINE]",
"dependencies": {}
}
}
},
"remote": {},
"workspace": {
"dependencies": [
"npm:@denotest/add@1",
"npm:@denotest/subtract@1"
]
}
}

View file

@ -0,0 +1 @@
import "subtract";

View file

@ -0,0 +1 @@
import "http://localhost:4545/welcome.ts";

View file

@ -0,0 +1 @@
import "http://localhost:4546/welcome.ts";

View file

@ -0,0 +1,16 @@
{
"tempDir": true,
"steps": [{
"args": "run 1.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock01.out"
}, {
"args": "run 2.ts",
"output": "[WILDCARD]"
}, {
"args": "task --quiet cat deno.lock",
"output": "lock02.out"
}]
}

View file

@ -0,0 +1,5 @@
{
"tasks": {
"cat": "cat"
}
}

View file

@ -0,0 +1,6 @@
{
"version": "3",
"remote": {
"http://localhost:4545/welcome.ts": "7353d5fcbc36c45d26bcbca478cf973092523b07c45999f41319820092b4de31"
}
}

View file

@ -0,0 +1,9 @@
{
"version": "3",
"redirects": {
"http://localhost:4546/welcome.ts": "http://localhost:4545/welcome.ts"
},
"remote": {
"http://localhost:4545/welcome.ts": "7353d5fcbc36c45d26bcbca478cf973092523b07c45999f41319820092b4de31"
}
}

View file

@ -0,0 +1,5 @@
{
"args": "run main.ts",
"output": "main.out",
"exitCode": 10
}

View file

@ -0,0 +1,13 @@
Download http://localhost:4545/subdir/mod2.ts
Download http://localhost:4545/subdir/print_hello.ts
error: Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://localhost:4545/subdir/print_hello.ts
Actual: fa6692c8f9ff3fb107e773c3ece5274e9d08be282867a1e3ded1d9c00fcaa63c
Expected: foobar
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.

View file

@ -0,0 +1,5 @@
{
"args": "run --config=deno.json http://localhost:4546/run/001_hello.js",
"output": "run.out",
"exitCode": 10
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,6 @@
{
"version": "3",
"remote": {
"http://localhost:4546/run/001_hello.js": "c479db5ea26965387423ca438bb977d0b4788d5901efcef52f69871e4c1048c5"
}
}

View file

@ -0,0 +1,12 @@
Download http://localhost:4546/run/001_hello.js
error: Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://localhost:4546/run/001_hello.js
Actual: Redirect to http://localhost:4545/run/001_hello.js
Expected: c479db5ea26965387423ca438bb977d0b4788d5901efcef52f69871e4c1048c5
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.

View file

@ -0,0 +1,13 @@
{
"tests": {
"true": {
"args": "run --config=true.json main.ts",
"output": "true.main.out",
"exitCode": 10
},
"false": {
"args": "run --config=false.json main.ts",
"output": "false.main.out"
}
}
}

View file

@ -0,0 +1,11 @@
[WILDCARD]Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://localhost:4545/subdir/print_hello.ts
Actual: fa6692c8f9ff3fb107e773c3ece5274e9d08be282867a1e3ded1d9c00fcaa63c
Expected: foobar
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.

View file

@ -0,0 +1 @@
[WILDCARD]success true true true true true true true true

View file

@ -0,0 +1,13 @@
{
"tests": {
"error_bad_checksum": {
"args": "run --config=config_file_lock_path.json http://localhost:4545/run/019_media_types.ts",
"output": "config_file_lock_path.out",
"exitCode": 10
},
"lock_flag_override": {
"args": "run --lock=run/lock_check_ok2.json --config=config_file_lock_path.json http://localhost:4545/run/019_media_types.ts",
"output": "019_media_types.ts.out"
}
}
}

View file

@ -0,0 +1,11 @@
[WILDCARD]Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://localhost:4545/subdir/mt_text_ecmascript.j3.js
Actual: 3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18
Expected: bad
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.

View file

@ -0,0 +1,10 @@
{
"http://localhost:4545/subdir/mt_application_ecmascript.j2.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_application_x_javascript.j4.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_application_x_typescript.t4.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_ecmascript.j3.js": "bad",
"http://localhost:4545/subdir/mt_text_javascript.j1.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_typescript.t1.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_video_mp2t.t3.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_video_vdn.t2.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18"
}

View file

@ -0,0 +1,11 @@
[WILDCARD]Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://localhost:4545/subdir/mt_text_ecmascript.j3.js
Actual: 3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18
Expected: bad
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.

View file

@ -0,0 +1,13 @@
{
"version": "3",
"remote": {
"http://localhost:4545/subdir/mt_application_ecmascript.j2.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_application_x_javascript.j4.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_application_x_typescript.t4.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_ecmascript.j3.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_javascript.j1.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_typescript.t1.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_video_mp2t.t3.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_video_vdn.t2.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18"
}
}

View file

@ -0,0 +1,14 @@
{
"version": "3",
"remote": {
"http://localhost:4545/run/019_media_types.ts": "6b099d422b8a83e19d6672ad28c1c42dd3523eaadd8029f185bf4d10c1dc6e92",
"http://localhost:4545/subdir/mt_application_ecmascript.j2.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_application_x_javascript.j4.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_application_x_typescript.t4.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_ecmascript.j3.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_javascript.j1.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_text_typescript.t1.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_video_mp2t.t3.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
"http://localhost:4545/subdir/mt_video_vdn.t2.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18"
}
}

View file

@ -0,0 +1,5 @@
{
"args": "run --lock=lock_check_err.json http://127.0.0.1:4545/run/003_relative_import.ts",
"output": "lock_check_err.out",
"exitCode": 10
}

View file

@ -0,0 +1,11 @@
[WILDCARD]Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
Specifier: http://127.0.0.1:4545/run/003_relative_import.ts
Actual: a1572e8fd2c2712b33f04aed2561505b5feb2c8696f1f2cded3de7127931b97e
Expected: bad
This could be caused by:
* the lock file may be corrupt
* the source itself may be corrupt
Use the --lock-write flag to regenerate the lockfile or --reload to reload the source code from the server.

Some files were not shown because too many files have changed in this diff Show more