Make automation "open" run the same finalization as a UI open

Automation's "open" op called io::load_bytes directly and installed
the result as-is, skipping everything the canonical path-based loader
(load_file_for_open / finalize_loaded_outcome) runs after parsing:
block-origin normalization for legacy non-zero-origin blocks,
relative raster/material path resolution, source_path assignment,
and the corrupt-entity purge the UI open path always applies. The
same file opened two ways behaved differently, and headless/automation
use was more exposed to malformed geometry with no filter at all.

Added io::load_bytes_finalized(path, bytes), which runs load_bytes
plus that same normalization and purge using the real path (not just
its basename, which the old code passed to load_bytes as the "name"
parameter — losing the directory needed for raster-path resolution
and source_path). automation.rs's "open" handler now uses it and
reports the purge count as a "purged" field in the response.

load_bytes itself is unchanged, since the byte round-trip tests
(sketch_persist.rs, named_parameters_persist.rs) deliberately want
the simpler byte-only path with no real filesystem path behind it.

New test constructs a document with one normal and one corrupt
(zero-radius) entity, saves it, opens it through automation, and
checks the corrupt entity was purged and source_path was set —
proving the automation path now matches the UI path.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Felix RiestraandClaude Sonnet 5 committed 2026-09-09 10:13:06 +02:00
1 parent 8bc9e83c2e
commit d0025d6ddf
2 files changed
+89 -9

No files matched your search

+26
View File
@@ -744,6 +744,32 @@ pub fn load_bytes(name: &str, bytes: Vec<u8>) -> Result<CadDocument, String> {
}
}
/// [`load_bytes`] plus the same finalization and corruption handling the
/// canonical path-based open (`load_file_for_open`/`finalize_loaded_outcome`)
/// already runs — for a byte-based open that nonetheless has a real
/// filesystem path behind it (automation's `"open"` op reads the file into
/// memory itself, e.g. to go through an edit lease, but the drawing still
/// lives at `path`). Without this, automation-opened documents kept
/// legacy non-zero block origins un-normalized, left relative raster/material
/// paths unresolved, carried no `source_path`, and skipped the corrupt-entity
/// purge the UI open path always runs — silently behaving differently from a
/// UI open of the exact same file. `load_bytes` itself is unchanged (and
/// still used directly by the byte round-trip tests, which have no real path
/// and don't want this finalization).
#[cfg(not(target_arch = "wasm32"))]
pub fn load_bytes_finalized(path: &Path, bytes: Vec<u8>) -> Result<(CadDocument, usize), String> {
let name = path
.file_name()
.map(|n| n.to_string_lossy().into_owned())
.unwrap_or_else(|| path.to_string_lossy().into_owned());
let mut doc = load_bytes(&name, bytes)?;
normalize_block_origins(&mut doc);
resolve_raster_image_paths(&mut doc, path.parent());
doc.source_path = Some(path.to_string_lossy().into_owned());
let dropped = purge_corrupt_entities(&mut doc);
Ok((doc, dropped))
}
/// Load a DWG or DXF file directly from a path (auto-detect by extension).
/// Peek at a file's leading bytes to tell a DWG (version tag "AC10xx") from a
/// DXF. Used for `.bak` copies, whose extension hides the real format.