Skip to content

Commit 6a527ef

Browse files
authored
fix: remove some potential panics and reduce error sizes (#160)
1 parent 432cae8 commit 6a527ef

File tree

3 files changed

+136
-95
lines changed

3 files changed

+136
-95
lines changed

src/deno_json/mod.rs

+36-21
Original file line numberDiff line numberDiff line change
@@ -551,8 +551,23 @@ impl TaskDefinition {
551551
}
552552
}
553553

554+
#[derive(Debug, JsError, Boxed)]
555+
pub struct ConfigFileReadError(pub Box<ConfigFileReadErrorKind>);
556+
557+
impl ConfigFileReadError {
558+
pub fn is_not_found(&self) -> bool {
559+
if let ConfigFileReadErrorKind::FailedReading { source: ioerr, .. } =
560+
self.as_kind()
561+
{
562+
matches!(ioerr.kind(), std::io::ErrorKind::NotFound)
563+
} else {
564+
false
565+
}
566+
}
567+
}
568+
554569
#[derive(Debug, Error, JsError)]
555-
pub enum ConfigFileReadError {
570+
pub enum ConfigFileReadErrorKind {
556571
#[class(type)]
557572
#[error("Could not convert config file path to specifier. Path: {0}")]
558573
PathToUrl(PathBuf),
@@ -587,16 +602,6 @@ pub enum ConfigFileReadError {
587602
NotObject { specifier: Url },
588603
}
589604

590-
impl ConfigFileReadError {
591-
pub fn is_not_found(&self) -> bool {
592-
if let ConfigFileReadError::FailedReading { source: ioerr, .. } = self {
593-
matches!(ioerr.kind(), std::io::ErrorKind::NotFound)
594-
} else {
595-
false
596-
}
597-
}
598-
}
599-
600605
#[derive(Debug, Error, JsError)]
601606
#[class(type)]
602607
#[error("Unsupported \"nodeModulesDir\" value.")]
@@ -914,7 +919,9 @@ impl ConfigFile {
914919
config_file_names: &[&str],
915920
) -> Result<Option<ConfigFileRc>, ConfigFileReadError> {
916921
fn is_skippable_err(e: &ConfigFileReadError) -> bool {
917-
if let ConfigFileReadError::FailedReading { source: ioerr, .. } = e {
922+
if let ConfigFileReadErrorKind::FailedReading { source: ioerr, .. } =
923+
e.as_kind()
924+
{
918925
is_skippable_io_error(ioerr)
919926
} else {
920927
false
@@ -951,8 +958,9 @@ impl ConfigFile {
951958
config_path: &Path,
952959
) -> Result<Self, ConfigFileReadError> {
953960
debug_assert!(config_path.is_absolute());
954-
let specifier = url_from_file_path(config_path)
955-
.map_err(|_| ConfigFileReadError::PathToUrl(config_path.to_path_buf()))?;
961+
let specifier = url_from_file_path(config_path).map_err(|_| {
962+
ConfigFileReadErrorKind::PathToUrl(config_path.to_path_buf()).into_box()
963+
})?;
956964
Self::from_specifier_and_path(sys, specifier, config_path)
957965
}
958966

@@ -970,10 +978,11 @@ impl ConfigFile {
970978
config_path: &Path,
971979
) -> Result<Self, ConfigFileReadError> {
972980
let text = sys.fs_read_to_string_lossy(config_path).map_err(|err| {
973-
ConfigFileReadError::FailedReading {
981+
ConfigFileReadErrorKind::FailedReading {
974982
specifier: specifier.clone(),
975983
source: err,
976984
}
985+
.into_box()
977986
})?;
978987
Self::new(&text, specifier)
979988
}
@@ -992,21 +1001,27 @@ impl ConfigFile {
9921001
json!({})
9931002
}
9941003
Err(e) => {
995-
return Err(ConfigFileReadError::Parse {
996-
specifier,
997-
source: Box::new(e),
998-
});
1004+
return Err(
1005+
ConfigFileReadErrorKind::Parse {
1006+
specifier,
1007+
source: Box::new(e),
1008+
}
1009+
.into_box(),
1010+
);
9991011
}
10001012
_ => {
1001-
return Err(ConfigFileReadError::NotObject { specifier });
1013+
return Err(
1014+
ConfigFileReadErrorKind::NotObject { specifier }.into_box(),
1015+
);
10021016
}
10031017
};
10041018
let json: ConfigFileJson =
10051019
serde_json::from_value(jsonc).map_err(|err| {
1006-
ConfigFileReadError::Deserialize {
1020+
ConfigFileReadErrorKind::Deserialize {
10071021
specifier: specifier.clone(),
10081022
source: err,
10091023
}
1024+
.into_box()
10101025
})?;
10111026

10121027
Ok(Self { specifier, json })

src/workspace/discovery.rs

+55-29
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ use crate::workspace::ConfigReadError;
3333
use crate::workspace::Workspace;
3434

3535
use super::ResolveWorkspaceMemberError;
36+
use super::ResolveWorkspaceMemberErrorKind;
3637
use super::ResolveWorkspacePatchError;
38+
use super::ResolveWorkspacePatchErrorKind;
3739
use super::UrlRc;
3840
use super::VendorEnablement;
3941
use super::WorkspaceDiscoverError;
@@ -308,7 +310,7 @@ fn discover_workspace_config_files_for_single_dir<
308310
start_dir = Some(dir);
309311
}
310312
DirOrConfigFile::ConfigFile(file) => {
311-
let specifier = url_from_file_path(file).unwrap();
313+
let specifier = url_from_file_path(file)?;
312314
let config_file = new_rc(
313315
ConfigFile::from_specifier(sys, specifier.clone())
314316
.map_err(ConfigReadError::DenoJsonRead)?,
@@ -637,11 +639,12 @@ fn handle_workspace_with_members<TSys: FsRead + FsMetadata + FsReadDir>(
637639
if let Some(name) = deno_json.json.name.as_deref() {
638640
if let Some(other_member_url) = seen_names.get(name) {
639641
return Err(
640-
ResolveWorkspaceMemberError::DuplicatePackageName {
642+
ResolveWorkspaceMemberErrorKind::DuplicatePackageName {
641643
name: name.to_string(),
642644
deno_json_url: deno_json.specifier.clone(),
643645
other_deno_json_url: (*other_member_url).clone(),
644646
}
647+
.into_box()
645648
.into(),
646649
);
647650
} else {
@@ -679,10 +682,13 @@ fn resolve_workspace_for_config_folder<
679682
let member = ensure_trailing_slash(raw_member);
680683
let member_dir_url = root_config_file_directory_url
681684
.join(&member)
682-
.map_err(|err| ResolveWorkspaceMemberError::InvalidMember {
683-
base: root_config_folder.folder_url(),
684-
member: raw_member.to_owned(),
685-
source: err,
685+
.map_err(|err| {
686+
ResolveWorkspaceMemberErrorKind::InvalidMember {
687+
base: root_config_folder.folder_url(),
688+
member: raw_member.to_owned(),
689+
source: err,
690+
}
691+
.into_box()
686692
})?;
687693
Ok(member_dir_url)
688694
};
@@ -692,10 +698,13 @@ fn resolve_workspace_for_config_folder<
692698
.as_str()
693699
.starts_with(root_config_file_directory_url.as_str())
694700
{
695-
return Err(ResolveWorkspaceMemberError::NonDescendant {
696-
workspace_url: root_config_file_directory_url.clone(),
697-
member_url: member_dir_url.clone(),
698-
});
701+
return Err(
702+
ResolveWorkspaceMemberErrorKind::NonDescendant {
703+
workspace_url: root_config_file_directory_url.clone(),
704+
member_url: member_dir_url.clone(),
705+
}
706+
.into_box(),
707+
);
699708
}
700709
Ok(())
701710
};
@@ -708,21 +717,23 @@ fn resolve_workspace_for_config_folder<
708717
}
709718

710719
let maybe_config_folder =
711-
load_config_folder(&url_to_file_path(member_dir_url).unwrap())?;
720+
load_config_folder(&url_to_file_path(member_dir_url)?)?;
712721
maybe_config_folder.ok_or_else(|| {
713722
// it's fine this doesn't use all the possible config file names
714723
// as this is only used to enhance the error message
715724
if member_dir_url.as_str().ends_with("/deno.json/")
716725
|| member_dir_url.as_str().ends_with("/deno.jsonc/")
717726
|| member_dir_url.as_str().ends_with("/package.json/")
718727
{
719-
ResolveWorkspaceMemberError::NotFoundMaybeSpecifiedFile {
728+
ResolveWorkspaceMemberErrorKind::NotFoundMaybeSpecifiedFile {
720729
dir_url: member_dir_url.clone(),
721730
}
731+
.into_box()
722732
} else {
723-
ResolveWorkspaceMemberError::NotFound {
733+
ResolveWorkspaceMemberErrorKind::NotFound {
724734
dir_url: member_dir_url.clone(),
725735
}
736+
.into_box()
726737
}
727738
})
728739
};
@@ -746,12 +757,13 @@ fn resolve_workspace_for_config_folder<
746757
),
747758
)
748759
.map_err(|err| {
749-
ResolveWorkspaceMemberError::MemberToPattern {
760+
ResolveWorkspaceMemberErrorKind::MemberToPattern {
750761
kind,
751762
base: root_config_file_directory_url.clone(),
752763
member: raw_member.to_string(),
753764
source: err,
754765
}
766+
.into_box()
755767
})
756768
})
757769
})
@@ -816,9 +828,10 @@ fn resolve_workspace_for_config_folder<
816828
for (raw_member, member_dir_url) in member_dir_urls {
817829
if member_dir_url == root_config_file_directory_url {
818830
return Err(
819-
ResolveWorkspaceMemberError::InvalidSelfReference {
831+
ResolveWorkspaceMemberErrorKind::InvalidSelfReference {
820832
member: raw_member.to_string(),
821833
}
834+
.into_box()
822835
.into(),
823836
);
824837
}
@@ -828,9 +841,10 @@ fn resolve_workspace_for_config_folder<
828841
.insert(new_rc(member_dir_url.clone()), member_config_folder);
829842
if previous_member.is_some() {
830843
return Err(
831-
ResolveWorkspaceMemberError::Duplicate {
844+
ResolveWorkspaceMemberErrorKind::Duplicate {
832845
member: raw_member.to_string(),
833846
}
847+
.into_box()
834848
.into(),
835849
);
836850
}
@@ -860,7 +874,7 @@ fn resolve_workspace_for_config_folder<
860874
}
861875
for pkg_json_path in pkg_json_paths {
862876
let member_dir_url =
863-
url_from_directory_path(pkg_json_path.parent().unwrap()).unwrap();
877+
url_from_directory_path(pkg_json_path.parent().unwrap())?;
864878
member_dir_urls.insert(member_dir_url);
865879
}
866880

@@ -872,20 +886,28 @@ fn resolve_workspace_for_config_folder<
872886
let member_config_folder =
873887
match find_member_config_folder(&member_dir_url) {
874888
Ok(config_folder) => config_folder,
875-
Err(ResolveWorkspaceMemberError::NotFound { dir_url }) => {
876-
// enhance the error to say we didn't find a package.json
889+
Err(err) => {
877890
return Err(
878-
ResolveWorkspaceMemberError::NotFoundPackageJson { dir_url }
879-
.into(),
891+
match err.into_kind() {
892+
ResolveWorkspaceMemberErrorKind::NotFound { dir_url } => {
893+
// enhance the error to say we didn't find a package.json
894+
ResolveWorkspaceMemberErrorKind::NotFoundPackageJson {
895+
dir_url,
896+
}
897+
.into_box()
898+
}
899+
err => err.into_box(),
900+
}
901+
.into(),
880902
);
881903
}
882-
Err(err) => return Err(err.into()),
883904
};
884905
if member_config_folder.pkg_json().is_none() {
885906
return Err(
886-
ResolveWorkspaceMemberError::NotFoundPackageJson {
907+
ResolveWorkspaceMemberErrorKind::NotFoundPackageJson {
887908
dir_url: member_dir_url,
888909
}
910+
.into_box()
889911
.into(),
890912
);
891913
}
@@ -950,7 +972,8 @@ fn resolve_patch_config_folders<TSys: FsRead + FsMetadata + FsReadDir>(
950972
WorkspaceDiscoverErrorKind::ResolvePatch {
951973
base: root_config_file_directory_url.clone(),
952974
patch: raw_member.to_string(),
953-
source: ResolveWorkspacePatchError::WorkspaceMemberNotAllowed,
975+
source: ResolveWorkspacePatchErrorKind::WorkspaceMemberNotAllowed
976+
.into_box(),
954977
}
955978
.into(),
956979
));
@@ -972,12 +995,15 @@ fn resolve_patch_member_config_folders<
972995
&Path,
973996
) -> Result<Option<ConfigFolder>, ConfigReadError>,
974997
) -> Result<BTreeMap<UrlRc, ConfigFolder>, ResolveWorkspacePatchError> {
975-
let patch_dir_path = url_to_file_path(patch_dir_url).unwrap();
998+
let patch_dir_path = url_to_file_path(patch_dir_url)?;
976999
let maybe_config_folder = load_config_folder(&patch_dir_path)?;
9771000
let Some(config_folder) = maybe_config_folder else {
978-
return Err(ResolveWorkspacePatchError::NotFound {
979-
dir_url: patch_dir_url.clone(),
980-
});
1001+
return Err(
1002+
ResolveWorkspacePatchErrorKind::NotFound {
1003+
dir_url: patch_dir_url.clone(),
1004+
}
1005+
.into_box(),
1006+
);
9811007
};
9821008
if config_folder.has_workspace_members() {
9831009
let maybe_vendor_dir =
@@ -989,7 +1015,7 @@ fn resolve_patch_member_config_folders<
9891015
&mut HashMap::new(),
9901016
&load_config_folder,
9911017
)
992-
.map_err(|err| ResolveWorkspacePatchError::Workspace(Box::new(err)))?;
1018+
.map_err(|err| ResolveWorkspacePatchErrorKind::Workspace(Box::new(err)))?;
9931019
raw_workspace
9941020
.members
9951021
.insert(new_rc(raw_workspace.root.folder_url()), raw_workspace.root);

0 commit comments

Comments
 (0)