mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Implement CEReactions codegen
This commit is contained in:
parent
e57ed3d42f
commit
438191e0b2
4 changed files with 73 additions and 15 deletions
|
@ -3152,7 +3152,7 @@ class CGCallGenerator(CGThing):
|
||||||
"""
|
"""
|
||||||
def __init__(self, errorResult, arguments, argsPre, returnType,
|
def __init__(self, errorResult, arguments, argsPre, returnType,
|
||||||
extendedAttributes, descriptor, nativeMethodName,
|
extendedAttributes, descriptor, nativeMethodName,
|
||||||
static, object="this"):
|
static, object="this", hasCEReactions=False):
|
||||||
CGThing.__init__(self)
|
CGThing.__init__(self)
|
||||||
|
|
||||||
assert errorResult is None or isinstance(errorResult, str)
|
assert errorResult is None or isinstance(errorResult, str)
|
||||||
|
@ -3185,6 +3185,9 @@ class CGCallGenerator(CGThing):
|
||||||
call = CGWrapper(call, pre="%s." % object)
|
call = CGWrapper(call, pre="%s." % object)
|
||||||
call = CGList([call, CGWrapper(args, pre="(", post=")")])
|
call = CGList([call, CGWrapper(args, pre="(", post=")")])
|
||||||
|
|
||||||
|
if hasCEReactions:
|
||||||
|
self.cgRoot.append(CGGeneric("push_new_element_queue();\n"))
|
||||||
|
|
||||||
self.cgRoot.append(CGList([
|
self.cgRoot.append(CGList([
|
||||||
CGGeneric("let result: "),
|
CGGeneric("let result: "),
|
||||||
result,
|
result,
|
||||||
|
@ -3193,6 +3196,9 @@ class CGCallGenerator(CGThing):
|
||||||
CGGeneric(";"),
|
CGGeneric(";"),
|
||||||
]))
|
]))
|
||||||
|
|
||||||
|
if hasCEReactions:
|
||||||
|
self.cgRoot.append(CGGeneric("pop_current_element_queue();\n"))
|
||||||
|
|
||||||
if isFallible:
|
if isFallible:
|
||||||
if static:
|
if static:
|
||||||
glob = "global.upcast::<GlobalScope>()"
|
glob = "global.upcast::<GlobalScope>()"
|
||||||
|
@ -3267,11 +3273,12 @@ class CGPerSignatureCall(CGThing):
|
||||||
idlNode.maplikeOrSetlikeOrIterable,
|
idlNode.maplikeOrSetlikeOrIterable,
|
||||||
idlNode.identifier.name))
|
idlNode.identifier.name))
|
||||||
else:
|
else:
|
||||||
|
hasCEReactions = idlNode.getExtendedAttribute("CEReactions")
|
||||||
cgThings.append(CGCallGenerator(
|
cgThings.append(CGCallGenerator(
|
||||||
errorResult,
|
errorResult,
|
||||||
self.getArguments(), self.argsPre, returnType,
|
self.getArguments(), self.argsPre, returnType,
|
||||||
self.extendedAttributes, descriptor, nativeMethodName,
|
self.extendedAttributes, descriptor, nativeMethodName,
|
||||||
static))
|
static, hasCEReactions=hasCEReactions))
|
||||||
|
|
||||||
self.cgRoot = CGList(cgThings, "\n")
|
self.cgRoot = CGList(cgThings, "\n")
|
||||||
|
|
||||||
|
@ -5642,6 +5649,8 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
||||||
'dom::bindings::interface::define_guarded_properties',
|
'dom::bindings::interface::define_guarded_properties',
|
||||||
'dom::bindings::interface::html_constructor',
|
'dom::bindings::interface::html_constructor',
|
||||||
'dom::bindings::interface::is_exposed_in',
|
'dom::bindings::interface::is_exposed_in',
|
||||||
|
'dom::bindings::interface::pop_current_element_queue',
|
||||||
|
'dom::bindings::interface::push_new_element_queue',
|
||||||
'dom::bindings::iterable::Iterable',
|
'dom::bindings::iterable::Iterable',
|
||||||
'dom::bindings::iterable::IteratorType',
|
'dom::bindings::iterable::IteratorType',
|
||||||
'dom::bindings::js::JS',
|
'dom::bindings::js::JS',
|
||||||
|
|
|
@ -103,6 +103,7 @@ use js::jsapi::{TrueHandleValue, Value};
|
||||||
use js::jsval::{JSVal, PrivateValue};
|
use js::jsval::{JSVal, PrivateValue};
|
||||||
use js::rust::{define_methods, define_properties, get_object_class};
|
use js::rust::{define_methods, define_properties, get_object_class};
|
||||||
use libc;
|
use libc;
|
||||||
|
use script_thread::ScriptThread;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
/// The class of a non-callback interface object.
|
/// The class of a non-callback interface object.
|
||||||
|
@ -300,6 +301,14 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
|
||||||
// Custom element upgrades are not implemented yet, so these steps are unnecessary.
|
// Custom element upgrades are not implemented yet, so these steps are unnecessary.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_new_element_queue() {
|
||||||
|
ScriptThread::push_new_element_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_current_element_queue() {
|
||||||
|
ScriptThread::pop_current_element_queue();
|
||||||
|
}
|
||||||
|
|
||||||
/// Create and define the interface object of a callback interface.
|
/// Create and define the interface object of a callback interface.
|
||||||
pub unsafe fn create_callback_interface_object(
|
pub unsafe fn create_callback_interface_object(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
|
|
|
@ -33,6 +33,7 @@ use microtask::Microtask;
|
||||||
use script_thread::ScriptThread;
|
use script_thread::ScriptThread;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -495,6 +496,7 @@ enum BackupElementQueueFlag {
|
||||||
#[derive(HeapSizeOf, JSTraceable)]
|
#[derive(HeapSizeOf, JSTraceable)]
|
||||||
#[must_root]
|
#[must_root]
|
||||||
pub struct CustomElementReactionStack {
|
pub struct CustomElementReactionStack {
|
||||||
|
stack: DOMRefCell<Vec<ElementQueue>>,
|
||||||
backup_queue: ElementQueue,
|
backup_queue: ElementQueue,
|
||||||
processing_backup_element_queue: Cell<BackupElementQueueFlag>,
|
processing_backup_element_queue: Cell<BackupElementQueueFlag>,
|
||||||
}
|
}
|
||||||
|
@ -502,11 +504,29 @@ pub struct CustomElementReactionStack {
|
||||||
impl CustomElementReactionStack {
|
impl CustomElementReactionStack {
|
||||||
pub fn new() -> CustomElementReactionStack {
|
pub fn new() -> CustomElementReactionStack {
|
||||||
CustomElementReactionStack {
|
CustomElementReactionStack {
|
||||||
|
stack: DOMRefCell::new(Vec::new()),
|
||||||
backup_queue: ElementQueue::new(),
|
backup_queue: ElementQueue::new(),
|
||||||
processing_backup_element_queue: Cell::new(BackupElementQueueFlag::NotProcessing),
|
processing_backup_element_queue: Cell::new(BackupElementQueueFlag::NotProcessing),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_new_element_queue(&self) {
|
||||||
|
self.stack.borrow_mut().push(ElementQueue::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_current_element_queue(&self) {
|
||||||
|
rooted_vec!(let mut stack);
|
||||||
|
mem::swap(&mut *stack, &mut *self.stack.borrow_mut());
|
||||||
|
|
||||||
|
if let Some(current_queue) = stack.last() {
|
||||||
|
current_queue.invoke_reactions();
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
|
||||||
|
mem::swap(&mut *self.stack.borrow_mut(), &mut *stack);
|
||||||
|
self.stack.borrow_mut().append(&mut *stack);
|
||||||
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue
|
/// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue
|
||||||
/// Step 4
|
/// Step 4
|
||||||
pub fn invoke_backup_element_queue(&self) {
|
pub fn invoke_backup_element_queue(&self) {
|
||||||
|
@ -519,22 +539,24 @@ impl CustomElementReactionStack {
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue
|
/// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue
|
||||||
pub fn enqueue_element(&self, element: &Element) {
|
pub fn enqueue_element(&self, element: &Element) {
|
||||||
// TODO: Steps 1 - 2
|
if let Some(current_queue) = self.stack.borrow().last() {
|
||||||
// Support multiple queues
|
// Step 2
|
||||||
|
current_queue.append_element(element);
|
||||||
|
} else {
|
||||||
|
// Step 1.1
|
||||||
|
self.backup_queue.append_element(element);
|
||||||
|
|
||||||
// Step 1.1
|
// Step 1.2
|
||||||
self.backup_queue.append_element(element);
|
if self.processing_backup_element_queue.get() == BackupElementQueueFlag::Processing {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Step 1.2
|
// Step 1.3
|
||||||
if self.processing_backup_element_queue.get() == BackupElementQueueFlag::Processing {
|
self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing);
|
||||||
return;
|
|
||||||
|
// Step 4
|
||||||
|
ScriptThread::enqueue_microtask(Microtask::CustomElementReaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1.3
|
|
||||||
self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing);
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
ScriptThread::enqueue_microtask(Microtask::CustomElementReaction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction
|
/// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction
|
||||||
|
|
|
@ -746,6 +746,24 @@ impl ScriptThread {
|
||||||
let _ = window.layout_chan().send(msg);
|
let _ = window.layout_chan().send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_new_element_queue() {
|
||||||
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
|
if let Some(script_thread) = root.get() {
|
||||||
|
let script_thread = unsafe { &*script_thread };
|
||||||
|
script_thread.custom_element_reaction_stack.push_new_element_queue();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_current_element_queue() {
|
||||||
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
|
if let Some(script_thread) = root.get() {
|
||||||
|
let script_thread = unsafe { &*script_thread };
|
||||||
|
script_thread.custom_element_reaction_stack.pop_current_element_queue();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enqueue_callback_reaction(element:&Element, reaction: CallbackReaction) {
|
pub fn enqueue_callback_reaction(element:&Element, reaction: CallbackReaction) {
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
if let Some(script_thread) = root.get() {
|
if let Some(script_thread) = root.get() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue