aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py13
-rw-r--r--components/script/dom/bindings/interface.rs9
-rw-r--r--components/script/dom/customelementregistry.rs48
-rw-r--r--components/script/script_thread.rs18
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() {