diff --git a/.changes/fix-nondeterministic-context-codegen.md b/.changes/fix-nondeterministic-context-codegen.md new file mode 100644 index 000000000000..5b4d8237a072 --- /dev/null +++ b/.changes/fix-nondeterministic-context-codegen.md @@ -0,0 +1,7 @@ +--- +'tauri-utils': 'patch:bug' +--- + +Sort csp/plugin/header configs when generating HashMap constructors so that `generate_context!` is deterministic. + +See: https://github.com/tauri-apps/tauri/issues/14978 for more information \ No newline at end of file diff --git a/crates/tauri-utils/src/config.rs b/crates/tauri-utils/src/config.rs index 8826e3f51b43..78f0ed3eceda 100644 --- a/crates/tauri-utils/src/config.rs +++ b/crates/tauri-utils/src/config.rs @@ -3842,9 +3842,14 @@ mod build { quote!(#prefix::Policy(#policy.into())) } Self::DirectiveMap(list) => { + // Pass a sorted vec so the HashMap constructor is deterministic + // see: https://github.com/tauri-apps/tauri/issues/14978 + // TODO: Remove this in v3, use a BTreeMap instead of a HashMap + let mut sorted: Vec<_> = list.iter().collect(); + sorted.sort_by_key(|(k, _)| *k); let map = map_lit( quote! { ::std::collections::HashMap }, - list, + sorted, str_lit, identity, ); @@ -3900,7 +3905,17 @@ mod build { quote!(#prefix::List(#list)) } Self::Map(m) => { - let map = map_lit(quote! { ::std::collections::HashMap }, m, str_lit, str_lit); + // Pass a sorted vec so the HashMap constructor is deterministic + // see: https://github.com/tauri-apps/tauri/issues/14978 + // TODO: Remove this in v3, use a BTreeMap instead of a HashMap + let mut sorted: Vec<_> = m.iter().collect(); + sorted.sort_by_key(|(k, _)| *k); + let map = map_lit( + quote! { ::std::collections::HashMap }, + sorted, + str_lit, + str_lit, + ); quote!(#prefix::Map(#map)) } }) @@ -4047,9 +4062,14 @@ mod build { impl ToTokens for PluginConfig { fn to_tokens(&self, tokens: &mut TokenStream) { + // Pass a sorted vec so the HashMap constructor is deterministic + // see: https://github.com/tauri-apps/tauri/issues/14978 + // TODO: Remove this in v3, use a BTreeMap instead of a HashMap + let mut sorted: Vec<_> = self.0.iter().collect(); + sorted.sort_by_key(|(k, _)| *k); let config = map_lit( quote! { ::std::collections::HashMap }, - &self.0, + sorted, str_lit, json_value_lit, );