Skip to content

Commit 928c831

Browse files
authored
Do not allow two different package specs with the same suffix (#8214)
1 parent 0c82d0a commit 928c831

2 files changed

Lines changed: 99 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
- Remove support for deprecated `bs-dependencies`, `bs-dev-dependencies`, and `bsc-flags` configuration options. Use `dependencies`, `dev-dependencies`, and `compiler-flags` instead. https://github.com/rescript-lang/rescript/pull/8196
2727
- `bsc`: remove legacy `-uncurried` flag. https://github.com/rescript-lang/rescript/pull/8201
2828
- Remove deprecated cli flags `--dev`, `--create-sourcedirs` and `build -w`. https://github.com/rescript-lang/rescript/pull/8202
29+
- Do not allow two different package specs with the same suffix to avoid conflicts. https://github.com/rescript-lang/rescript/pull/8214
2930

3031
#### :eyeglasses: Spec Compliance
3132

rewatch/src/config.rs

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,19 +745,65 @@ fn validate_package_specs_value(value: &serde_json::Value) -> Result<()> {
745745
None => return Ok(()),
746746
};
747747

748+
let top_level_suffix = value
749+
.get("suffix")
750+
.and_then(|suffix| suffix.as_str())
751+
.unwrap_or(".js")
752+
.to_string();
753+
let mut seen_suffixes = std::collections::HashSet::new();
754+
748755
match specs {
749756
serde_json::Value::Array(specs) => {
750757
for spec in specs {
751758
validate_package_spec_value(spec)?;
759+
if let Some(suffix) = resolve_spec_suffix(spec, &top_level_suffix) {
760+
let in_source = resolve_spec_in_source(spec);
761+
if !seen_suffixes.insert((suffix.clone(), in_source)) {
762+
return Err(anyhow!(
763+
"Duplicate package-spec suffix \"{suffix}\" is not allowed."
764+
));
765+
}
766+
}
767+
}
768+
}
769+
serde_json::Value::Object(_) => {
770+
validate_package_spec_value(specs)?;
771+
if let Some(suffix) = resolve_spec_suffix(specs, &top_level_suffix) {
772+
let in_source = resolve_spec_in_source(specs);
773+
if !seen_suffixes.insert((suffix.clone(), in_source)) {
774+
return Err(anyhow!(
775+
"Duplicate package-spec suffix \"{suffix}\" is not allowed."
776+
));
777+
}
752778
}
753779
}
754-
serde_json::Value::Object(_) => validate_package_spec_value(specs)?,
755780
_ => {}
756781
}
757782

758783
Ok(())
759784
}
760785

786+
fn resolve_spec_suffix(spec: &serde_json::Value, top_level_suffix: &str) -> Option<String> {
787+
if !spec.is_object() {
788+
return None;
789+
}
790+
791+
match spec.get("suffix").and_then(|suffix| suffix.as_str()) {
792+
Some(suffix) => Some(suffix.to_string()),
793+
None => Some(top_level_suffix.to_string()),
794+
}
795+
}
796+
797+
fn resolve_spec_in_source(spec: &serde_json::Value) -> bool {
798+
if !spec.is_object() {
799+
return true;
800+
}
801+
802+
spec.get("in-source")
803+
.and_then(|in_source| in_source.as_bool())
804+
.unwrap_or(true)
805+
}
806+
761807
fn validate_package_spec_value(value: &serde_json::Value) -> Result<()> {
762808
let module = match value.get("module") {
763809
Some(module) => module,
@@ -837,6 +883,57 @@ pub mod tests {
837883
assert_eq!(config.get_suffix(spec), ".mjs");
838884
}
839885

886+
#[test]
887+
fn test_package_specs_duplicate_suffix_default() {
888+
let json = r#"
889+
{
890+
"name": "dup-suffix-default",
891+
"sources": ".",
892+
"package-specs": [
893+
{ "module": "commonjs", "in-source": true },
894+
{ "module": "esmodule", "in-source": true }
895+
]
896+
}
897+
"#;
898+
899+
let error = Config::new_from_json_string(json).unwrap_err().to_string();
900+
assert!(error.contains("Duplicate package-spec suffix"));
901+
}
902+
903+
#[test]
904+
fn test_package_specs_duplicate_suffix_explicit() {
905+
let json = r#"
906+
{
907+
"name": "dup-suffix-explicit",
908+
"sources": ".",
909+
"package-specs": [
910+
{ "module": "commonjs", "in-source": true, "suffix": ".mjs" },
911+
{ "module": "esmodule", "in-source": true, "suffix": ".mjs" }
912+
]
913+
}
914+
"#;
915+
916+
let error = Config::new_from_json_string(json).unwrap_err().to_string();
917+
assert!(error.contains("Duplicate package-spec suffix"));
918+
}
919+
920+
#[test]
921+
fn test_package_specs_duplicate_suffix_different_in_source_ok() {
922+
let json = r#"
923+
{
924+
"name": "dup-suffix-different-in-source",
925+
"sources": ".",
926+
"package-specs": [
927+
{ "module": "esmodule", "in-source": true, "suffix": ".res.js" },
928+
{ "module": "esmodule", "in-source": false, "suffix": ".res.js" }
929+
]
930+
}
931+
"#;
932+
933+
let config = Config::new_from_json_string(json).unwrap();
934+
assert_eq!(config.get_package_specs().len(), 2);
935+
}
936+
840937
#[test]
841938
fn test_sources() {
842939
let json = r#"

0 commit comments

Comments
 (0)