Perform a microtask checkpoint after executing classic scripts and callbacks.

This commit is contained in:
Josh Matthews 2017-01-12 12:53:53 -05:00
parent 32d4f84a30
commit b5d2bd757b
7 changed files with 49 additions and 25 deletions

View file

@ -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();
}
}
}

View file

@ -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>() {

View file

@ -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);

View file

@ -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| {

View file

@ -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

View file

@ -1,5 +0,0 @@
[microtask_after_script.html]
type: testharness
[Microtask immediately after script]
expected: FAIL

View file

@ -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