diff options
author | Josh Matthews <josh@joshmatthews.net> | 2017-01-12 12:53:53 -0500 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2017-02-01 12:54:33 -0500 |
commit | b5d2bd757b45aa7f1e61c947d883eb977c6ad7af (patch) | |
tree | a43aaa5c69190004106f8fb49a29a06326cc77d4 | |
parent | 32d4f84a30035b6b1094f7e68adbe1e6a883bb9b (diff) | |
download | servo-b5d2bd757b45aa7f1e61c947d883eb977c6ad7af.tar.gz servo-b5d2bd757b45aa7f1e61c947d883eb977c6ad7af.zip |
Perform a microtask checkpoint after executing classic scripts and callbacks.
7 files changed, 49 insertions, 25 deletions
diff --git a/components/script/dom/bindings/settings_stack.rs b/components/script/dom/bindings/settings_stack.rs index 10afc833cb4..dec63924915 100644 --- a/components/script/dom/bindings/settings_stack.rs +++ b/components/script/dom/bindings/settings_stack.rs @@ -11,6 +11,7 @@ use js::jsapi::JSTracer; use js::jsapi::UnhideScriptedCaller; use js::rust::Runtime; use std::cell::RefCell; +use std::thread; thread_local!(static STACK: RefCell<Vec<StackEntry>> = RefCell::new(Vec::new())); @@ -36,7 +37,7 @@ pub unsafe fn trace(tracer: *mut JSTracer) { /// RAII struct that pushes and pops entries from the script settings stack. pub struct AutoEntryScript { - global: usize, + global: Root<GlobalScope>, } impl AutoEntryScript { @@ -50,7 +51,7 @@ impl AutoEntryScript { kind: StackEntryKind::Entry, }); AutoEntryScript { - global: global as *const _ as usize, + global: Root::from_ref(global), } }) } @@ -62,12 +63,17 @@ impl Drop for AutoEntryScript { STACK.with(|stack| { let mut stack = stack.borrow_mut(); let entry = stack.pop().unwrap(); - assert_eq!(&*entry.global as *const GlobalScope as usize, - self.global, + assert_eq!(&*entry.global as *const GlobalScope, + &*self.global as *const GlobalScope, "Dropped AutoEntryScript out of order."); assert_eq!(entry.kind, StackEntryKind::Entry); trace!("Clean up after running script with {:p}", &*entry.global); - }) + }); + + // Step 5 + if !thread::panicking() && incumbent_global().is_none() { + self.global.perform_a_microtask_checkpoint(); + } } } diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index aaebf091c6d..cc42ef18d06 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -449,6 +449,17 @@ impl GlobalScope { unreachable!(); } + /// Perform a microtask checkpoint. + pub fn perform_a_microtask_checkpoint(&self) { + if self.is::<Window>() { + return ScriptThread::invoke_perform_a_microtask_checkpoint(); + } + if let Some(worker) = self.downcast::<WorkerGlobalScope>() { + return worker.perform_a_microtask_checkpoint(); + } + unreachable!(); + } + /// Enqueue a microtask for subsequent execution. pub fn enqueue_microtask(&self, job: Microtask) { if self.is::<Window>() { diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index e1e8dabac7b..8703a45ea82 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -486,11 +486,7 @@ impl HTMLScriptElement { document.set_current_script(Some(self)); // Step 5.a.2. - let window = window_from_node(self); - let line_number = if script.external { 1 } else { self.line_number as u32 }; - rooted!(in(window.get_cx()) let mut rval = UndefinedValue()); - window.upcast::<GlobalScope>().evaluate_script_on_global_with_result( - &script.text, script.url.as_str(), rval.handle_mut(), line_number); + self.run_a_classic_script(&script); // Step 6. document.set_current_script(old_script.r()); @@ -506,6 +502,24 @@ impl HTMLScriptElement { } } + // https://html.spec.whatwg.org/multipage/#run-a-classic-script + pub fn run_a_classic_script(&self, script: &ClassicScript) { + // TODO use a settings object rather than this element's document/window + // Step 2 + let document = document_from_node(self); + if !document.is_fully_active() || !document.is_scripting_enabled() { + return; + } + + // Steps 4-10 + let window = window_from_node(self); + let line_number = if script.external { 1 } else { self.line_number as u32 }; + rooted!(in(window.get_cx()) let mut rval = UndefinedValue()); + let global = window.upcast::<GlobalScope>(); + global.evaluate_script_on_global_with_result( + &script.text, script.url.as_str(), rval.handle_mut(), line_number); + } + pub fn queue_error_event(&self) { let window = window_from_node(self); window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"), &window); diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index d204ab776b8..f54ff2ca097 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -567,6 +567,13 @@ impl ScriptThreadFactory for ScriptThread { } impl ScriptThread { + pub fn invoke_perform_a_microtask_checkpoint() { + SCRIPT_THREAD_ROOT.with(|root| { + let script_thread = unsafe { &*root.get().unwrap() }; + script_thread.perform_a_microtask_checkpoint() + }) + } + pub fn page_headers_available(id: &PipelineId, metadata: Option<Metadata>) -> Option<Root<ServoParser>> { SCRIPT_THREAD_ROOT.with(|root| { diff --git a/tests/wpt/metadata/html/webappapis/scripting/event-loops/microtask_after_raf.html.ini b/tests/wpt/metadata/html/webappapis/scripting/event-loops/microtask_after_raf.html.ini deleted file mode 100644 index 9ebe79a9879..00000000000 --- a/tests/wpt/metadata/html/webappapis/scripting/event-loops/microtask_after_raf.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[microtask_after_raf.html] - type: testharness - disabled: https://github.com/servo/servo/issues/13501 - [Microtask execute immediately after script] - expected: FAIL - diff --git a/tests/wpt/metadata/html/webappapis/scripting/event-loops/microtask_after_script.html.ini b/tests/wpt/metadata/html/webappapis/scripting/event-loops/microtask_after_script.html.ini deleted file mode 100644 index 49871c85772..00000000000 --- a/tests/wpt/metadata/html/webappapis/scripting/event-loops/microtask_after_script.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[microtask_after_script.html] - type: testharness - [Microtask immediately after script] - expected: FAIL - diff --git a/tests/wpt/metadata/html/webappapis/scripting/event-loops/task_microtask_ordering.html.ini b/tests/wpt/metadata/html/webappapis/scripting/event-loops/task_microtask_ordering.html.ini index 8d063ebb67f..a9a640fee27 100644 --- a/tests/wpt/metadata/html/webappapis/scripting/event-loops/task_microtask_ordering.html.ini +++ b/tests/wpt/metadata/html/webappapis/scripting/event-loops/task_microtask_ordering.html.ini @@ -1,8 +1,5 @@ [task_microtask_ordering.html] type: testharness - [Basic task and microtask ordering] - expected: FAIL - [Level 1 bossfight (synthetic click)] expected: FAIL - + bug: https://github.com/servo/servo/issues/1980 |