diff options
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 13 | ||||
-rw-r--r-- | components/script/dom/bindings/interface.rs | 9 | ||||
-rw-r--r-- | components/script/dom/customelementregistry.rs | 48 | ||||
-rw-r--r-- | components/script/script_thread.rs | 18 |
4 files changed, 73 insertions, 15 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 5f60a9fc5fa..efb39208b44 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -3152,7 +3152,7 @@ class CGCallGenerator(CGThing): """ def __init__(self, errorResult, arguments, argsPre, returnType, extendedAttributes, descriptor, nativeMethodName, - static, object="this"): + static, object="this", hasCEReactions=False): CGThing.__init__(self) assert errorResult is None or isinstance(errorResult, str) @@ -3185,6 +3185,9 @@ class CGCallGenerator(CGThing): call = CGWrapper(call, pre="%s." % object) call = CGList([call, CGWrapper(args, pre="(", post=")")]) + if hasCEReactions: + self.cgRoot.append(CGGeneric("push_new_element_queue();\n")) + self.cgRoot.append(CGList([ CGGeneric("let result: "), result, @@ -3193,6 +3196,9 @@ class CGCallGenerator(CGThing): CGGeneric(";"), ])) + if hasCEReactions: + self.cgRoot.append(CGGeneric("pop_current_element_queue();\n")) + if isFallible: if static: glob = "global.upcast::<GlobalScope>()" @@ -3267,11 +3273,12 @@ class CGPerSignatureCall(CGThing): idlNode.maplikeOrSetlikeOrIterable, idlNode.identifier.name)) else: + hasCEReactions = idlNode.getExtendedAttribute("CEReactions") cgThings.append(CGCallGenerator( errorResult, self.getArguments(), self.argsPre, returnType, self.extendedAttributes, descriptor, nativeMethodName, - static)) + static, hasCEReactions=hasCEReactions)) 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::html_constructor', '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::IteratorType', 'dom::bindings::js::JS', diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index 9900bf00e9a..887a62f11eb 100644 --- a/components/script/dom/bindings/interface.rs +++ b/components/script/dom/bindings/interface.rs @@ -103,6 +103,7 @@ use js::jsapi::{TrueHandleValue, Value}; use js::jsval::{JSVal, PrivateValue}; use js::rust::{define_methods, define_properties, get_object_class}; use libc; +use script_thread::ScriptThread; use std::ptr; /// 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. } +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. pub unsafe fn create_callback_interface_object( cx: *mut JSContext, diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 0d151abb127..998c4fdcb12 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -33,6 +33,7 @@ use microtask::Microtask; use script_thread::ScriptThread; use std::cell::Cell; use std::collections::{HashMap, VecDeque}; +use std::mem; use std::ops::Deref; use std::ptr; use std::rc::Rc; @@ -495,6 +496,7 @@ enum BackupElementQueueFlag { #[derive(HeapSizeOf, JSTraceable)] #[must_root] pub struct CustomElementReactionStack { + stack: DOMRefCell<Vec<ElementQueue>>, backup_queue: ElementQueue, processing_backup_element_queue: Cell<BackupElementQueueFlag>, } @@ -502,11 +504,29 @@ pub struct CustomElementReactionStack { impl CustomElementReactionStack { pub fn new() -> CustomElementReactionStack { CustomElementReactionStack { + stack: DOMRefCell::new(Vec::new()), backup_queue: ElementQueue::new(), 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 /// Step 4 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 pub fn enqueue_element(&self, element: &Element) { - // TODO: Steps 1 - 2 - // Support multiple queues - - // Step 1.1 - self.backup_queue.append_element(element); + if let Some(current_queue) = self.stack.borrow().last() { + // Step 2 + current_queue.append_element(element); + } else { + // Step 1.1 + self.backup_queue.append_element(element); - // Step 1.2 - if self.processing_backup_element_queue.get() == BackupElementQueueFlag::Processing { - return; - } + // Step 1.2 + if self.processing_backup_element_queue.get() == BackupElementQueueFlag::Processing { + return; + } - // Step 1.3 - self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing); + // Step 1.3 + self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing); - // Step 4 - ScriptThread::enqueue_microtask(Microtask::CustomElementReaction); + // Step 4 + ScriptThread::enqueue_microtask(Microtask::CustomElementReaction); + } } /// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index cb4603f805e..5ed642f11c7 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -746,6 +746,24 @@ impl ScriptThread { 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) { SCRIPT_THREAD_ROOT.with(|root| { if let Some(script_thread) = root.get() { |