mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-09 09:33:54 +00:00
Queued tab activations keep the file access scope they were asked in
A document asked for again while a dialog was open was queued by path only, and opened later in the scope of the frame that ran the queue. A request confined to automation roots could then read a file outside them, if the document was closed meanwhile and its path became a link out of the roots. Each queued activation now carries its ScopeHandle and runs in it, as background opens already do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Opus 5.5
parent
8f66e2b694
commit
72cf1a9b3c
@@ -282,8 +282,9 @@ pub(crate) fn open_file(app: &mut VectorcraftApp, path: &str, background: bool)
|
||||
// a drag acts on the active document, its tab comes to the front once that ends
|
||||
// ([`crate::opening::poll`]), as a file that finishes opening then does.
|
||||
if document_index_for_path(app, path).is_some() && !crate::opening::may_switch(app) {
|
||||
if !app.opening.activate.iter().any(|p| same_open_path(p, path)) {
|
||||
app.opening.activate.push(path.to_string());
|
||||
if !app.opening.activate.iter().any(|(p, _)| same_open_path(p, path)) {
|
||||
let scope = vectorcraft_engine::file_access::ScopeHandle::capture();
|
||||
app.opening.activate.push((path.to_string(), scope));
|
||||
}
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ pub struct Pending {
|
||||
pub struct Opening {
|
||||
pub pending: Vec<Pending>,
|
||||
/// Open documents asked for again while the active one couldn't change: their tabs come to
|
||||
/// the front once it can ([`may_switch`]).
|
||||
pub activate: Vec<String>,
|
||||
/// the front once it can ([`may_switch`]), each in the file access scope it was asked in.
|
||||
pub activate: Vec<(String, ScopeHandle)>,
|
||||
}
|
||||
|
||||
/// Is a long operation running that should show the busy cursor and status spinner (background
|
||||
@@ -106,9 +106,9 @@ pub fn poll(app: &mut VectorcraftApp) {
|
||||
if !may_switch(app) {
|
||||
return;
|
||||
}
|
||||
for path in std::mem::take(&mut app.opening.activate) {
|
||||
for (path, scope) in std::mem::take(&mut app.opening.activate) {
|
||||
// Closed meanwhile, it opens again; a failure is reported to the user there.
|
||||
let _ = crate::io::open_reporting(app, &path);
|
||||
let _ = scope.run(|| crate::io::open_reporting(app, &path));
|
||||
}
|
||||
let mut i = 0;
|
||||
while let Some(p) = app.opening.pending.get(i) {
|
||||
|
||||
@@ -409,3 +409,32 @@ fn reopening_while_a_dialog_is_open_waits_for_it_to_close() {
|
||||
assert_eq!((app.session.documents().len(), app.session.active_index()), (2, Some(0)));
|
||||
let _ = std::fs::remove_dir_all(d);
|
||||
}
|
||||
|
||||
/// A document asked for under automation roots while a dialog is open comes to the front, or
|
||||
/// opens again, in those roots once the dialog closes, not in the scope of the frame that runs it
|
||||
/// (#5369): closed meanwhile and now a link to a file outside the roots, it is not read.
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn a_queued_reopen_keeps_the_roots_it_was_asked_in() {
|
||||
use vectorcraft_engine::file_access;
|
||||
let (mut app, d, _) = saved_and_another("queued-roots");
|
||||
let (inside, outside) = (d.join("inside"), d.join("outside"));
|
||||
std::fs::create_dir_all(&inside).unwrap();
|
||||
std::fs::create_dir_all(&outside).unwrap();
|
||||
let path = inside.join("doc.vectorcraft").to_string_lossy().to_string();
|
||||
app.run("document.activate", json!({"index": 0})).unwrap();
|
||||
app.run("file.saveAs", json!({"path": path})).unwrap();
|
||||
app.run("document.activate", json!({"index": 1})).unwrap();
|
||||
app.ui.dialog = Some(crate::state::Dialog::new(crate::dialogs::save_options::KIND, json!({})));
|
||||
let roots = file_access::AutomationRoots::new(&[inside.as_path()], &[]).unwrap();
|
||||
assert_eq!(file_access::confine(roots.as_ref(), || crate::io::open_reporting(&mut app, &path)).unwrap(), serde_json::Value::Null);
|
||||
// Closed, and its file swapped for a link to one outside the roots.
|
||||
app.session.execute("file.close", &json!({"index": 0})).unwrap();
|
||||
let away = outside.join("doc.vectorcraft");
|
||||
std::fs::rename(&path, &away).unwrap();
|
||||
std::os::unix::fs::symlink(&away, &path).unwrap();
|
||||
app.ui.dialog = None;
|
||||
crate::opening::poll(&mut app);
|
||||
assert_eq!(app.session.documents().len(), 1, "the file outside the roots is not opened");
|
||||
let _ = std::fs::remove_dir_all(d);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user