From 6ccd62355eb73e381388cc92140ee03c557736a6 Mon Sep 17 00:00:00 2001 From: Erwan Leboucher Date: Wed, 30 Sep 2026 11:21:52 +0200 Subject: [PATCH] fix(android): stabilize embedded asset ordering Signed-off-by: Erwan Leboucher --- .changeset/fix-android-asset-ordering.md | 5 + src-tauri/Cargo.lock | 215 ++++++++++++++++------- src-tauri/Cargo.toml | 7 + src-tauri/tests/asset_reproducibility.rs | 47 +++++ 4 files changed, 208 insertions(+), 66 deletions(-) create mode 100644 .changeset/fix-android-asset-ordering.md create mode 100644 src-tauri/tests/asset_reproducibility.rs diff --git a/.changeset/fix-android-asset-ordering.md b/.changeset/fix-android-asset-ordering.md new file mode 100644 index 0000000000..e00d23843e --- /dev/null +++ b/.changeset/fix-android-asset-ordering.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +Fix nondeterministic ordering of embedded assets and CSP hashes in Android builds. diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4dc1014a2d..c43152a37e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -101,15 +101,15 @@ dependencies = [ [[package]] name = "alloc-no-stdlib" -version = "2.0.4" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" +checksum = "c2fb6cfd47bf496ff64095c20eaba0c201404ee38714d4142fcfa1dc334fcc7a" [[package]] name = "alloc-stdlib" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" +checksum = "0b5c1865780388bfa186411ab5f247819487fc4864c6e9c3106611fa347586e1" dependencies = [ "alloc-no-stdlib", ] @@ -201,7 +201,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -212,7 +212,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -751,9 +751,9 @@ dependencies = [ [[package]] name = "brotli" -version = "8.0.4" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" +checksum = "f8b851b75c23ca7873623d612fe49bd1989aeb03d08fb9432187eb253d3d4c6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -762,9 +762,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.3" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" +checksum = "941cd9bd4ddab83cb46fa5a2d428f1c857b24ac78cb876cf7beb710840934bd7" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1023,6 +1023,17 @@ dependencies = [ "uuid", ] +[[package]] +name = "cfb" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a347dcabdae9c31b0825fd6a8bed285ec9c2acb89c47827126d52fa4f59cece3" +dependencies = [ + "fnv", + "uuid", + "web-time", +] + [[package]] name = "cfg-expr" version = "0.15.8" @@ -1547,7 +1558,7 @@ version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" dependencies = [ - "cssparser-macros", + "cssparser-macros 0.6.1", "dtoa-short", "itoa", "matches", @@ -1564,7 +1575,20 @@ version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" dependencies = [ - "cssparser-macros", + "cssparser-macros 0.6.1", + "dtoa-short", + "itoa", + "phf 0.13.1", + "smallvec", +] + +[[package]] +name = "cssparser" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9cdaae01d5ed7882b04d795e7f752f46ff52d2fa3b50a20d28c464510bba98" +dependencies = [ + "cssparser-macros 0.7.1", "dtoa-short", "itoa", "phf 0.13.1", @@ -1582,20 +1606,20 @@ dependencies = [ ] [[package]] -name = "ctor" -version = "0.8.0" +name = "cssparser-macros" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" +checksum = "d045de693cb712d0b22c6a64be5b953f67b3ce00ab5ad3dd5d8b441886ab8e1a" dependencies = [ - "ctor-proc-macro", - "dtor", + "quote", + "syn 3.0.3", ] [[package]] -name = "ctor-proc-macro" -version = "0.0.7" +name = "ctor" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" +checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d" [[package]] name = "ctr" @@ -1986,7 +2010,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -2077,6 +2101,21 @@ dependencies = [ "tendril 0.5.1", ] +[[package]] +name = "dom_query" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fac5fca71e65e94cc718a6e2af65d6e0f9c6027751c2aa562fbb5087fda639bc" +dependencies = [ + "bit-set", + "cssparser 0.37.0", + "foldhash 0.2.0", + "html5ever 0.39.0", + "precomputed-hash", + "selectors 0.38.0", + "tendril 0.5.1", +] + [[package]] name = "dos-date-time" version = "0.3.0" @@ -2138,21 +2177,6 @@ dependencies = [ "dtoa", ] -[[package]] -name = "dtor" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" -dependencies = [ - "dtor-proc-macro", -] - -[[package]] -name = "dtor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" - [[package]] name = "dunce" version = "1.0.5" @@ -2314,7 +2338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3716,7 +3740,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" dependencies = [ - "cfb", + "cfb 0.7.3", ] [[package]] @@ -3724,6 +3748,9 @@ name = "infer" version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4200d433cbd5178df7797c9c2e75b348b728e39631cf14520d1e2fc424201f4" +dependencies = [ + "cfb 0.14.0", +] [[package]] name = "inout" @@ -4003,12 +4030,24 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" dependencies = [ - "jsonptr", + "jsonptr 0.6.3", "serde", "serde_json", "thiserror 1.0.69", ] +[[package]] +name = "json-patch" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7421438de105a0827e44fadd05377727847d717c80ce29a229f85fd04c427b72" +dependencies = [ + "jsonptr 0.7.1", + "serde", + "serde_json", + "thiserror 2.0.20", +] + [[package]] name = "jsonptr" version = "0.6.3" @@ -4019,6 +4058,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "jsonptr" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5a3cc660ba5d72bce0b3bb295bf20847ccbb40fd423f3f05b61273672e561fe" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "keyboard-types" version = "0.7.0" @@ -4781,7 +4830,7 @@ dependencies = [ "png 0.18.1", "serde", "thiserror 2.0.20", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -4905,7 +4954,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5390,7 +5439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.45.0", ] [[package]] @@ -6129,7 +6178,7 @@ dependencies = [ "once_cell", "socket2 0.6.5", "tracing", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6740,7 +6789,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6799,7 +6848,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6859,6 +6908,7 @@ dependencies = [ "objc2-foundation", "objc2-photos", "percent-encoding", + "quote", "regex", "reqwest 0.12.28", "sentry", @@ -6867,6 +6917,7 @@ dependencies = [ "sha2 0.11.0", "tauri", "tauri-build", + "tauri-codegen", "tauri-plugin-android-fs", "tauri-plugin-app-icon", "tauri-plugin-clipboard-manager", @@ -6891,6 +6942,7 @@ dependencies = [ "tauri-plugin-window-state", "tauri-runtime-cef", "tauri-typegen", + "tempfile", "tokio", "tokio-util", "ts-rs", @@ -7066,6 +7118,25 @@ dependencies = [ "smallvec", ] +[[package]] +name = "selectors" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adfa1c298912827b8a28b223b3b874357397ae706e6190acd9bf28cee99114d" +dependencies = [ + "bitflags 2.13.1", + "cssparser 0.37.0", + "derive_more 2.1.1", + "log", + "new_debug_unreachable", + "phf 0.13.1", + "phf_codegen 0.13.1", + "precomputed-hash", + "rustc-hash", + "servo_arc 0.4.3", + "smallvec", +] + [[package]] name = "semver" version = "1.0.28" @@ -7588,7 +7659,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -7782,9 +7853,9 @@ dependencies = [ [[package]] name = "swift-rs" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" +checksum = "e45c444e496845d3f2a351146bff59aae4975b2280238df1dfaa0c7d1846f38e" dependencies = [ "base64 0.21.7", "serde", @@ -8036,7 +8107,7 @@ dependencies = [ "dirs", "glob", "heck 0.5.0", - "json-patch", + "json-patch 3.0.1", "schemars 0.8.22", "semver", "serde", @@ -8048,16 +8119,16 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.6.3" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" +checksum = "3926b73ac01df7c14f19ff872cd56e67213a87acc0000ea37ddb300f3d11a3e3" dependencies = [ "base64 0.22.1", "brotli", "ico", - "json-patch", + "json-patch 4.2.0", "plist", - "png 0.17.16", + "png 0.18.1", "proc-macro2", "quote", "semver", @@ -8299,7 +8370,7 @@ dependencies = [ "thiserror 2.0.20", "tokio", "url", - "urlpattern", + "urlpattern 0.3.0", ] [[package]] @@ -8625,21 +8696,21 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.9.3" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" +checksum = "4dd257082deff79550de3409ed146104aeaf86fe38649615b04a304144939677" dependencies = [ "anyhow", "brotli", "cargo_metadata 0.19.2", "ctor", - "dom_query", + "dom_query 0.28.0", "dunce", "glob", "html5ever 0.29.1", "http 1.5.0", - "infer 0.19.0", - "json-patch", + "infer 0.22.0", + "json-patch 4.2.0", "kuchikiki", "log", "memchr", @@ -8658,7 +8729,7 @@ dependencies = [ "thiserror 2.0.20", "toml 1.1.4+spec-1.1.0", "url", - "urlpattern", + "urlpattern 0.6.0", "uuid", "walkdir", ] @@ -8692,10 +8763,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -9326,7 +9397,7 @@ dependencies = [ "png 0.18.1", "serde", "thiserror 2.0.20", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -9412,7 +9483,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset", "tempfile", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -9594,6 +9665,18 @@ dependencies = [ "url", ] +[[package]] +name = "urlpattern" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df16f50ef4cc145211879a3867ba757076b25dfee812040dcb0658bd9ae7904b" +dependencies = [ + "icu_properties", + "regex", + "serde", + "url", +] + [[package]] name = "utf-8" version = "0.7.6" @@ -10144,7 +10227,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -10984,7 +11067,7 @@ dependencies = [ "cookie", "crossbeam-channel", "dirs", - "dom_query", + "dom_query 0.27.0", "dpi", "dunce", "gdkx11", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 91c7c53b8c..307dd165b8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,8 +16,15 @@ crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] serde_json = "1.0" tauri-build = { version = "2.6.3", features = [] } +# 2.7 sorts embedded assets and CSP hashes for reproducible native libraries. +tauri-codegen = "2.7.0" tauri-typegen = "0.5" +[dev-dependencies] +quote = "1" +tauri-codegen = "2.7.0" +tempfile = "3" + [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } diff --git a/src-tauri/tests/asset_reproducibility.rs b/src-tauri/tests/asset_reproducibility.rs new file mode 100644 index 0000000000..f90fb04f56 --- /dev/null +++ b/src-tauri/tests/asset_reproducibility.rs @@ -0,0 +1,47 @@ +use quote::ToTokens; +use std::path::PathBuf; +use tauri_codegen::embedded_assets::{AssetOptions, EmbeddedAssets}; + +fn generate(paths: Vec) -> String { + let options = AssetOptions::new(Default::default()); + EmbeddedAssets::new(paths, &options, |_, _, _, _| Ok(())) + .unwrap() + .into_token_stream() + .to_string() +} + +#[test] +fn embedded_assets_do_not_depend_on_collection_order() { + let dir = tempfile::tempdir().unwrap(); + let assets_dir = dir.path().join("assets"); + let out_dir = dir.path().join("out"); + std::fs::create_dir(&assets_dir).unwrap(); + std::fs::create_dir(&out_dir).unwrap(); + std::env::set_var("OUT_DIR", &out_dir); + + let mut paths = Vec::new(); + for i in 0..16 { + let script = assets_dir.join(format!("chunk-{i}.js")); + std::fs::write(&script, format!("console.log({i});")).unwrap(); + paths.push(script); + + let locale = assets_dir.join(format!("locale-{i}.json")); + std::fs::write(&locale, format!(r#"{{"locale":{i}}}"#)).unwrap(); + paths.push(locale); + } + + let expected = generate(paths.clone()); + assert!(expected.contains("CspHash :: Script")); + assert!(expected.contains("locale-0.json")); + + for _ in 0..32 { + assert_eq!(generate(paths.clone()), expected); + } + + paths.reverse(); + assert_eq!(generate(paths.clone()), expected); + for _ in 0..paths.len() { + paths.rotate_left(1); + assert_eq!(generate(paths.clone()), expected); + } +}