Skip to content

Commit ea9c408

Browse files
committed
servo: Merge #17761 - Add [CEReactions] to webidls (from cbrewster:ce_reactions); r=jdm
<!-- Please describe your changes on the following line: --> Relies on #17614 --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: a6739cb17f381b88531eb6173d048868aec8e082
1 parent bd9bd29 commit ea9c408

File tree

82 files changed

+1144
-750
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1144
-750
lines changed

servo/components/script/dom/bindings/codegen/CodegenRust.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3152,7 +3152,7 @@ class CGCallGenerator(CGThing):
31523152
"""
31533153
def __init__(self, errorResult, arguments, argsPre, returnType,
31543154
extendedAttributes, descriptor, nativeMethodName,
3155-
static, object="this"):
3155+
static, object="this", hasCEReactions=False):
31563156
CGThing.__init__(self)
31573157

31583158
assert errorResult is None or isinstance(errorResult, str)
@@ -3185,6 +3185,9 @@ def __init__(self, errorResult, arguments, argsPre, returnType,
31853185
call = CGWrapper(call, pre="%s." % object)
31863186
call = CGList([call, CGWrapper(args, pre="(", post=")")])
31873187

3188+
if hasCEReactions:
3189+
self.cgRoot.append(CGGeneric("push_new_element_queue();\n"))
3190+
31883191
self.cgRoot.append(CGList([
31893192
CGGeneric("let result: "),
31903193
result,
@@ -3193,6 +3196,9 @@ def __init__(self, errorResult, arguments, argsPre, returnType,
31933196
CGGeneric(";"),
31943197
]))
31953198

3199+
if hasCEReactions:
3200+
self.cgRoot.append(CGGeneric("pop_current_element_queue();\n"))
3201+
31963202
if isFallible:
31973203
if static:
31983204
glob = "global.upcast::<GlobalScope>()"
@@ -3267,11 +3273,12 @@ def __init__(self, returnType, argsPre, arguments, nativeMethodName, static,
32673273
idlNode.maplikeOrSetlikeOrIterable,
32683274
idlNode.identifier.name))
32693275
else:
3276+
hasCEReactions = idlNode.getExtendedAttribute("CEReactions")
32703277
cgThings.append(CGCallGenerator(
32713278
errorResult,
32723279
self.getArguments(), self.argsPre, returnType,
32733280
self.extendedAttributes, descriptor, nativeMethodName,
3274-
static))
3281+
static, hasCEReactions=hasCEReactions))
32753282

32763283
self.cgRoot = CGList(cgThings, "\n")
32773284

@@ -5642,6 +5649,8 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
56425649
'dom::bindings::interface::define_guarded_properties',
56435650
'dom::bindings::interface::html_constructor',
56445651
'dom::bindings::interface::is_exposed_in',
5652+
'dom::bindings::interface::pop_current_element_queue',
5653+
'dom::bindings::interface::push_new_element_queue',
56455654
'dom::bindings::iterable::Iterable',
56465655
'dom::bindings::iterable::IteratorType',
56475656
'dom::bindings::js::JS',

servo/components/script/dom/bindings/interface.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ use js::jsapi::{TrueHandleValue, Value};
103103
use js::jsval::{JSVal, PrivateValue};
104104
use js::rust::{define_methods, define_properties, get_object_class};
105105
use libc;
106+
use script_thread::ScriptThread;
106107
use std::ptr;
107108

108109
/// The class of a non-callback interface object.
@@ -300,6 +301,14 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
300301
// Custom element upgrades are not implemented yet, so these steps are unnecessary.
301302
}
302303

304+
pub fn push_new_element_queue() {
305+
ScriptThread::push_new_element_queue();
306+
}
307+
308+
pub fn pop_current_element_queue() {
309+
ScriptThread::pop_current_element_queue();
310+
}
311+
303312
/// Create and define the interface object of a callback interface.
304313
pub unsafe fn create_callback_interface_object(
305314
cx: *mut JSContext,

servo/components/script/dom/customelementregistry.rs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use microtask::Microtask;
3333
use script_thread::ScriptThread;
3434
use std::cell::Cell;
3535
use std::collections::{HashMap, VecDeque};
36+
use std::mem;
3637
use std::ops::Deref;
3738
use std::ptr;
3839
use std::rc::Rc;
@@ -495,18 +496,37 @@ enum BackupElementQueueFlag {
495496
#[derive(HeapSizeOf, JSTraceable)]
496497
#[must_root]
497498
pub struct CustomElementReactionStack {
499+
stack: DOMRefCell<Vec<ElementQueue>>,
498500
backup_queue: ElementQueue,
499501
processing_backup_element_queue: Cell<BackupElementQueueFlag>,
500502
}
501503

502504
impl CustomElementReactionStack {
503505
pub fn new() -> CustomElementReactionStack {
504506
CustomElementReactionStack {
507+
stack: DOMRefCell::new(Vec::new()),
505508
backup_queue: ElementQueue::new(),
506509
processing_backup_element_queue: Cell::new(BackupElementQueueFlag::NotProcessing),
507510
}
508511
}
509512

513+
pub fn push_new_element_queue(&self) {
514+
self.stack.borrow_mut().push(ElementQueue::new());
515+
}
516+
517+
pub fn pop_current_element_queue(&self) {
518+
rooted_vec!(let mut stack);
519+
mem::swap(&mut *stack, &mut *self.stack.borrow_mut());
520+
521+
if let Some(current_queue) = stack.last() {
522+
current_queue.invoke_reactions();
523+
}
524+
stack.pop();
525+
526+
mem::swap(&mut *self.stack.borrow_mut(), &mut *stack);
527+
self.stack.borrow_mut().append(&mut *stack);
528+
}
529+
510530
/// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue
511531
/// Step 4
512532
pub fn invoke_backup_element_queue(&self) {
@@ -519,22 +539,24 @@ impl CustomElementReactionStack {
519539

520540
/// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue
521541
pub fn enqueue_element(&self, element: &Element) {
522-
// TODO: Steps 1 - 2
523-
// Support multiple queues
524-
525-
// Step 1.1
526-
self.backup_queue.append_element(element);
542+
if let Some(current_queue) = self.stack.borrow().last() {
543+
// Step 2
544+
current_queue.append_element(element);
545+
} else {
546+
// Step 1.1
547+
self.backup_queue.append_element(element);
527548

528-
// Step 1.2
529-
if self.processing_backup_element_queue.get() == BackupElementQueueFlag::Processing {
530-
return;
531-
}
549+
// Step 1.2
550+
if self.processing_backup_element_queue.get() == BackupElementQueueFlag::Processing {
551+
return;
552+
}
532553

533-
// Step 1.3
534-
self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing);
554+
// Step 1.3
555+
self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing);
535556

536-
// Step 4
537-
ScriptThread::enqueue_microtask(Microtask::CustomElementReaction);
557+
// Step 4
558+
ScriptThread::enqueue_microtask(Microtask::CustomElementReaction);
559+
}
538560
}
539561

540562
/// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction
@@ -578,9 +600,11 @@ impl CustomElementReactionStack {
578600
unsafe { val.to_jsval(cx, value.handle_mut()); }
579601
}
580602

581-
let namespace = DOMString::from(&*namespace);
582-
rooted!(in(cx) let mut namespace_value = UndefinedValue());
583-
unsafe { namespace.to_jsval(cx, namespace_value.handle_mut()); }
603+
rooted!(in(cx) let mut namespace_value = NullValue());
604+
if namespace != ns!() {
605+
let namespace = DOMString::from(&*namespace);
606+
unsafe { namespace.to_jsval(cx, namespace_value.handle_mut()); }
607+
}
584608

585609
let args = vec![Heap::default(), Heap::default(), Heap::default(), Heap::default()];
586610
args[0].set(name_value.get());

servo/components/script/dom/node.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,13 +1422,12 @@ impl Node {
14221422
for descendant in node.traverse_preorder() {
14231423
descendant.set_owner_doc(document);
14241424
}
1425-
for descendant in node.traverse_preorder() {
1425+
for descendant in node.traverse_preorder().filter_map(|d| d.as_custom_element()) {
14261426
// Step 3.2.
1427-
if let Some(element) = node.as_custom_element() {
1428-
ScriptThread::enqueue_callback_reaction(&*element,
1429-
CallbackReaction::Adopted(old_doc.clone(), Root::from_ref(document)));
1430-
}
1431-
1427+
ScriptThread::enqueue_callback_reaction(&*descendant,
1428+
CallbackReaction::Adopted(old_doc.clone(), Root::from_ref(document)));
1429+
}
1430+
for descendant in node.traverse_preorder() {
14321431
// Step 3.3.
14331432
vtable_for(&descendant).adopting_steps(&old_doc);
14341433
}
@@ -1636,9 +1635,17 @@ impl Node {
16361635
for kid in new_nodes {
16371636
// Step 7.1.
16381637
parent.add_child(*kid, child);
1639-
// Step 7.2: insertion steps.
1640-
if let Some(element) = kid.as_custom_element() {
1641-
ScriptThread::enqueue_callback_reaction(&*element, CallbackReaction::Connected);
1638+
// Step 7.7.
1639+
for descendant in kid.traverse_preorder().filter_map(Root::downcast::<Element>) {
1640+
// Step 7.7.2.
1641+
if descendant.is_connected() {
1642+
// Step 7.7.2.1.
1643+
if descendant.get_custom_element_definition().is_some() {
1644+
ScriptThread::enqueue_callback_reaction(&*descendant, CallbackReaction::Connected);
1645+
}
1646+
// TODO: Step 7.7.2.2.
1647+
// Try to upgrade descendant.
1648+
}
16421649
}
16431650
}
16441651
if let SuppressObserver::Unsuppressed = suppress_observers {

servo/components/script/dom/webidls/Attr.webidl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ interface Attr {
1818
readonly attribute DOMString name;
1919
[Constant]
2020
readonly attribute DOMString nodeName; // historical alias of .name
21-
[Pure]
21+
[CEReactions, Pure]
2222
attribute DOMString value;
23-
[Pure]
23+
[CEReactions, Pure]
2424
attribute DOMString textContent; // historical alias of .value
25-
[Pure]
25+
[CEReactions, Pure]
2626
attribute DOMString nodeValue; // historical alias of .value
2727

2828
[Pure]

0 commit comments

Comments
 (0)