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
+12
-29
@@ -39,9 +39,13 @@
|
||||
}
|
||||
@keyframes ocs-spin { to { transform: rotate(360deg); } }
|
||||
/* Browser-menu print support: hidden on screen, the only thing shown on
|
||||
paper. beforeprint snapshots the WebGL canvas into it (below), so the
|
||||
paper. The Rust side keeps the img synchronized with the WebGL canvas
|
||||
via a frame-callback readback (sys::refresh_print_snapshot), so the
|
||||
printout is the drawing instead of a blank page — WebGL canvases do
|
||||
not composite into the print surface on their own. */
|
||||
not composite into the print surface on their own. A `beforeprint`
|
||||
listener cannot do this: wgpu runs without preserveDrawingBuffer, so
|
||||
by then the drawing buffer is already cleared after composite, and
|
||||
an async capture inside beforeprint finishes after printing started. */
|
||||
#print-snapshot { display: none; }
|
||||
@media print {
|
||||
body > *:not(#print-snapshot) { display: none !important; }
|
||||
@@ -66,7 +70,12 @@
|
||||
<div class="title">Open <span>CAD</span> Studio</div>
|
||||
<div class="sub">Loading…</div>
|
||||
</div>
|
||||
<!-- Print-only copy of the canvas; filled by beforeprint below. -->
|
||||
<!-- Print-only copy of the canvas, kept ALWAYS WARM by the Rust side
|
||||
(sys::refresh_print_snapshot runs off the frames subscription,
|
||||
throttled to ~2 s): the snapshot must exist BEFORE beforeprint
|
||||
fires, because the WebGL drawing buffer is cleared after each
|
||||
composite and cannot be read from a beforeprint listener. No JS
|
||||
here on purpose; the print CSS above does the rest. -->
|
||||
<img id="print-snapshot" alt="" />
|
||||
<script src="ocs-control.js" defer></script>
|
||||
<script>
|
||||
@@ -84,32 +93,6 @@
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
// Print support. The drawing lives in a WebGL canvas, which browsers
|
||||
// rasterize as blank on the print surface. beforeprint therefore copies
|
||||
// it onto a 2D canvas (the same drawImage readback the Rust side's
|
||||
// sys::capture_canvas uses — no Rust state involved, the canvas is
|
||||
// located from the DOM) and shows the snapshot in the print-only
|
||||
// <img>; afterprint drops it again to free the PNG.
|
||||
(() => {
|
||||
const snapshot = document.getElementById("print-snapshot");
|
||||
if (!snapshot) return;
|
||||
window.addEventListener("beforeprint", () => {
|
||||
const canvas = document.querySelector("canvas");
|
||||
if (!canvas || !canvas.width || !canvas.height) return;
|
||||
const copy = document.createElement("canvas");
|
||||
copy.width = canvas.width;
|
||||
copy.height = canvas.height;
|
||||
const context = copy.getContext("2d");
|
||||
if (!context) return;
|
||||
context.drawImage(canvas, 0, 0);
|
||||
snapshot.src = copy.toDataURL("image/png");
|
||||
});
|
||||
window.addEventListener("afterprint", () => {
|
||||
snapshot.removeAttribute("src");
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
(() => {
|
||||
const splash = document.getElementById("loading");
|
||||
|
||||
Reference in new issue
Block a user