Merge pull request #1870 from storytold/fix/svg-link-scope

Importers: an SVG's linked files are read within the automation roots again
This commit is contained in:
BFlat authored and GitHub committed 2026-10-14 10:28:37 +07:00
commit dcd0da87cb
2 files changed
+36 -5

No files matched your search

+10 -5
View File
@@ -273,12 +273,17 @@ pub fn load_with(name: &str, bytes: &[u8], opts: &LoadOptions) -> Result<Loaded>
/// own): rasters stay linked, SVG files become art, missing ones placeholders (see
/// [`vectorcraft_svg::ImportOptions`]).
pub(crate) fn import_svg(text: &str, folder: Option<&str>) -> Result<(Document, Vec<String>)> {
// The importer reads on a thread of its own (for its stack): what may be read is what may be
// read here.
let scope = crate::file_access::ScopeHandle::capture();
let read = |path: &str| {
// Only files (not folders or devices) are read.
file_stamp(path)?;
let bytes = read_file(path).ok()?;
let link = crate::cmd::links::link_info(path, &bytes);
Some((bytes, link))
scope.clone().run(|| {
// Only files (not folders or devices) are read.
file_stamp(path)?;
let bytes = read_file(path).ok()?;
let link = crate::cmd::links::link_info(path, &bytes);
Some((bytes, link))
})
};
vectorcraft_svg::import_with(text, &vectorcraft_svg::ImportOptions { folder, read: Some(&read) }).map_err(err)
}
+26
View File
@@ -314,6 +314,32 @@ fn a_copy_stays_inside_the_write_root() {
let _ = std::fs::remove_dir_all(&root);
}
/// An SVG's linked files are read on the importer's own thread (it needs a deep stack): the roots
/// in force on the thread that opens the SVG hold there too.
#[test]
fn an_svg_reads_its_links_within_the_read_root() {
let root = folder("svg-roots");
for dir in ["in", "out"] {
write(&root.join(dir).join("dot.png"), &png(4, 4, RED));
}
// What came of an SVG linking to the picture in `dir`: the pictures read, and the warnings.
let import = |dir: &str| {
let href = root.join(dir).join("dot.png").to_string_lossy().replace('\\', "/");
let svg =
format!("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\"><image width=\"4\" height=\"4\" href=\"{href}\"/></svg>");
let (doc, warnings) = crate::cmd::fileio::import_svg(&svg, None).unwrap();
(doc.images.len(), warnings)
};
let (inside, outside) = (import("in"), import("out"));
assert_eq!(inside, outside, "both are read with no roots in force");
let roots = crate::file_access::AutomationRoots::new(Some(&root.join("in")), None).unwrap();
crate::file_access::confine(roots.as_ref(), || {
assert_eq!(import("in"), inside, "inside the read root: read as before");
assert_ne!(import("out"), outside, "outside the read root: not read");
});
let _ = std::fs::remove_dir_all(&root);
}
#[test]
fn junk_search_params_never_fail_internally() {
let root = folder("junk");