1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
|
# DOM
[Rendered](https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/dom/README.md)
Author: hayato@chromium.org, some edits by masonf@chromium.org
The `renderer/core/dom` directory contains the implementation of [DOM].
[dom]: https://dom.spec.whatwg.org/
[dom standard]: https://dom.spec.whatwg.org/
Basically, this directory should contain only files related to the [DOM
Standard]. However, for historical reasons, the `renderer/core/dom` directory
has been used as if it were a _misc_ directory. As a result, unfortunately, this
directory contains a lot of files which are not directly related to DOM.
Please don't add unrelated files to this directory any more. We are trying to
organize the files so that developers wouldn't get confused by seeing this
directory.
- See the
[spreadsheet](https://docs.google.com/spreadsheets/d/1OydPU6r8CTj8HC4D9_gVkriJETu1Egcw2RlajYcw3FM/edit?usp=sharing),
as a rough plan to organize Source/core/dom files.
The classification in the spreadsheet might be wrong. Please update the
spreadsheet, and move files if you can, if you know more appropriate places
for each file.
- See [crbug.com/738794](http://crbug.com/738794) for tracking our efforts.
# Node and Node Tree
In this README, we draw a tree in left-to-right direction in _ascii-art_
notation. `A` is the root of the tree.
```text
A
├───B
├───C
│ ├───D
│ └───E
└───F
```
`Node` is a base class of all kinds of nodes in a node tree. Each `Node` has
following 3 pointers (but not limited to):
- `parent_or_shadow_host_node_`: Points to the parent (or the shadow host if it
is a shadow root; explained later)
- `previous_`: Points to the previous sibling
- `next_`: Points to the next sibling
`ContainerNode`, from which `Element` extends, has additional pointers for its
child:
- `first_child_`: The meaning is obvious.
- `last_child_`: Nit.
That means:
- Siblings are stored as a linked list. It takes O(N) to access a parent's n-th
child.
- A parent can't tell how many children it has in O(1).

Further info:
- `Node`, `ContainerNode`
# C++11 range-based for loops for traversing a tree
You can traverse a tree manually:
```c++
// In C++
// Traverse a node's children.
for (Node* child = parent.firstChild(); child; child = child->nextSibling()) {
...
}
// ...
// Traverse nodes in tree order, depth-first traversal.
void foo(const Node& node) {
...
for (Node* child = node.firstChild(); child; child = child->nextSibling()) {
foo(*child); // Recursively
}
}
```
Tree order is:

However, traversing a tree in this way might be error-prone. Instead, you can
use `NodeTraversal` and `ElementTraversal`. They provide C++11 range-based
for loops such as:
```c++
// In C++
for (Node& child : NodeTraversal::childrenOf(parent) {
...
}
```
e.g. Given a parent _A_, this traverses _B_, _C_, and _F_ in this order.
```c++
// In C++
for (Node& node : NodeTraversal::startsAt(root)) {
...
}
```
e.g. Given the root _A_, this traverses _A_, _B_, _C_, _D_, _E_, and _F_ in this
order.There are several other useful range-based for loops for each purpose. The
cost of using range-based for loops is zero because everything can be inlined.
Further info:
- `NodeTraversal` and `ElementTraversal` (more type-safe version)
- The [CL](https://codereview.chromium.org/642973003), which introduced these
range-based for loops.
# Shadow Tree
A **shadow tree** is a node tree whose root is a `ShadowRoot`. From web
developer's perspective, a shadow root can be created by calling
`element.attachShadow{ ... }` API. The _element_ here is called a **shadow
host**, or just a **host** if the context is clear.
- A shadow root is always attached to another node tree through its host. A
shadow tree is therefore never alone.
- The node tree of a shadow root’s host is sometimes referred to as the **light
tree**.

For example, given the example node tree:
```text
A
├───B
├───C
│ ├───D
│ └───E
└───F
```
Web developers can create a shadow root, and manipulate the shadow tree in the
following way:
```javascript
// In JavaScript
const b = document.querySelector('#B');
const shadowRoot = b.attachShadow({ mode: 'open' });
const sb = document.createElement('div');
shadowRoot.appendChild(sb);
```
The resulting shadow tree would be:
```text
shadowRoot
└── sb
```
The _shadowRoot_ has one child, _sb_. This shadow tree is _attached_ to B:
```text
A
└── B
├──/shadowRoot
│ └── sb
├── C
│ ├── D
│ └── E
└── F
```
In this README, a notation (`──/`) is used to represent a
_shadowhost-shadowroot_ relationship, in a **composed tree**. A composed tree
will be explained later. A _shadowhost-shadowroot_ is 1:1 relationship.
Though a shadow root has always a corresponding shadow host element, a light
tree and a shadow tree should be considered separately, from a node tree's
perspective. (`──/`) is _NOT_ a parent-child relationship in a node tree.
For example, even though _B_ _hosts_ the shadow tree, _shadowRoot_ is not
considered as a _child_ of _B_. That means the following traversal:
```c++
// In C++
for (Node& node : NodeTraversal::startsAt(A)) {
...
}
```
traverses only _A_, _B_, _C_, _D_, _E_ and _F_ nodes. It never visits
_shadowRoot_ nor _sb_. NodeTraversal never cross a shadow boundary, `──/`.
Further info:
- `ShadowRoot`
- `Element#attachShadow`
# TreeScope
`Document` and `ShadowRoot` are always the root of a node tree. Both `Document`
and `ShadowRoot` implement `TreeScope`.
`TreeScope` maintains a lot of information about the underlying tree for
efficiency. For example, TreeScope has an _id-to-element_ mapping, as
[`TreeOrderedMap`](./tree_ordered_map.h), so that `querySelector('#foo')` can
find an element whose id attribute is "foo" in O(1). In other words,
`root.querySelector('#foo')` can be slow if it is used in a node tree whose
root is not `TreeScope`.
Each `Node` has a `tree_scope_` pointer, which points to:
- The root node: if the node's root is either Document or ShadowRoot.
- [owner document](https://dom.spec.whatwg.org/#concept-node-documentOwnerDocument),
otherwise.
That means `tree_scope_` pointer is always non-null (except for while in a DOM
mutation), but it doesn't always point to the node's root.
Since each node doesn't have a pointer which _always_ points to the root,
`Node::getRootNode(...)` may take O(N) if the node is neither in a document tree
nor in a shadow tree. If the node is in TreeScope (`Node#IsInTreeScope()` can
tell it), we can get the root in O(1).
Each node has flags, which is updated in DOM mutation, so that we can tell
whether the node is in a document tree, in a shadow tree, or in none of them, by
using `Node::IsInDocumentTree()` and/or `Node::IsInShadowTree()`.
If you want to add new features to `Document`, `Document` might be a wrong place
to add. Instead, please consider to add functionality to `TreeScope`. We want to
treat a document tree and a shadow tree equally as much as possible.
## Example
```text
document
└── a1
├──/shadowRoot1
│ └── s1
└── a2
└── a3
document-fragment
└── b1
├──/shadowRoot2
│ └── t2
└── b2
└── b3
```
- Here, there are 4 node trees; The root node of each tree is _document_,
_shadowRoot1_, _document-fragment_, and _shadowRoot2_.
- Suppose that each node is created by `document.createElement(...)` (except for
Document and ShadowRoot). That means each node's **owner document** is
_document_.
| node | node's root | node's `_tree_scope` points to: |
| ----------------- | ------------------------ | ------------------------------- |
| document | document (self) | document (self) |
| a1 | document | document |
| a2 | document | document |
| a3 | document | document |
| shadowRoot1 | shadowRoot1 (self) | shadowRoot1 (self) |
| s1 | shadowRoot1 | shadowRoot1 |
| document-fragment | document-fragment (self) | document |
| b1 | document-fragment | document |
| b2 | document-fragment | document |
| b3 | document-fragment | document |
| shadowRoot2 | shadowRoot2 (self) | shadowRoot2 (self) |
| t1 | shadowRoot2 | shadowRoot2 |
Further Info:
- [`tree_scope.h`](./tree_scope.h), [`tree_scope.cc`](./tree_scope.cc)
- `Node#GetTreeScope()`, `Node#IsInTreeScope()`
# Composed Tree (a tree of node trees)
In the previous picture, you might think that different node trees, e.g., a
document tree and a shadow tree, were _connected_ to each other. That is _true_
in some sense. We call this _super tree_ as _composed tree_, which is a _tree of
trees_.

The following is a complex example:
```text
document
├── a1 (host)
│ ├──/shadowRoot1
│ │ └── b1
│ └── a2 (host)
│ ├──/shadowRoot2
│ │ ├── c1
│ │ │ ├── c2
│ │ │ └── c3
│ │ └── c4
│ ├── a3
│ └── a4
└── a5
└── a6 (host)
└──/shadowRoot3
└── d1
├── d2
├── d3 (host)
│ └──/shadowRoot4
│ ├── e1
│ └── e2
└── d4 (host)
└──/shadowRoot5
├── f1
└── f2
```
If you see this carefully, you can notice that this _composed tree_ is composed
of 6 node trees; 1 document tree and 5 shadow trees:
- document tree
```text
document
├── a1 (host)
│ └── a2 (host)
│ ├── a3
│ └── a4
└── a5
└── a6 (host)
```
- shadow tree 1
```text
shadowRoot1
└── b1
```
- shadow tree 2
```text
shadowRoot2
├── c1
│ ├── c2
│ └── c3
└── c4
```
- shadow tree 3
```text
shadowRoot3
└── d1
├── d2
├── d3 (host)
└── d4 (host)
```
- shadow tree 4
```text
shadowRoot4
├── e1
└── e2
```
- shadow tree 5
```text
shadowRoot5
├── f1
└── f2
```
If we consider each _node tree_ as _node_ of a _super-tree_, we can draw a
super-tree as such:
```text
document
├── shadowRoot1
├── shadowRoot2
└── shadowRoot3
├── shadowRoot4
└── shadowRoot5
```
Here, a root node is used as a representative of each node tree; A root node and
a node tree itself can be sometimes exchangeable in explanations.
We call this kind of a _super-tree_ (_a tree of node trees_) a **composed
tree**. The concept of a _composed tree_ is very useful to understand how Shadow
DOM's encapsulation works.
[DOM Standard] defines the following terminologies:
- [shadow-including tree order](https://dom.spec.whatwg.org/#concept-shadow-including-tree-order)
- [shadow-including root](https://dom.spec.whatwg.org/#concept-shadow-including-root)
- [shadow-including descendant](https://dom.spec.whatwg.org/#concept-shadow-including-descendant)
- [shadow-including inclusive descendant](https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant)
- [shadow-including ancestor](https://dom.spec.whatwg.org/#concept-shadow-including-ancestor)
- [shadow-including inclusive ancestor](https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor)
- [closed-shadow-hidden](https://dom.spec.whatwg.org/#concept-closed-shadow-hidden)
For example,
- _d1_'s _shadow-including ancestor nodes_ are _shadowRoot3_, _a6_, _a5_, and
_document_
- _d1_'s _shadow-including descendant nodes_ are _d2_, _d3_, _shadowRoot4_,
_e1_, _e2_, _d4_, _shadowRoot5_, _f1_, and _f2_.
To honor Shadow DOM's encapsulation, we have a concept of _visibility
relationship_ between two nodes.
In the following table, "`-`" means that "node _A_ is _visible_ from node _B_".
| _A_ \ _B_ | document | a1 | a2 | b1 | c1 | d1 | d2 | e1 | f1 |
| --------- | -------- | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| document | - | - | - | - | - | - | - | - | - |
| a1 | - | - | - | - | - | - | - | - | - |
| a2 | - | - | - | - | - | - | - | - | - |
| b1 | hidden | hidden | hidden | - | hidden | hidden | hidden | hidden | hidden |
| c1 | hidden | hidden | hidden | hidden | - | hidden | hidden | hidden | hidden |
| d1 | hidden | hidden | hidden | hidden | hidden | - | - | - | - |
| d2 | hidden | hidden | hidden | hidden | hidden | - | - | - | - |
| e1 | hidden | hidden | hidden | hidden | hidden | hidden | hidden | - | hidden |
| f1 | hidden | hidden | hidden | hidden | hidden | hidden | hidden | hidden | - |
For example, _document_ is _visible_ from any node.
To understand _visibility relationship_ easily, here is a rule of thumb:
- If node _B_ can reach node _A_ by traversing an _edge_ (in the first picture
of this section), recursively, _A_ is visible from _B_.
- However, an _edge_ of (`──/`) ( _shadowhost-shadowroot_ relationship) is
one-directional:
- From a shadow root to the shadow host -> Okay
- From a shadow host to the shadow root -> Forbidden
In other words, a node in an _inner tree_ can see a node in an _outer tree_ in a
composed tree, but the opposite is not true.
We have designed (or re-designed) a bunch of Web-facing APIs to honor this basic
principle. If you add a new API to the web platform and Blink, please consider
this rule and don't _leak_ a node which should be hidden to web developers.
Warning: Unfortunately, a _composed tree_ had a different meaning in the past;
it was used to specify a _flat tree_ (which will be explained later). If you
find a wrong usage of a composed tree in Blink, please fix it.
Further Info:
- `TreeScope::ParentTreeScope()`
- `Node::IsConnected()`
- DOM Standard: [connected](https://dom.spec.whatwg.org/#connected)
- DOM Standard: [retarget](https://dom.spec.whatwg.org/#retarget)
# Flat tree
A composed tree itself can't be rendered _as is_. From the rendering's
perspective, Blink has to construct a _layout tree_, which would be used as an
input to the _paint phase_. A layout tree is a tree whose node is
`LayoutObject`, which points to `Node` in a node tree, plus additional
calculated layout information.
Before the Web Platform got Shadow DOM, the structure of a layout tree is almost
_similar_ to the structure of a document tree; where only one node tree,
_document tree_, is being involved there.
Since the Web Platform got Shadow DOM, we now have a composed tree which is
composed of multiple node trees, instead of a single node tree. That means we
have to _flatten_ the composed tree to the one node tree, called a _flat tree_,
from which a layout tree is constructed.

For example, given the following composed tree,
```text
document
├── a1 (host)
│ ├──/shadowRoot1
│ │ └── b1
│ └── a2 (host)
│ ├──/shadowRoot2
│ │ ├── c1
│ │ │ ├── c2
│ │ │ └── c3
│ │ └── c4
│ ├── a3
│ └── a4
└── a5
└── a6 (host)
└──/shadowRoot3
└── d1
├── d2
├── d3 (host)
│ └──/shadowRoot4
│ ├── e1
│ └── e2
└── d4 (host)
└──/shadowRoot5
├── f1
└── f2
```
This composed tree would be flattened into the following _flat tree_ (assuming
there are not `<slot>` elements there):
```text
document
├── a1 (host)
│ └── b1
└── a5
└── a6 (host)
└── d1
├── d2
├── d3 (host)
│ ├── e1
│ └── e2
└── d4 (host)
├── f1
└── f2
```
We can't explain the exact algorithm of how to flatten a composed tree into a
flat tree until we explain the concept of _slots_ and _slot assignment_. If we
ignore the effect of `<slot>`, we can define a flat tree as:
- A root of a flat tree: _document_
- Given a node _A_ which is in a flat tree, its children are defined,
recursively, as follows:
- If _A_ is a shadow host, its shadow root's children
- Otherwise, _A_'s children
# Slots and node assignments
Please see this
[nice article](https://developers.google.com/web/fundamentals/web-components/shadowdom)
how `<slot>` elements work in general.
> _Slots_ are placeholders inside your component that users can fill with their
> own markup.
Here, I'll show some examples.
## Example 1
Given the following composed tree and slot assignments,
Composed tree:
```text
A
├──/shadowRoot1
│ ├── slot1
│ └── slot2
├── B
└── C
```
Slot Assignments:
| slot | slot's assigned nodes |
| ----- | --------------------- |
| slot1 | [C] |
| slot2 | [B] |
The flat tree would be:
```text
A
├── slot1
│ └── C
└── slot2
└── B
```
## Example 2
More complex example is here.
Composed tree:
```text
A
├──/shadowRoot1
│ ├── B
│ │ └── slot1
│ ├── slot2
│ │ └── C
│ ├── D
│ └── slot3
│ ├── E
│ └── F
├── G
├── H
├── I
└── J
```
Slot Assignments:
| slot | slot's assigned nodes |
| ----- | ------------------------ |
| slot1 | [H] |
| slot2 | [G, I] |
| slot3 | [] (nothing is assigned) |
The flat tree would be:
```text
A
├── B
│ └── slot1
│ └── H
├── slot2
│ ├── G
│ └── I
├── D
└── slot3
├── E
└── F
```
- `slot2`'s child, `C`, is not shown in this flat tree because `slot2` has
non-empty assigned nodes, `[G, I]`, which are used as `slot2`'s children in
the flat tree.
- If a slot doesn't have any assigned nodes, the slot's children are used as
_fallback contents_ in the flat tree. e.g. `slot3`s children in the flat tree
are `E` and `F`.
- If a host's child node is assigned to nowhere, the child is not used, as is
the case, e.g., for `J`.
## Example 3
A slot itself can be assigned to another slot.
For example, if we attach a shadow root to `B`, and put a `<slot>`, `slot4`,
inside of the shadow tree.
```text
A
├──/shadowRoot1
│ ├── B
│ │ ├──/shadowRoot2
│ │ │ └── K
│ │ │ └── slot4
│ │ └── slot1
│ ├── slot2
│ │ └── C
│ ├── D
│ └── slot3
│ ├── E
│ └── F
├── G
├── H
├── I
└── J
```
| slot | slot's assigned nodes |
| ----- | ------------------------ |
| slot1 | [H] |
| slot2 | [G, I] |
| slot3 | [] (nothing is assigned) |
| slot4 | [slot1] |
The flat tree would be:
```text
A
├── B
│ └── K
│ └── slot4
│ └── slot1
│ └── H
├── slot2
│ ├── G
│ └── I
├── D
└── slot3
├── E
└── F
```
# Slot Assignment Recalc
Please see
[Incremental Shadow DOM](https://docs.google.com/document/d/1R9J8CVaSub_nbaVQwwm3NjCoZye4feJ7ft7tVe5QerM/edit?usp=sharing)
to know how assignments are recalc-ed.
# FlatTreeTraversal
Blink doesn't store nor maintain a flat tree data structure in the memory.
Instead, Blink provides a utility class,
[`FlatTreeTraversal`](./flat_tree_traversal.h), which traverses a composed tree
_in a flat tree order_.
e.g. in the above example 3,
- `FlatTreeTraversal::firstChild(slot1)` returns `H`
- `FlatTreeTraversal::parent(H)` returns `slot1`
- `FlatTreeTraversal::nextSibling(G)` returns `I`
- `FlatTreeTraversal::previousSibling(I)` returns `G`
The APIs which `FlatTreeTraversal` provides are very similar to ones other
traversal utility classes provide, such as `NodeTraversal` and
`ElementTraversal`.
# Event path and Event Retargeting
<!-- Old doc: https://www.w3.org/TR/2014/WD-shadow-dom-20140617/ -->
The [DOM Standard] defines how an event should be dispatched
[here](https://dom.spec.whatwg.org/#concept-event-dispatch), including how the
[event path](https://dom.spec.whatwg.org/#event-path) should be calculated.
However, I wouldn't be surprised if the steps described there might appear
cryptic to you.
In this README, I'll explain how an event is dispatched and how its event path
is calculated briefly by using some relatively-understandable examples.
Basically, an event is dispatched across shadow trees.

Let me show more complex example composed tree, involving a slot:
```text
A
└── B
├──/shadowroot-C
│ └── D
│ ├──/shadowroot-E
│ │ └── F
│ │ └── slot-G
│ └── H
│ └── I
│ ├──/shadowroot-J
│ │ └── K
│ │ ├──/shadowroot-L
│ │ │ └── M
│ │ │ ├──/shadowroot-N
│ │ │ │ └── slot-O
│ │ │ └── slot-P
│ │ └── Q
│ │ └── slot-R
│ └── slot-S
└── T
└── U
```
Slot Assignments:
| slot | slot's assigned nodes |
| ------ | --------------------- |
| slot-G | [H] |
| slot-O | [slot-P] |
| slot-P | [Q] |
| slot-R | [slot-S] |
| slot-S | [T] |
Given that, suppose that an event is fired on `U`. Then an event path would be
(in reverse order):
```text
[U => T => slot-S => slot-R => Q => slot-P => slot-O => shadowroot-N => M
=> shadowroot-L => K => shadowroot-J => I => H => slot-G => F => shadowroot-E
=> D => shadowroot-C => B => A]
```
Roughly speaking, an event's _parent_ (the next node in event path) is
calculated as follows:
- If a node is assigned to a slot, the _parent_ is the node's asigned slot.
- If a node is a shadow root, the _parent_ is its shadow host.
- In other cases, the _parent_ is node's parent.
In the above case, `event.target`, `U`, doesn't change in its lifetime because
`U` can be _seen_ from every nodes there. However, if an event is fired on node
`Q`, for example, `event.target` would be adjusted for some nodes in event path
to honor encapsulation. That is called _event re-targeting_.
Here is an event path for an event which is fired on `Q` :
| event.currenttarget | (re-targeted) event.target |
| ------------------- | -------------------------- |
| Q | Q |
| slot-P | Q |
| slot-O | Q |
| shadowroot-N | Q |
| M | Q |
| shadowroot-L | Q |
| K | Q |
| shadowroot-J | Q |
| I | I |
| H | I |
| slot-G | I |
| F | I |
| shadowroot-E | I |
| D | I |
| shadowroot-C | I |
| B | B |
| A | B |
# Design goal of event path calculation
TODO(hayato): Explain.
# Composed events
TODO(hayato): Explain.
# Event path and related targets
TODO(hayato): Explain.
# DOM mutations
TODO(hayato): Explain.
# Related flags
TODO(hayato): Explain.
|