mirror of
https://github.com/servo/servo.git
synced 2025-06-13 19:04:30 +00:00
Perform a microtask checkpoint after executing classic scripts and callbacks.
This commit is contained in:
parent
32d4f84a30
commit
b5d2bd757b
7 changed files with 49 additions and 25 deletions
|
@ -11,6 +11,7 @@ use js::jsapi::JSTracer;
|
||||||
use js::jsapi::UnhideScriptedCaller;
|
use js::jsapi::UnhideScriptedCaller;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
thread_local!(static STACK: RefCell<Vec<StackEntry>> = RefCell::new(Vec::new()));
|
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.
|
/// RAII struct that pushes and pops entries from the script settings stack.
|
||||||
pub struct AutoEntryScript {
|
pub struct AutoEntryScript {
|
||||||
global: usize,
|
global: Root<GlobalScope>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AutoEntryScript {
|
impl AutoEntryScript {
|
||||||
|
@ -50,7 +51,7 @@ impl AutoEntryScript {
|
||||||
kind: StackEntryKind::Entry,
|
kind: StackEntryKind::Entry,
|
||||||
});
|
});
|
||||||
AutoEntryScript {
|
AutoEntryScript {
|
||||||
global: global as *const _ as usize,
|
global: Root::from_ref(global),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -62,12 +63,17 @@ impl Drop for AutoEntryScript {
|
||||||
STACK.with(|stack| {
|
STACK.with(|stack| {
|
||||||
let mut stack = stack.borrow_mut();
|
let mut stack = stack.borrow_mut();
|
||||||
let entry = stack.pop().unwrap();
|
let entry = stack.pop().unwrap();
|
||||||
assert_eq!(&*entry.global as *const GlobalScope as usize,
|
assert_eq!(&*entry.global as *const GlobalScope,
|
||||||
self.global,
|
&*self.global as *const GlobalScope,
|
||||||
"Dropped AutoEntryScript out of order.");
|
"Dropped AutoEntryScript out of order.");
|
||||||
assert_eq!(entry.kind, StackEntryKind::Entry);
|
assert_eq!(entry.kind, StackEntryKind::Entry);
|
||||||
trace!("Clean up after running script with {:p}", &*entry.global);
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -449,6 +449,17 @@ impl GlobalScope {
|
||||||
unreachable!();
|
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.
|
/// Enqueue a microtask for subsequent execution.
|
||||||
pub fn enqueue_microtask(&self, job: Microtask) {
|
pub fn enqueue_microtask(&self, job: Microtask) {
|
||||||
if self.is::<Window>() {
|
if self.is::<Window>() {
|
||||||
|
|
|
@ -486,11 +486,7 @@ impl HTMLScriptElement {
|
||||||
document.set_current_script(Some(self));
|
document.set_current_script(Some(self));
|
||||||
|
|
||||||
// Step 5.a.2.
|
// Step 5.a.2.
|
||||||
let window = window_from_node(self);
|
self.run_a_classic_script(&script);
|
||||||
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);
|
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
document.set_current_script(old_script.r());
|
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) {
|
pub fn queue_error_event(&self) {
|
||||||
let window = window_from_node(self);
|
let window = window_from_node(self);
|
||||||
window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"), &window);
|
window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"), &window);
|
||||||
|
|
|
@ -567,6 +567,13 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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>)
|
pub fn page_headers_available(id: &PipelineId, metadata: Option<Metadata>)
|
||||||
-> Option<Root<ServoParser>> {
|
-> Option<Root<ServoParser>> {
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[microtask_after_script.html]
|
|
||||||
type: testharness
|
|
||||||
[Microtask immediately after script]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
[task_microtask_ordering.html]
|
[task_microtask_ordering.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[Basic task and microtask ordering]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Level 1 bossfight (synthetic click)]
|
[Level 1 bossfight (synthetic click)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
bug: https://github.com/servo/servo/issues/1980
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue