@@ -188,7 +188,15 @@ impl PostRunFingerprint {
188188 }
189189
190190 for ( pattern, stored_matches) in & self . tracked_env_globs {
191- let current_matches = match_env_glob ( pattern. as_str ( ) , unfiltered_envs) ?;
191+ let current_matches = match match_env_glob ( pattern. as_str ( ) , unfiltered_envs) ? {
192+ EnvGlobValidation :: Matches ( matches) => matches,
193+ EnvGlobValidation :: NonUtf8Value ( mismatch) => {
194+ return Ok ( Some ( PostRunMismatch :: TrackedEnvGlob {
195+ pattern : pattern. clone ( ) ,
196+ mismatch,
197+ } ) ) ;
198+ }
199+ } ;
192200 if let Some ( mismatch) = first_env_glob_mismatch ( stored_matches, & current_matches) {
193201 return Ok ( Some ( PostRunMismatch :: TrackedEnvGlob {
194202 pattern : pattern. clone ( ) ,
@@ -202,24 +210,35 @@ impl PostRunFingerprint {
202210}
203211
204212/// Build the current match-set for `pattern` by enumerating the given env
205- /// snapshot and keeping UTF-8 names whose representation matches the glob.
213+ /// snapshot and keeping UTF-8 names whose representation matches the glob. If
214+ /// a matching env has a non-UTF-8 value, return a changed mismatch so the stale
215+ /// cache entry is not replayed.
206216fn match_env_glob (
207217 pattern : & str ,
208218 envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
209- ) -> anyhow:: Result < BTreeMap < Str , EnvValueHash > > {
219+ ) -> anyhow:: Result < EnvGlobValidation > {
210220 let glob = vite_glob:: env:: EnvGlob :: new ( pattern) ?;
211- Ok ( envs
212- . iter ( )
213- . filter_map ( |( name, value) | {
214- let name_str = name. to_str ( ) ?;
215- let value_str = value. to_str ( ) ?;
216- if glob. is_match ( name_str) {
217- Some ( ( Str :: from ( name_str) , EnvValueHash :: new ( value_str) ) )
218- } else {
219- None
220- }
221- } )
222- . collect ( ) )
221+ let mut matches = BTreeMap :: new ( ) ;
222+ for ( name, value) in envs {
223+ let Some ( name_str) = name. to_str ( ) else {
224+ continue ;
225+ } ;
226+ if !glob. is_match ( name_str) {
227+ continue ;
228+ }
229+ let Some ( value_str) = value. to_str ( ) else {
230+ return Ok ( EnvGlobValidation :: NonUtf8Value ( EnvMismatch :: Changed {
231+ name : Str :: from ( name_str) ,
232+ } ) ) ;
233+ } ;
234+ matches. insert ( Str :: from ( name_str) , EnvValueHash :: new ( value_str) ) ;
235+ }
236+ Ok ( EnvGlobValidation :: Matches ( matches) )
237+ }
238+
239+ enum EnvGlobValidation {
240+ Matches ( BTreeMap < Str , EnvValueHash > ) ,
241+ NonUtf8Value ( EnvMismatch ) ,
223242}
224243
225244/// Find the first deterministic difference between stored and current env
@@ -487,4 +506,32 @@ mod tests {
487506
488507 assert ! ( err. to_string( ) . contains( "tracked env value for PROBE_ENV is not valid UTF-8" ) ) ;
489508 }
509+
510+ #[ test]
511+ fn validate_reports_current_non_utf8_tracked_env_glob_value_as_changed ( ) {
512+ let mut tracked_env_globs = BTreeMap :: new ( ) ;
513+ tracked_env_globs. insert ( Str :: from ( "PROBE_*" ) , BTreeMap :: new ( ) ) ;
514+ let fingerprint = PostRunFingerprint { tracked_env_globs, ..PostRunFingerprint :: default ( ) } ;
515+
516+ let mut unfiltered_envs = FxHashMap :: default ( ) ;
517+ unfiltered_envs. insert (
518+ Arc :: < OsStr > :: from ( OsStr :: new ( "PROBE_BAD" ) ) ,
519+ Arc :: < OsStr > :: from ( non_utf8_os_string ( ) ) ,
520+ ) ;
521+
522+ let workspace_root = vite_path:: current_dir ( ) . expect ( "cwd" ) ;
523+ let mismatch =
524+ fingerprint. validate ( & workspace_root, & unfiltered_envs) . expect ( "validation succeeds" ) ;
525+
526+ match mismatch {
527+ Some ( PostRunMismatch :: TrackedEnvGlob {
528+ pattern,
529+ mismatch : EnvMismatch :: Changed { name } ,
530+ } ) => {
531+ assert_eq ! ( pattern. as_str( ) , "PROBE_*" ) ;
532+ assert_eq ! ( name. as_str( ) , "PROBE_BAD" ) ;
533+ }
534+ other => panic ! ( "expected changed tracked env glob mismatch, got {other:?}" ) ,
535+ }
536+ }
490537}
0 commit comments