mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-12 15:52:52 +00:00
Merge pull request #6779 from dotCooCoo/fix/script-sleep-reads-doc-cancel
Scripts: a canceled request stops a run asleep in $.sleep at its next slice
This commit is contained in:
@@ -1787,6 +1787,10 @@ impl Session {
|
||||
if let Some(e) = job.host.dialogs.take_failure() {
|
||||
return Some(self.script_failed(job, &e));
|
||||
}
|
||||
// A canceled request ends a sleep or a wait at this pump.
|
||||
if vectorcraft_doc::cancel::check().is_err() {
|
||||
self.script_stop.set();
|
||||
}
|
||||
if (job.host.waiting.get() || job.host.asleep().is_some() || job.host.dialogs.is_waiting()) && !self.script_stop.is_set() {
|
||||
JOBS.with(|jobs| jobs.borrow_mut().insert(key.id, job));
|
||||
self.script_key = Some(key);
|
||||
@@ -1798,9 +1802,6 @@ impl Session {
|
||||
let e = RunError { kind: RunErrorKind::Limit(kind), message: format!("limit reached: {kind:?}"), line: 0, column: 0 };
|
||||
return Some(self.script_failed(job, &e));
|
||||
}
|
||||
if vectorcraft_doc::cancel::check().is_err() {
|
||||
self.script_stop.set();
|
||||
}
|
||||
job.host.calls_this_slice.set(0);
|
||||
let outcome = run_slice(self, &mut job);
|
||||
match outcome {
|
||||
|
||||
@@ -217,6 +217,26 @@ fn dialog_loop_stops_or_exhausts() {
|
||||
assert_eq!(art(&s), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_run_waiting_at_a_dialog_stops_at_the_next_slice_once_its_work_is_canceled() {
|
||||
let mut s = one_doc();
|
||||
let before = art(&s);
|
||||
let token = crate::cancel::CancelToken::new();
|
||||
s.script_frames = true;
|
||||
let source = "vc.run('shape.rectangle', {x: 20, y: 0, width: 5, height: 5}); alert('x'); vc.log('answered');";
|
||||
assert_eq!(s.execute("script.run", &json!({"source": source, "name": "d.js"})).unwrap()["running"], true);
|
||||
assert!(crate::cancel::scope(&token, None, || s.script_pump()).is_none());
|
||||
assert!(s.script_dialog().is_some());
|
||||
token.cancel();
|
||||
let ended = crate::cancel::scope(&token, None, || s.script_pump());
|
||||
assert!(ended.expect("the run goes on waiting for an answer").is_err());
|
||||
let report = s.script_report().unwrap();
|
||||
assert_eq!((report["kind"].as_str(), &report["log"]), (Some("stopped"), &json!([])), "{report}");
|
||||
assert_eq!(report["dialogs"][0]["answer"], "stop");
|
||||
assert_eq!(s.script_dialog(), None);
|
||||
assert_eq!(art(&s), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dialog_text_limits_and_controls() {
|
||||
let mut s = one_doc();
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::time::Duration;
|
||||
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use crate::cancel::{self, CancelToken};
|
||||
use crate::script::{TEST_ELAPSED, TEST_NO_CLOCK};
|
||||
use crate::*;
|
||||
|
||||
@@ -204,6 +205,36 @@ fn a_sleeping_run_stops_when_asked() {
|
||||
TEST_ELAPSED.set(None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_sleeping_run_stops_at_the_next_slice_once_its_work_is_canceled() {
|
||||
for (asleep_until, when) in
|
||||
[(None, "before its first slice"), (Some(Duration::ZERO), "while it sleeps"), (Some(Duration::from_secs(1)), "at its wake time")]
|
||||
{
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
let before = (format!("{:?}", s.documents()[0].doc.layers), s.documents()[0].history.undo.len());
|
||||
s.script_frames = true;
|
||||
TEST_ELAPSED.set(Some(Duration::ZERO));
|
||||
let source = "vc.run('shape.rectangle', {x: 0, y: 0, width: 5, height: 5}); $.sleep(1000); vc.log('woke'); \
|
||||
vc.run('shape.rectangle', {x: 9, y: 0, width: 5, height: 5});";
|
||||
s.execute("script.run", &json!({"source": source, "name": "t.js"})).unwrap();
|
||||
let token = CancelToken::new();
|
||||
if let Some(at) = asleep_until {
|
||||
assert!(cancel::scope(&token, None, || s.script_pump()).is_none(), "{when}");
|
||||
assert_eq!(s.script_sleep_left(), Some(Duration::from_secs(1)), "{when}");
|
||||
TEST_ELAPSED.set(Some(at));
|
||||
}
|
||||
token.cancel();
|
||||
let ended = cancel::scope(&token, None, || s.script_pump());
|
||||
TEST_ELAPSED.set(None);
|
||||
assert!(ended.unwrap_or_else(|| panic!("{when}: the run goes on waiting")).is_err(), "{when}");
|
||||
let report = s.script_report().unwrap();
|
||||
assert_eq!((report["kind"].as_str(), &report["log"]), (Some("stopped"), &json!([])), "{when}: {report}");
|
||||
assert!(!s.script_running(), "{when}");
|
||||
assert_eq!((format!("{:?}", s.documents()[0].doc.layers), s.documents()[0].history.undo.len()), before, "{when}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sleep_takes_milliseconds_from_0_to_1000() {
|
||||
let mut s = Session::new();
|
||||
|
||||
@@ -845,6 +845,30 @@ fn a_person_can_let_a_growing_run_go_on_or_stop_it() {
|
||||
assert_eq!(state(&s), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_run_waiting_to_grow_stops_at_the_next_slice_once_its_work_is_canceled() {
|
||||
TEST_GROWTH.with(|g| g.set(Some(20)));
|
||||
let mut s = two_docs();
|
||||
let before = state(&s);
|
||||
s.script_frames = true;
|
||||
run(&mut s, "for (var i = 0; i < 25; i++) vc.run('shape.rectangle', {x:i,y:1,width:1,height:1});").unwrap();
|
||||
let token = crate::cancel::CancelToken::new();
|
||||
for _ in 0..1_000 {
|
||||
if s.script_waiting() {
|
||||
break;
|
||||
}
|
||||
assert!(crate::cancel::scope(&token, None, || s.script_pump()).is_none());
|
||||
}
|
||||
assert!(s.script_waiting());
|
||||
token.cancel();
|
||||
let ended = crate::cancel::scope(&token, None, || s.script_pump());
|
||||
TEST_GROWTH.with(|g| g.set(None));
|
||||
assert!(ended.expect("the run goes on waiting for Continue").is_err());
|
||||
assert_eq!(s.script_report().unwrap()["kind"], "stopped");
|
||||
assert!(!s.script_running());
|
||||
assert_eq!(state(&s), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_file_saved_before_a_failure_stays_written_and_is_named() {
|
||||
let path = std::env::temp_dir().join(format!("vc-script-save-{}.svg", std::process::id()));
|
||||
|
||||
Reference in New Issue
Block a user