forked from 1b-agent/opencadstudio-upstream
fix: close the adversarial findings on the save/paste/merge wave
Three reviewers over the in-place save, the paste/print/capture bundle, and the upstream merge: two blockers, six majors — all fixed. In-place save (blocker + 2 majors): - A stale retained handle could receive bytes serialized for a DIFFERENT format (Save As .dwg->.dxf whose re-pick failed wrote DXF bytes through the .dwg handle) or silently save in place while the user was told a copy was downloading. The serialized format now travels to completion (tab-keyed pending map), the write requires a matching handle extension AND a live tab, and a failed re-pick drops the old handle before the download fallback. - Discarding an unsaved tab leaked its handle, and a serialization still in flight could then overwrite the real file the user just declined to save. Discard drops the handle; a tab-gone completion downloads instead of writing. - Overlapping saves had no guard (native has one): a wasm in-flight slot refuses a second save with the same localized message, cleared on every exit path. Paste/print/capture (blocker + 2 majors): - pasted_image_name built its timestamp from Date::new(0) — a CONSTANT name, so every paste overwrote every earlier paste's image (the registry is last-wins; the first entity then displayed the second paste's pixels). Real clock, milliseconds, and a collision-suffixed unique name now, with the pure logic tested. - The beforeprint snapshot read the canvas outside the frame — blank on WebGL2 (no preserveDrawingBuffer). The print image is now kept WARM: refreshed on redraw frames (throttled to 2 s, skipped when hidden), so it is ready before the browser ever prints. - A capture op in a hidden tab wedged the ENTIRE automation channel (frames never fire, the pending op blocked every settle). Intake now fails fast when hidden, and a 5 s watchdog expires a parked capture with a clear error. Merge residue (3 majors): - The 9 upstream XREF-bind tests lost in resolution are restored verbatim (the bind feature shipped untested). - The XREF manager panel reported registry-loaded xrefs as NotFound on web — stat now consults the registry first (wasm), with a regression test. - Snap: our endpoint map gained the closing-segment wraparound pair (survey-scale closed polylines kept cm-level precision on the last edge), and the 3D-snap gate no longer suppresses the 2D edge wire when the F4 system is disabled (solid edges were snappable by NEITHER system); the setting is mirrored to the scene with invalidation, and the test that encoded the old bug now pins the fallback.
This commit is contained in:
1 parent
55e3a6a9e2
commit
da9504604e
15 files changed
+1071
-84
No files matched your search
@@ -798,6 +798,11 @@ pub(super) struct OpenCADStudio {
|
||||
main_window: Option<window::Id>,
|
||||
/// Hides drawing UI overlays for one thumbnail capture frame.
|
||||
thumbnail_capture_clean: bool,
|
||||
/// Web: when the print-only snapshot `<img>` was last refreshed (see
|
||||
/// [`crate::sys::refresh_print_snapshot`]). `None` = never captured, so
|
||||
/// the first presented frame fills it.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
print_snapshot_at: Option<Instant>,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pending_native_thumbnail_save: Option<PendingNativeThumbnailSave>,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -2099,6 +2104,12 @@ pub enum Message {
|
||||
/// directly and never emits this.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
ControlCaptureFrame,
|
||||
/// Web: a frame was presented, so the print-only snapshot `<img>` can be
|
||||
/// refreshed from the still-readable canvas (see
|
||||
/// [`crate::sys::refresh_print_snapshot`]). The handler throttles to one
|
||||
/// capture every 2 s; native never emits this.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
PrintSnapshotFrame,
|
||||
ControlToggle,
|
||||
Tick(Instant),
|
||||
/// Periodic drain of plugin-to-host requests that arrived outside a host
|
||||
@@ -4264,6 +4275,8 @@ impl OpenCADStudio {
|
||||
pending_click_snap: None,
|
||||
main_window: None,
|
||||
thumbnail_capture_clean: false,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
print_snapshot_at: None,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pending_native_thumbnail_save: None,
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -4644,6 +4657,30 @@ impl OpenCADStudio {
|
||||
app
|
||||
}
|
||||
|
||||
/// Web: keep the print-only snapshot `<img>` always warm
|
||||
/// ([`crate::sys::refresh_print_snapshot`]). Runs on every presented
|
||||
/// frame but captures at most once every 2 s, and only while the page is
|
||||
/// visible — a hidden tab presents no frames anyway, and skipping keeps a
|
||||
/// backgrounded app from burning encode cycles it cannot need. Frames
|
||||
/// only arrive while the window is actually redrawing, so an idle app
|
||||
/// performs no captures at all; the printout may thus lag the canvas by
|
||||
/// up to the throttle window.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn on_print_snapshot_frame(&mut self) {
|
||||
const THROTTLE: std::time::Duration = std::time::Duration::from_secs(2);
|
||||
if self
|
||||
.print_snapshot_at
|
||||
.is_some_and(|at| at.elapsed() < THROTTLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if !crate::sys::page_visible() {
|
||||
return;
|
||||
}
|
||||
self.print_snapshot_at = Some(Instant::now());
|
||||
crate::sys::refresh_print_snapshot();
|
||||
}
|
||||
|
||||
/// Install `cmd` as the active interactive command for tab `tab`.
|
||||
#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
||||
pub(crate) fn set_active_command(
|
||||
|
||||
Reference in new issue
Block a user