forked from 1b-agent/opencadstudio-upstream
web: worker-route WBLOCK/SAVEALL/ARCHIVE; close the follow-up review
WBLOCK, SAVEALL, and web ARCHIVE now serialize through the Web Worker
like SAVE/AUTOSAVE: prepare on the main thread, writer pass on the
worker, inline fallback on any worker failure. SAVEALL clears each
tab's dirty flag under the same unchanged-tab race guard the single
save uses; ARCHIVE assembles the ZIP in the completion handler so the
transmittal matches the snapshot taken at command time.
The review of the previous fix commit found the collision refusal
still REPLACED the registry bytes — the exact silent retargeting it
was meant to prevent. The refusal now keeps the old registration, the
extraction settings picker reports refused picks in the wizard's error
slot (previously silent, and the stale collision flag could surface as
a wrong-file warning on an unrelated browse), and the xref registry's
same-name ambiguity is documented as a browser fundamental (native
distinguishes by folder): newest registration wins consistently for
resolution, ARCHIVE, and XRELOAD — matching what the drawing displays.
Also: the Quit pending-close survives a successful web tab-save
(continue the quit instead of dropping it), the last ZIP64 sentinel
(central size) is rejected like the other four, and the new behaviors
gained regression tests (collision keeps old bytes, registry eviction,
including the deadlock fix for the guard-scoping that test exposed).
(cherry picked from commit b635d56c)
Ported onto main (#1717 review): ARCHIVE and SAVEALL serialize
document_for_save() like a single web Save; the ZIP is built with the
zip crate; WBLOCK keeps its native background-task title.
This commit is contained in:
1 parent
8968e79942
commit
108ef045b8
6 files changed
+406
-81
No files matched your search
@@ -79,14 +79,18 @@ pub(crate) fn register_picked_source(path: &str, bytes: Arc<Vec<u8>>) -> bool {
|
||||
let mut cache = picked_sources()
|
||||
.lock()
|
||||
.unwrap_or_else(|error| error.into_inner());
|
||||
let replaced = cache
|
||||
.get(path)
|
||||
.is_some_and(|old| old.as_slice() != bytes.as_slice());
|
||||
if replaced {
|
||||
take_last_collision().replace(file_name_of(path));
|
||||
let Some(old) = cache.get(path) else {
|
||||
cache.insert(path.to_string(), bytes);
|
||||
return true;
|
||||
};
|
||||
if old.as_slice() == bytes.as_slice() {
|
||||
return true;
|
||||
}
|
||||
cache.insert(path.to_string(), bytes);
|
||||
!replaced
|
||||
// Refuse AND keep the old bytes: overwriting would silently retarget
|
||||
// every reference reading this name. The name is remembered so the
|
||||
// browse handlers can tell the user why their pick did nothing.
|
||||
take_last_collision().replace(file_name_of(path));
|
||||
false
|
||||
}
|
||||
|
||||
/// The name whose re-pick was refused because different bytes are already
|
||||
@@ -1846,6 +1850,13 @@ impl OpenCADStudio {
|
||||
&mut self,
|
||||
path: Option<PathBuf>,
|
||||
) -> Task<Message> {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
if let Some(name) = take_last_collision().take() {
|
||||
self.data_extraction.error = crate::tf!(
|
||||
"\"{name}\" is already loaded with different contents; the existing file was kept."
|
||||
)
|
||||
.into_owned();
|
||||
}
|
||||
if let Some(path) = path {
|
||||
self.data_extraction.settings_path = path.to_string_lossy().into_owned();
|
||||
if self.data_extraction.begin != ExtractionBegin::New {
|
||||
@@ -2074,6 +2085,23 @@ impl OpenCADStudio {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
/// A refused same-name re-pick must KEEP the old bytes: overwriting
|
||||
/// would silently retarget every reference reading that name.
|
||||
#[test]
|
||||
fn collision_refusal_keeps_the_registered_bytes() {
|
||||
register_picked_source("a.csv", Arc::new(b"old".to_vec()));
|
||||
let fresh = register_picked_source("a.csv", Arc::new(b"new".to_vec()));
|
||||
assert!(!fresh, "differing bytes under a live name are refused");
|
||||
assert_eq!(
|
||||
picked_source_bytes("a.csv").as_ref().map(|b| b.as_slice()),
|
||||
Some(&b"old"[..]),
|
||||
"the old registration survives the refusal"
|
||||
);
|
||||
// Identical bytes are a no-op accept.
|
||||
assert!(register_picked_source("a.csv", Arc::new(b"old".to_vec())));
|
||||
}
|
||||
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user