summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/dom
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/dom')
-rw-r--r--chromium/third_party/blink/renderer/core/dom/BUILD.gn3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/README.md341
-rw-r--r--chromium/third_party/blink/renderer/core/dom/abort_signal.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/character_data.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/character_data.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/comment.h3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/common_definitions.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.cc387
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.h59
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_init.cc89
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_init.h20
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_type.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_implementation.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_string_list.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_string_list.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.cc514
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.h33
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/custom_event.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event.h26
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_listener.h19
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_path.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_path.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_queue.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_queue.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.cc172
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.h18
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/window_event_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/window_event_context.h3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc102
-rw-r--r--chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h30
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc368
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h331
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc772
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/dom/global_event_handlers.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h39
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/named_node_map.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/named_node_map.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.cc91
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.h18
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_traversal.h10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/processing_instruction.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/dom/processing_instruction.h9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/pseudo_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.h15
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment.cc84
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment.h10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_ordered_map.h6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_scope.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_scope.h8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/visited_link_state.cc1
85 files changed, 1825 insertions, 2689 deletions
diff --git a/chromium/third_party/blink/renderer/core/dom/BUILD.gn b/chromium/third_party/blink/renderer/core/dom/BUILD.gn
index 740a785228d..fa23d84b2ef 100644
--- a/chromium/third_party/blink/renderer/core/dom/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/dom/BUILD.gn
@@ -140,8 +140,6 @@ blink_core_sources("dom") {
"first_letter_pseudo_element.h",
"flat_tree_traversal.cc",
"flat_tree_traversal.h",
- "flat_tree_traversal_ng.cc",
- "flat_tree_traversal_ng.h",
"frame_request_callback_collection.cc",
"frame_request_callback_collection.h",
"global_event_handlers.h",
@@ -153,6 +151,7 @@ blink_core_sources("dom") {
"id_target_observer_registry.h",
"idle_deadline.cc",
"idle_deadline.h",
+ "ignore_opens_during_unload_count_incrementer.h",
"increment_load_event_delay_count.cc",
"increment_load_event_delay_count.h",
"iterator.h",
diff --git a/chromium/third_party/blink/renderer/core/dom/README.md b/chromium/third_party/blink/renderer/core/dom/README.md
index 6a315e94658..a0430a7dac6 100644
--- a/chromium/third_party/blink/renderer/core/dom/README.md
+++ b/chromium/third_party/blink/renderer/core/dom/README.md
@@ -4,15 +4,15 @@
Author: hayato@chromium.org
-The `Source/core/dom` directory contains the implementation of [DOM].
+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 a file which is related to [DOM
-Standard]. However, for historical reasons, `Source/core/dom` directory has been
-used as if it were _misc_ directory. As a result, unfortunately, this directory
-contains a lot of files which are not directly related to DOM.
+Standard]. However, for historical reasons, `renderer/core/dom` directory has
+been used as if it were _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 at seeing this
@@ -30,8 +30,8 @@ directory.
# Node and Node Tree
-In this README, we draw a tree in left-to-right direction. `A` is the root of
-the 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
@@ -62,6 +62,8 @@ That means:
child.
- Parent can't tell how many children it has in O(1).
+![next sibling and previous sibling](https://hayato.io/2017/dom/next-sibling.svg)
+
Further info:
- `Node`, `ContainerNode`
@@ -89,6 +91,10 @@ void foo(const Node& node) {
}
```
+Tree order is:
+
+![tree order](https://hayato.io/2017/dom/tree-order.svg)
+
However, traversing a tree in this way might be error-prone. Instead, you can
use `NodeTraversal` and `ElementTraversal`. They provides a C++11's range-based
for loops, such as:
@@ -110,10 +116,8 @@ 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.
+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:
@@ -133,6 +137,8 @@ host**, or just a **host** if the context is clear.
- The node tree of a shadow root’s host is sometimes referred to as the **light
tree**.
+![shadow tree](https://hayato.io/2017/dom/shadow-tree.svg)
+
For example, given the example node tree:
```text
@@ -208,8 +214,8 @@ and `ShadowRoot` implements `TreeScope`.
`TreeScope` maintains a lot of information about the underlying tree for
efficiency. For example, TreeScope has a _id-to-element_ mapping, as
-[`TreeOrderedMap`](./TreeOrderedMap.h), so that `querySelector('#foo')` can find
-an element whose id attribute is "foo" in O(1). In other words,
+[`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 that is used in a node tree whose
root is not `TreeScope`.
@@ -276,14 +282,19 @@ document-fragment
Further Info:
-- [`TreeScope.h`](./TreeScope.h), [`TreeScope.cpp`](./TreeScope.cpp)
+- [`tree_scope.h`](./tree_scope.h), [`tree_scope.cc`](./tree_scope.cc)
- `Node#GetTreeScope()`, `Node#ContainingTreeScope()`, `Node#IsInTreeScope()`
# Composed Tree (a tree of node trees)
In the previous picture, you might think that more than one node trees, a
document tree and a shadow tree, were _connected_ to each other. That is _true_
-in some sense. The following is a more complex example:
+in some sense. We call this _super tree_ as _composed tree_, which is a _tree of
+trees_.
+
+![super tree](https://hayato.io/2017/dom/super-tree.svg)
+
+The following is a complex example:
```text
document
@@ -470,6 +481,8 @@ 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.
+![flat tree](https://hayato.io/2017/dom/flat-tree.svg)
+
For example, given the following composed tree,
```text
@@ -530,25 +543,311 @@ flat tree can be defined as:
- If _A_ is a shadow host, its shadow root's children
- Otherwise, _A_'s children
-# Distribution and slots
+# Slots and node assignments
-TODO(hayato): Explain.
+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
-In the meantime, please see
-[Incremental Shadow DOM](https://docs.google.com/document/d/1R9J8CVaSub_nbaVQwwm3NjCoZye4feJ7ft7tVe5QerM/edit?usp=sharing).
+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 slots 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. e.g. `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`.
+
+## Warning
+
+For historical reasons, Blink still supports Shadow DOM v0, where the different
+node distribution mechanism is still used. To support v0, you need to call
+`Node::UpdateDistributionForFlatTreeTraversal` before calling any function of
+`FlatTreeTraversal`.
+
+If you use `FlatTreeTraversal` without updating distribution, you would hit
+DCHECK. :(
+
+Since `Node::UpdateDistributionForFlatTreeTraversal` can take O(N) in the worst
+case (_even if the distribution flag is clean!_), you should be careful not to
+call it in hot code paths. If you are not sure, please contact
+dom-dev@chromium.org, or add hayato@chromium.org to reviewers.
+
+Once Blink removes Shadow DOM v0 in the future, you don't need to call
+`Node::UpdateDistributionForFlatTreeTraversal` before using `FlatTreeTraversal`
+beforehand in most cases, however, that wouldn't happen soon.
+
+# Event path and Event Retargeting
+
+<!-- Old doc: https://www.w3.org/TR/2014/WD-shadow-dom-20140617/ -->
+
+[DOM Standard] defines how an event should be dispatched
+[here](https://dom.spec.whatwg.org/#concept-event-dispatch), including how
+[event path](https://dom.spec.whatwg.org/#event-path) should be calculated,
+however, I wouldn't be surprised if the steps described there might look a kind
+of cryptogram 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.
+
+![event dispatch](https://hayato.io/2017/dom/event-dispatch.svg)
+
+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 | [O] |
+| slot-R | [slot-S] |
+| slot-S | [T] |
+
+Given that, suppose that an event is fired on `U`, 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 honer 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.
-# DOM mutations
+# Composed events
TODO(hayato): Explain.
-# Related flags
+# Event path and related targets
TODO(hayato): Explain.
-# Event path and Event Retargeting
+# DOM mutations
+
+TODO(hayato): Explain.
+
+# Related flags
TODO(hayato): Explain.
diff --git a/chromium/third_party/blink/renderer/core/dom/abort_signal.cc b/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
index e0283241bd6..b088e008562 100644
--- a/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
@@ -42,7 +43,7 @@ void AbortSignal::SignalAbort() {
std::move(closure).Run();
}
abort_algorithms_.clear();
- DispatchEvent(Event::Create(EventTypeNames::abort));
+ DispatchEvent(*Event::Create(EventTypeNames::abort));
}
void AbortSignal::Follow(AbortSignal* parentSignal) {
diff --git a/chromium/third_party/blink/renderer/core/dom/character_data.cc b/chromium/third_party/blink/renderer/core/dom/character_data.cc
index 4fe5a46d7a7..8530b0e823e 100644
--- a/chromium/third_party/blink/renderer/core/dom/character_data.cc
+++ b/chromium/third_party/blink/renderer/core/dom/character_data.cc
@@ -41,11 +41,9 @@ void CharacterData::Atomize() {
}
void CharacterData::setData(const String& data) {
- const String& non_null_data = !data.IsNull() ? data : g_empty_string;
unsigned old_length = length();
- SetDataAndUpdate(non_null_data, 0, old_length, non_null_data.length(),
- kUpdateFromNonParser);
+ SetDataAndUpdate(data, 0, old_length, data.length(), kUpdateFromNonParser);
GetDocument().DidRemoveText(*this, 0, old_length);
}
@@ -171,7 +169,7 @@ bool CharacterData::ContainsOnlyWhitespace() const {
}
void CharacterData::setNodeValue(const String& node_value) {
- setData(node_value);
+ setData(!node_value.IsNull() ? node_value : g_empty_string);
}
void CharacterData::SetDataAndUpdate(const String& new_data,
@@ -217,7 +215,7 @@ void CharacterData::DidModifyData(const String& old_data, UpdateSource source) {
if (source != kUpdateFromParser && !IsInShadowTree()) {
if (GetDocument().HasListenerType(
Document::kDOMCharacterDataModifiedListener)) {
- DispatchScopedEvent(MutationEvent::Create(
+ DispatchScopedEvent(*MutationEvent::Create(
EventTypeNames::DOMCharacterDataModified, Event::Bubbles::kYes,
nullptr, old_data, data_));
}
diff --git a/chromium/third_party/blink/renderer/core/dom/character_data.idl b/chromium/third_party/blink/renderer/core/dom/character_data.idl
index 1d216114e5f..30b22212172 100644
--- a/chromium/third_party/blink/renderer/core/dom/character_data.idl
+++ b/chromium/third_party/blink/renderer/core/dom/character_data.idl
@@ -20,7 +20,7 @@
// https://dom.spec.whatwg.org/#interface-characterdata
interface CharacterData : Node {
- attribute [TreatNullAs=NullString] DOMString data;
+ attribute [TreatNullAs=EmptyString] DOMString data;
readonly attribute unsigned long length;
[RaisesException] DOMString substringData(unsigned long offset, unsigned long count);
void appendData(DOMString data);
diff --git a/chromium/third_party/blink/renderer/core/dom/comment.h b/chromium/third_party/blink/renderer/core/dom/comment.h
index f4f81ad3519..5b1579ba869 100644
--- a/chromium/third_party/blink/renderer/core/dom/comment.h
+++ b/chromium/third_party/blink/renderer/core/dom/comment.h
@@ -27,7 +27,7 @@
namespace blink {
-class Comment final : public CharacterData {
+class CORE_EXPORT Comment final : public CharacterData {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -39,6 +39,7 @@ class Comment final : public CharacterData {
String nodeName() const override;
NodeType getNodeType() const override;
Node* Clone(Document&, CloneChildrenFlag) const override;
+ void DetachLayoutTree(const AttachContext&) final {}
};
DEFINE_NODE_TYPE_CASTS(Comment, getNodeType() == Node::kCommentNode);
diff --git a/chromium/third_party/blink/renderer/core/dom/common_definitions.idl b/chromium/third_party/blink/renderer/core/dom/common_definitions.idl
index d9e3f29334c..60c8b6ec8d1 100644
--- a/chromium/third_party/blink/renderer/core/dom/common_definitions.idl
+++ b/chromium/third_party/blink/renderer/core/dom/common_definitions.idl
@@ -7,6 +7,12 @@
typedef (ArrayBuffer or ArrayBufferView) BufferSource;
typedef unsigned long long DOMTimeStamp;
+
+// https://heycam.github.io/webidl/#Function
+
+callback Function = any (any... arguments);
+
+
// typedefs used in multiple files.
typedef object JSON;
diff --git a/chromium/third_party/blink/renderer/core/dom/container_node.cc b/chromium/third_party/blink/renderer/core/dom/container_node.cc
index 31c96bdc0fb..659d355a779 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.cc
@@ -354,7 +354,7 @@ void ContainerNode::DidInsertNodeVector(
}
DispatchSubtreeModifiedEvent();
- if (AXObjectCache* cache = GetDocument().GetOrCreateAXObjectCache())
+ if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
cache->DidInsertChildrenOfNode(this);
}
@@ -700,14 +700,15 @@ Node* ContainerNode::RemoveChild(Node* old_child,
}
{
- SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(GetDocument());
HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
TreeOrderedMap::RemoveScope tree_remove_scope;
-
Node* prev = child->previousSibling();
Node* next = child->nextSibling();
- RemoveBetween(prev, next, *child);
- NotifyNodeRemoved(*child);
+ {
+ SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(GetDocument());
+ RemoveBetween(prev, next, *child);
+ NotifyNodeRemoved(*child);
+ }
ChildrenChanged(ChildrenChange::ForRemoval(*child, prev, next,
kChildrenChangeSourceAPI));
}
@@ -926,7 +927,7 @@ void ContainerNode::NotifyNodeInsertedInternal(
if (!isConnected() && !IsInShadowTree() && !node.IsContainerNode())
continue;
if (Node::kInsertionShouldCallDidNotifySubtreeInsertions ==
- node.InsertedInto(this))
+ node.InsertedInto(*this))
post_insertion_notification_targets.push_back(&node);
if (ShadowRoot* shadow_root = node.GetShadowRoot())
NotifyNodeInsertedInternal(*shadow_root,
@@ -944,17 +945,40 @@ void ContainerNode::NotifyNodeRemoved(Node& root) {
// since the virtual call to removedFrom is not needed.
if (!node.IsContainerNode() && !node.IsInTreeScope())
continue;
- node.RemovedFrom(this);
+ node.RemovedFrom(*this);
if (ShadowRoot* shadow_root = node.GetShadowRoot())
NotifyNodeRemoved(*shadow_root);
}
}
+#if DCHECK_IS_ON()
+namespace {
+
+bool AttachedAllowedWhenAttaching(Node* node) {
+ return node->getNodeType() == Node::kCommentNode ||
+ node->getNodeType() == Node::kProcessingInstructionNode;
+}
+
+bool ChildAttachedAllowedWhenAttachingChildren(ContainerNode* node) {
+ if (node->IsShadowRoot())
+ return true;
+ if (node->IsV0InsertionPoint())
+ return true;
+ if (IsHTMLSlotElement(node))
+ return true;
+ if (IsShadowHost(node))
+ return true;
+ return false;
+}
+
+} // namespace
+#endif
+
DISABLE_CFI_PERF
void ContainerNode::AttachLayoutTree(AttachContext& context) {
for (Node* child = firstChild(); child; child = child->nextSibling()) {
#if DCHECK_IS_ON()
- DCHECK(child->NeedsAttach() ||
+ DCHECK(child->NeedsAttach() || AttachedAllowedWhenAttaching(child) ||
ChildAttachedAllowedWhenAttachingChildren(this));
#endif
if (child->NeedsAttach())
@@ -981,11 +1005,10 @@ void ContainerNode::ChildrenChanged(const ChildrenChange& change) {
GetDocument().IncDOMTreeVersion();
GetDocument().NotifyChangeChildren(*this);
InvalidateNodeListCachesInAncestors(nullptr, nullptr, &change);
- if (change.IsChildInsertion()) {
- if (!ChildNeedsStyleRecalc()) {
- SetChildNeedsStyleRecalc();
- MarkAncestorsWithChildNeedsStyleRecalc();
- }
+ if (!ChildNeedsStyleRecalc() && change.IsChildInsertion() &&
+ change.sibling_changed->NeedsStyleRecalc()) {
+ SetChildNeedsStyleRecalc();
+ MarkAncestorsWithChildNeedsStyleRecalc();
}
}
@@ -1277,15 +1300,15 @@ static void DispatchChildInsertionEvents(Node& child) {
if (c->parentNode() &&
document->HasListenerType(Document::kDOMNodeInsertedListener)) {
c->DispatchScopedEvent(
- MutationEvent::Create(EventTypeNames::DOMNodeInserted,
- Event::Bubbles::kYes, c->parentNode()));
+ *MutationEvent::Create(EventTypeNames::DOMNodeInserted,
+ Event::Bubbles::kYes, c->parentNode()));
}
// dispatch the DOMNodeInsertedIntoDocument event to all descendants
if (c->isConnected() && document->HasListenerType(
Document::kDOMNodeInsertedIntoDocumentListener)) {
for (; c; c = NodeTraversal::Next(*c, &child)) {
- c->DispatchScopedEvent(MutationEvent::Create(
+ c->DispatchScopedEvent(*MutationEvent::Create(
EventTypeNames::DOMNodeInsertedIntoDocument, Event::Bubbles::kNo));
}
}
@@ -1319,7 +1342,7 @@ static void DispatchChildRemovalEvents(Node& child) {
Document::InDOMNodeRemovedHandlerState::kDOMNodeRemoved);
}
NodeChildRemovalTracker scope(child);
- c->DispatchScopedEvent(MutationEvent::Create(
+ c->DispatchScopedEvent(*MutationEvent::Create(
EventTypeNames::DOMNodeRemoved, Event::Bubbles::kYes, c->parentNode()));
document.SetInDOMNodeRemovedHandlerState(original_document_state);
c->SetInDOMNodeRemovedHandler(original_node_flag);
@@ -1340,7 +1363,7 @@ static void DispatchChildRemovalEvents(Node& child) {
}
NodeChildRemovalTracker scope(child);
for (; c; c = NodeTraversal::Next(*c, &child)) {
- c->DispatchScopedEvent(MutationEvent::Create(
+ c->DispatchScopedEvent(*MutationEvent::Create(
EventTypeNames::DOMNodeRemovedFromDocument, Event::Bubbles::kNo));
}
document.SetInDOMNodeRemovedHandlerState(original_document_state);
@@ -1444,7 +1467,6 @@ void ContainerNode::RebuildChildrenLayoutTrees(
// This is done in ContainerNode::AttachLayoutTree but will never be cleared
// if we don't enter ContainerNode::AttachLayoutTree so we do it here.
ClearChildNeedsStyleRecalc();
- ClearChildNeedsReattachLayoutTree();
}
void ContainerNode::CheckForSiblingStyleChanges(SiblingCheckType change_type,
@@ -1621,22 +1643,4 @@ NodeListsNodeData& ContainerNode::EnsureNodeLists() {
return EnsureRareData().EnsureNodeLists();
}
-#if DCHECK_IS_ON()
-bool ChildAttachedAllowedWhenAttachingChildren(ContainerNode* node) {
- if (node->IsShadowRoot())
- return true;
-
- if (node->IsV0InsertionPoint())
- return true;
-
- if (IsHTMLSlotElement(node))
- return true;
-
- if (IsShadowHost(node))
- return true;
-
- return false;
-}
-#endif
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/container_node.h b/chromium/third_party/blink/renderer/core/dom/container_node.h
index dea345ca2d3..578665e17db 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.h
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.h
@@ -456,10 +456,6 @@ class CORE_EXPORT ContainerNode : public Node {
TraceWrapperMember<Node> last_child_;
};
-#if DCHECK_IS_ON()
-bool ChildAttachedAllowedWhenAttachingChildren(ContainerNode*);
-#endif
-
WILL_NOT_BE_EAGERLY_TRACED_CLASS(ContainerNode);
DEFINE_NODE_TYPE_CASTS(ContainerNode, IsContainerNode());
diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc
index 5bfe30b8b88..e628c1ab824 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document.cc
@@ -32,6 +32,7 @@
#include <memory>
#include "base/auto_reset.h"
+#include "base/optional.h"
#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
@@ -49,12 +50,15 @@
#include "third_party/blink/public/platform/web_prerendering_support.h"
#include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
#include "third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element_creation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
+#include "third_party/blink/renderer/core/accessibility/ax_context.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
@@ -64,6 +68,7 @@
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
+#include "third_party/blink/renderer/core/css/css_style_sheet_init.h"
#include "third_party/blink/renderer/core/css/cssom/computed_style_property_map.h"
#include "third_party/blink/renderer/core/css/font_face_set_document.h"
#include "third_party/blink/renderer/core/css/invalidation/style_invalidator.h"
@@ -148,6 +153,7 @@
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/html/anchor_element_metrics.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_font_cache.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
@@ -179,6 +185,7 @@
#include "third_party/blink/renderer/core/html/html_unknown_element.h"
#include "third_party/blink/renderer/core/html/imports/html_import_loader.h"
#include "third_party/blink/renderer/core/html/imports/html_imports_controller.h"
+#include "third_party/blink/renderer/core/html/lazy_load_image_observer.h"
#include "third_party/blink/renderer/core/html/parser/html_document_parser.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h"
@@ -231,6 +238,7 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h"
#include "third_party/blink/renderer/core/script/script_runner.h"
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/core/svg/svg_script_element.h"
#include "third_party/blink/renderer/core/svg/svg_title_element.h"
@@ -268,7 +276,6 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
@@ -558,7 +565,7 @@ class Document::NetworkStateObserver final
Document* document = ToDocument(GetExecutionContext());
if (!document->domWindow())
return;
- document->domWindow()->DispatchEvent(Event::Create(event_name));
+ document->domWindow()->DispatchEvent(*Event::Create(event_name));
probe::networkStateChanged(document->GetFrame(), on_line);
}
@@ -630,6 +637,7 @@ Document::Document(const DocumentInit& initializer,
contains_plugins_(false),
ignore_destructive_write_count_(0),
throw_on_dynamic_markup_insertion_count_(0),
+ ignore_opens_during_unload_count_(0),
markers_(new DocumentMarkerController(*this)),
update_focus_appearance_timer_(
GetTaskRunner(TaskType::kInternalUserInteraction),
@@ -692,7 +700,8 @@ Document::Document(const DocumentInit& initializer,
slot_assignment_recalc_forbidden_recursion_depth_(0),
#endif
needs_to_record_ukm_outlive_time_(false),
- viewport_data_(new ViewportData(*this)) {
+ viewport_data_(new ViewportData(*this)),
+ agent_cluster_id_(base::UnguessableToken::Create()) {
if (frame_) {
DCHECK(frame_->GetPage());
ProvideContextFeaturesToDocumentFrom(*this, *frame_->GetPage());
@@ -1139,6 +1148,20 @@ ScriptPromise Document::createCSSStyleSheet(ScriptState* script_state,
ScriptValue::From(script_state, sheet));
}
+CSSStyleSheet* Document::createEmptyCSSStyleSheet(
+ ScriptState* script_state,
+ const CSSStyleSheetInit& options,
+ ExceptionState& exception_state) {
+ return CSSStyleSheet::Create(*this, options, exception_state);
+}
+
+CSSStyleSheet* Document::createEmptyCSSStyleSheet(
+ ScriptState* script_state,
+ ExceptionState& exception_state) {
+ return Document::createEmptyCSSStyleSheet(script_state, CSSStyleSheetInit(),
+ exception_state);
+}
+
ScriptValue Document::registerElement(ScriptState* script_state,
const AtomicString& name,
const ElementRegistrationOptions& options,
@@ -1433,7 +1456,7 @@ void Document::SetReadyState(DocumentReadyState ready_state) {
}
ready_state_ = ready_state;
- DispatchEvent(Event::Create(EventTypeNames::readystatechange));
+ DispatchEvent(*Event::Create(EventTypeNames::readystatechange));
}
bool Document::IsLoadCompleted() const {
@@ -1475,6 +1498,15 @@ void Document::setXMLStandalone(bool standalone,
}
void Document::SetContent(const String& content) {
+ // Only set the content of the document if it is ready to be set. This method
+ // could be called at any time.
+ if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) {
+ if (parser->IsParsing() && parser->IsExecutingScript())
+ return;
+ }
+ if (ignore_opens_during_unload_count_)
+ return;
+
open();
parser_->Append(content);
close();
@@ -1623,7 +1655,7 @@ void Document::UpdateTitle(const String& title) {
return;
DispatchDidReceiveTitle();
- if (AXObjectCache* cache = GetOrCreateAXObjectCache())
+ if (AXObjectCache* cache = ExistingAXObjectCache())
cache->DocumentTitleChanged();
}
@@ -1760,9 +1792,9 @@ void Document::SetWasDiscarded(bool was_discarded) {
}
void Document::DidChangeVisibilityState() {
- DispatchEvent(Event::CreateBubble(EventTypeNames::visibilitychange));
+ DispatchEvent(*Event::CreateBubble(EventTypeNames::visibilitychange));
// Also send out the deprecated version until it can be removed.
- DispatchEvent(Event::CreateBubble(EventTypeNames::webkitvisibilitychange));
+ DispatchEvent(*Event::CreateBubble(EventTypeNames::webkitvisibilitychange));
if (GetPageVisibilityState() == mojom::PageVisibilityState::kVisible)
Timeline().SetAllCompositorPending();
@@ -1922,6 +1954,7 @@ void Document::UpdateStyleInvalidationIfNeeded() {
if (!ChildNeedsStyleInvalidation() && !NeedsStyleInvalidation())
return;
TRACE_EVENT0("blink", "Document::updateStyleInvalidationIfNeeded");
+ SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.InvalidationTime");
GetStyleEngine().InvalidateStyle();
}
@@ -2023,8 +2056,7 @@ void Document::PropagateStyleToViewport() {
EOverscrollBehavior overscroll_behavior_y =
overflow_style->OverscrollBehaviorY();
using OverscrollBehaviorType = cc::OverscrollBehavior::OverscrollBehaviorType;
- if (RuntimeEnabledFeatures::CSSOverscrollBehaviorEnabled() &&
- IsInMainFrame()) {
+ if (IsInMainFrame()) {
GetPage()->GetOverscrollController().SetOverscrollBehavior(
cc::OverscrollBehavior(
static_cast<OverscrollBehaviorType>(overscroll_behavior_x),
@@ -2092,13 +2124,6 @@ void Document::PropagateStyleToViewport() {
#if DCHECK_IS_ON()
static void AssertLayoutTreeUpdated(Node& root) {
for (Node& node : NodeTraversal::InclusiveDescendantsOf(root)) {
- // We leave some nodes with dirty bits in the tree because they don't
- // matter like Comment and ProcessingInstruction nodes.
- // TODO(esprehn): Don't even mark those nodes as needing recalcs in the
- // first place.
- if (!node.IsElementNode() && !node.IsTextNode() && !node.IsShadowRoot() &&
- !node.IsDocumentNode())
- continue;
DCHECK(!node.NeedsStyleRecalc());
DCHECK(!node.ChildNeedsStyleRecalc());
DCHECK(!node.NeedsReattachLayoutTree());
@@ -2237,7 +2262,6 @@ void Document::UpdateStyle() {
TRACE_EVENT_BEGIN0("blink,blink_style", "Document::updateStyle");
RUNTIME_CALL_TIMER_SCOPE(V8PerIsolateData::MainThreadIsolate(),
RuntimeCallStats::CounterId::kUpdateStyle);
- TimeTicks start_time = CurrentTimeTicks();
unsigned initial_element_count = GetStyleEngine().StyleForElementCount();
@@ -2278,11 +2302,9 @@ void Document::UpdateStyle() {
if (Element* document_element = documentElement()) {
if (document_element->ShouldCallRecalcStyle(change)) {
TRACE_EVENT0("blink,blink_style", "Document::recalcStyle");
+ SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RecalcTime");
Element* viewport_defining = ViewportDefiningElement();
- ReattachLegacyLayoutObjectList legacy_layout_objects(*this);
- legacy_layout_objects.WillRecalcStyle();
document_element->RecalcStyle(change);
- legacy_layout_objects.DidRecalcStyle();
if (viewport_defining != ViewportDefiningElement())
ViewportDefiningElementDidChange();
}
@@ -2291,6 +2313,7 @@ void Document::UpdateStyle() {
if (document_element->NeedsReattachLayoutTree() ||
document_element->ChildNeedsReattachLayoutTree()) {
TRACE_EVENT0("blink,blink_style", "Document::rebuildLayoutTree");
+ SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RebuildLayoutTreeTime");
ReattachLegacyLayoutObjectList legacy_layout_objects(*this);
WhitespaceAttacher whitespace_attacher;
document_element->RebuildLayoutTree(whitespace_attacher);
@@ -2322,10 +2345,6 @@ void Document::UpdateStyle() {
"blink,blink_style", "Document::updateStyle", "resolverAccessCount",
GetStyleEngine().StyleForElementCount() - initial_element_count);
}
-
- DEFINE_STATIC_LOCAL(CustomCountHistogram, update_histogram,
- ("Style.UpdateTime", 0, 10000000, 50));
- update_histogram.CountMicroseconds(CurrentTimeTicks() - start_time);
}
void Document::ViewportDefiningElementDidChange() {
@@ -2455,7 +2474,7 @@ void Document::LayoutUpdated() {
// Plugins can run script inside layout which can detach the page.
// TODO(dcheng): Does it make sense to do any of this work if detached?
if (GetFrame() && GetFrame()->IsMainFrame())
- GetFrame()->GetPage()->GetChromeClient().LayoutUpdated();
+ GetFrame()->GetPage()->GetChromeClient().MainFrameLayoutUpdated();
Markers().InvalidateRectsForAllTextMatchMarkers();
@@ -2796,8 +2815,10 @@ void Document::Shutdown() {
}
sequential_focus_navigation_starting_point_ = nullptr;
- if (this == &AXObjectCacheOwner())
+ if (this == &AXObjectCacheOwner()) {
+ ax_contexts_.clear();
ClearAXObjectCache();
+ }
layout_view_ = nullptr;
ContainerNode::DetachLayoutTree();
@@ -2896,13 +2917,54 @@ Document& Document::AXObjectCacheOwner() const {
return *doc;
}
+void Document::AddAXContext(AXContext* context) {
+ // The only case when |&cache_owner| is not |this| is when this is a
+ // pop-up. We want pop-ups to share the AXObjectCache of their parent
+ // document. However, there's no valid reason to explicitly create an
+ // AXContext for a pop-up document, so check to make sure we're not
+ // trying to do that here.
+ DCHECK_EQ(&AXObjectCacheOwner(), this);
+
+ // If the document has already been detached, do not make a new AXObjectCache.
+ if (!GetLayoutView())
+ return;
+
+ ax_contexts_.push_back(context);
+ if (ax_contexts_.size() != 1)
+ return;
+
+ if (!ax_object_cache_)
+ ax_object_cache_ = AXObjectCache::Create(*this);
+}
+
+void Document::RemoveAXContext(AXContext* context) {
+ auto** iter =
+ std::find_if(ax_contexts_.begin(), ax_contexts_.end(),
+ [&context](const auto& item) { return item == context; });
+ if (iter != ax_contexts_.end())
+ ax_contexts_.erase(iter);
+ if (ax_contexts_.size() == 0)
+ ClearAXObjectCache();
+}
+
void Document::ClearAXObjectCache() {
DCHECK_EQ(&AXObjectCacheOwner(), this);
+
// Clear the cache member variable before calling delete because attempts
// are made to access it during destruction.
if (ax_object_cache_)
ax_object_cache_->Dispose();
ax_object_cache_.Clear();
+
+ // If there's at least one AXContext in scope and there's still a LayoutView
+ // around, recreate an empty AXObjectCache.
+ //
+ // TODO(dmazzoni): right now ClearAXObjectCache() is being used as a way
+ // to invalidate / reset the AXObjectCache while keeping it around. We
+ // should rewrite that as a method on AXObjectCache rather than destroying
+ // and recreating it here.
+ if (ax_contexts_.size() > 0 && GetLayoutView())
+ ax_object_cache_ = AXObjectCache::Create(*this);
}
AXObjectCache* Document::ExistingAXObjectCache() const {
@@ -2916,28 +2978,6 @@ AXObjectCache* Document::ExistingAXObjectCache() const {
return cache_owner.ax_object_cache_.Get();
}
-AXObjectCache* Document::GetOrCreateAXObjectCache() const {
- Settings* settings = GetSettings();
- if (!settings || !settings->GetAccessibilityEnabled())
- return nullptr;
-
- // Every document has its own AXObjectCache if accessibility is enabled,
- // except for page popups (such as select popups or context menus),
- // which share the AXObjectCache of their owner.
- //
- // See http://crbug.com/532249
- Document& cache_owner = AXObjectCacheOwner();
-
- // If the document has already been detached, do not make a new axObjectCache.
- if (!cache_owner.GetLayoutView())
- return nullptr;
-
- DCHECK(&cache_owner == this || !ax_object_cache_);
- if (!cache_owner.ax_object_cache_)
- cache_owner.ax_object_cache_ = AXObjectCache::Create(cache_owner);
- return cache_owner.ax_object_cache_.Get();
-}
-
CanvasFontCache* Document::GetCanvasFontCache() {
if (!canvas_font_cache_)
canvas_font_cache_ = CanvasFontCache::Create(*this);
@@ -2985,6 +3025,7 @@ void Document::SetPrinting(PrintingState state) {
}
}
+// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps
void Document::open(Document* entered_document,
ExceptionState& exception_state) {
if (ImportLoader()) {
@@ -2994,12 +3035,16 @@ void Document::open(Document* entered_document,
return;
}
+ // If |document| is an XML document, then throw an "InvalidStateError"
+ // DOMException exception.
if (!IsHTMLDocument()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Only HTML documents support open().");
return;
}
+ // If |document|'s throw-on-dynamic-markup-insertion counter is greater than
+ // 0, then throw an "InvalidStateError" DOMException.
if (throw_on_dynamic_markup_insertion_count_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -3010,58 +3055,83 @@ void Document::open(Document* entered_document,
if (!AllowedToUseDynamicMarkUpInsertion("open", exception_state))
return;
- if (entered_document) {
- if (!GetSecurityOrigin()->IsSameSchemeHostPort(
- entered_document->GetSecurityOrigin())) {
- exception_state.ThrowSecurityError(
- "Can only call open() on same-origin documents.");
+ // If |document|'s origin is not same origin to the origin of the responsible
+ // document specified by the entry settings object, then throw a
+ // "SecurityError" DOMException.
+ if (entered_document && !GetSecurityOrigin()->IsSameSchemeHostPort(
+ entered_document->GetSecurityOrigin())) {
+ exception_state.ThrowSecurityError(
+ "Can only call open() on same-origin documents.");
+ return;
+ }
+
+ // If |document| has an active parser whose script nesting level is greater
+ // than 0, then return |document|.
+ if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) {
+ if (parser->IsParsing() && parser->IsExecutingScript())
return;
- }
- SetSecurityOrigin(entered_document->GetMutableSecurityOrigin());
+ }
- if (this != entered_document) {
- // Clear the hash fragment from the inherited URL to prevent a
- // scroll-into-view for any document.open()'d frame.
- KURL new_url = entered_document->Url();
- new_url.SetFragmentIdentifier(String());
- SetURL(new_url);
- SetReferrerPolicy(entered_document->GetReferrerPolicy());
- }
+ // Similarly, if |document|'s ignore-opens-during-unload counter is greater
+ // than 0, then return |document|.
+ if (ignore_opens_during_unload_count_)
+ return;
+
+ // Change |document|'s URL to the URL of the responsible document specified
+ // by the entry settings object.
+ if (entered_document && this != entered_document) {
+ // Clear the hash fragment from the inherited URL to prevent a
+ // scroll-into-view for any document.open()'d frame.
+ KURL new_url = entered_document->Url();
+ new_url.SetFragmentIdentifier(String());
+ SetURL(new_url);
- cookie_url_ = entered_document->CookieURL();
+ SetSecurityOrigin(entered_document->GetMutableSecurityOrigin());
+ SetReferrerPolicy(entered_document->GetReferrerPolicy());
+ SetCookieURL(entered_document->CookieURL());
}
open();
}
+// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps
void Document::open() {
DCHECK(!ImportLoader());
+ DCHECK(!ignore_opens_during_unload_count_);
+ if (ScriptableDocumentParser* parser = GetScriptableDocumentParser())
+ DCHECK(!parser->IsParsing() || !parser->IsExecutingScript());
- if (frame_) {
- if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) {
- if (parser->IsParsing()) {
- // FIXME: HTML5 doesn't tell us to check this, it might not be correct.
- if (parser->IsExecutingScript())
- return;
-
- if (!parser->WasCreatedByScript() && parser->HasInsertionPoint())
- return;
- }
- }
-
- if (frame_->Loader().HasProvisionalNavigation()) {
- frame_->Loader().StopAllLoaders();
- // Navigations handled by the client should also be cancelled.
- if (frame_->Client())
- frame_->Client()->AbortClientNavigation();
- }
+ // Abort |document|.
+ //
+ // TODO(timothygu): We are only aborting the document if there is a
+ // provisional navigation, unlike the spec.
+ if (frame_ && frame_->Loader().HasProvisionalNavigation()) {
+ frame_->Loader().StopAllLoaders();
+ // Navigations handled by the client should also be cancelled.
+ if (frame_ && frame_->Client())
+ frame_->Client()->AbortClientNavigation();
}
+ // For each shadow-including inclusive descendant |node| of |document|, erase
+ // all event listeners and handlers given |node|.
+ //
+ // Erase all event listeners and handlers given |window|.
+ //
+ // NB: Document::RemoveAllEventListeners() (called by
+ // RemoveAllEventListenersRecursively()) erases event listeners from the
+ // Window object as well.
RemoveAllEventListenersRecursively();
+
ResetTreeScope();
if (frame_)
frame_->Selection().Clear();
+
+ // Create a new HTML parser and associate it with |document|.
+ //
+ // Set the current document readiness of |document| to "loading".
ImplicitOpen(kForceSynchronousParsing);
+
+ // This is a script-created parser.
if (ScriptableDocumentParser* parser = GetScriptableDocumentParser())
parser->SetWasCreatedByScript(true);
@@ -3257,10 +3327,8 @@ DOMWindow* Document::open(LocalDOMWindow* current_window,
entered_window, exception_state);
}
+// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#dom-document-close
void Document::close(ExceptionState& exception_state) {
- // FIXME: We should follow the specification more closely:
- // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close
-
if (ImportLoader()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -3268,12 +3336,16 @@ void Document::close(ExceptionState& exception_state) {
return;
}
+ // If the Document object is an XML document, then throw an
+ // "InvalidStateError" DOMException.
if (!IsHTMLDocument()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Only HTML documents support close().");
return;
}
+ // If the Document object's throw-on-dynamic-markup-insertion counter is
+ // greater than zero, then throw an "InvalidStateError" DOMException.
if (throw_on_dynamic_markup_insertion_count_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
@@ -3287,13 +3359,20 @@ void Document::close(ExceptionState& exception_state) {
close();
}
+// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#dom-document-close
void Document::close() {
+ // If there is no script-created parser associated with the document, then
+ // return.
if (!GetScriptableDocumentParser() ||
!GetScriptableDocumentParser()->WasCreatedByScript() ||
!GetScriptableDocumentParser()->IsParsing())
return;
+ // Insert an explicit "EOF" character at the end of the parser's input
+ // stream.
parser_->Finish();
+
+ // TODO(timothygu): We should follow the specification more closely.
if (!parser_ || !parser_->IsParsing())
SetReadyState(kComplete);
CheckCompleted();
@@ -3358,10 +3437,13 @@ void Document::ImplicitClose() {
View()->UpdateLayout();
}
+ if (View())
+ View()->ScrollAndFocusFragmentAnchor();
+
load_event_progress_ = kLoadEventCompleted;
if (GetFrame() && GetLayoutView()) {
- if (AXObjectCache* cache = GetOrCreateAXObjectCache()) {
+ if (AXObjectCache* cache = ExistingAXObjectCache()) {
if (this == &AXObjectCacheOwner())
cache->HandleLoadComplete(this);
else
@@ -3454,6 +3536,8 @@ bool Document::CheckCompletedInternal() {
DCHECK(ukm_binding.is_bound());
ukm_binding->SetDocumentSourceId(ukm_source_id_);
}
+
+ AnchorElementMetrics::MaybeReportViewportMetricsOnLoad(*this);
}
return true;
@@ -3471,8 +3555,8 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient& chrome_client,
if (ProcessingBeforeUnload())
return false;
- BeforeUnloadEvent* before_unload_event = BeforeUnloadEvent::Create();
- before_unload_event->initEvent(EventTypeNames::beforeunload, false, true);
+ BeforeUnloadEvent& before_unload_event = *BeforeUnloadEvent::Create();
+ before_unload_event.initEvent(EventTypeNames::beforeunload, false, true);
load_event_progress_ = kBeforeUnloadEventInProgress;
const TimeTicks beforeunload_event_start = CurrentTimeTicks();
dom_window_->DispatchEvent(before_unload_event, this);
@@ -3483,7 +3567,7 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient& chrome_client,
("DocumentEventTiming.BeforeUnloadDuration", 0, 10000000, 50));
beforeunload_histogram.CountMicroseconds(beforeunload_event_end -
beforeunload_event_start);
- if (!before_unload_event->defaultPrevented())
+ if (!before_unload_event.defaultPrevented())
DefaultEventHandler(before_unload_event);
enum BeforeUnloadDialogHistogramEnum {
@@ -3495,10 +3579,10 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient& chrome_client,
};
DEFINE_STATIC_LOCAL(EnumerationHistogram, beforeunload_dialog_histogram,
("Document.BeforeUnloadDialog", kDialogEnumMax));
- if (before_unload_event->returnValue().IsNull()) {
+ if (before_unload_event.returnValue().IsNull()) {
beforeunload_dialog_histogram.Count(kNoDialogNoText);
}
- if (!GetFrame() || before_unload_event->returnValue().IsNull())
+ if (!GetFrame() || before_unload_event.returnValue().IsNull())
return true;
if (!GetFrame()->HasBeenActivated()) {
@@ -3520,11 +3604,19 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient& chrome_client,
Intervention::GenerateReport(frame_, "BeforeUnloadMultiple", message);
return true;
}
- String text = before_unload_event->returnValue();
+ String text = before_unload_event.returnValue();
beforeunload_dialog_histogram.Count(
BeforeUnloadDialogHistogramEnum::kShowDialog);
- if (chrome_client.OpenBeforeUnloadConfirmPanel(text, frame_, is_reload)) {
- did_allow_navigation = true;
+ const TimeTicks beforeunload_confirmpanel_start = CurrentTimeTicks();
+ did_allow_navigation =
+ chrome_client.OpenBeforeUnloadConfirmPanel(text, frame_, is_reload);
+ const TimeTicks beforeunload_confirmpanel_end = CurrentTimeTicks();
+ if (did_allow_navigation) {
+ // Only record when a navigation occurs, since we want to understand
+ // the impact of the before unload dialog on overall input to navigation.
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "DocumentEventTiming.BeforeUnloadDialogDuration.ByNavigation",
+ beforeunload_confirmpanel_end - beforeunload_confirmpanel_start);
return true;
}
@@ -3548,7 +3640,8 @@ void Document::DispatchUnloadEvents() {
if (LocalDOMWindow* window = domWindow()) {
const TimeTicks pagehide_event_start = CurrentTimeTicks();
window->DispatchEvent(
- PageTransitionEvent::Create(EventTypeNames::pagehide, false), this);
+ *PageTransitionEvent::Create(EventTypeNames::pagehide, false),
+ this);
const TimeTicks pagehide_event_end = CurrentTimeTicks();
DEFINE_STATIC_LOCAL(
CustomCountHistogram, pagehide_histogram,
@@ -3565,7 +3658,7 @@ void Document::DispatchUnloadEvents() {
// Dispatch visibilitychange event, but don't bother doing
// other notifications as we're about to be unloaded.
const TimeTicks pagevisibility_hidden_event_start = CurrentTimeTicks();
- DispatchEvent(Event::CreateBubble(EventTypeNames::visibilitychange));
+ DispatchEvent(*Event::CreateBubble(EventTypeNames::visibilitychange));
const TimeTicks pagevisibility_hidden_event_end = CurrentTimeTicks();
DEFINE_STATIC_LOCAL(CustomCountHistogram, pagevisibility_histogram,
("DocumentEventTiming.PageVibilityHiddenDuration",
@@ -3574,7 +3667,7 @@ void Document::DispatchUnloadEvents() {
pagevisibility_hidden_event_end -
pagevisibility_hidden_event_start);
DispatchEvent(
- Event::CreateBubble(EventTypeNames::webkitvisibilitychange));
+ *Event::CreateBubble(EventTypeNames::webkitvisibilitychange));
}
if (!frame_)
return;
@@ -3584,7 +3677,7 @@ void Document::DispatchUnloadEvents() {
DocumentLoader* document_loader =
frame_->Loader().GetProvisionalDocumentLoader();
load_event_progress_ = kUnloadEventInProgress;
- Event* unload_event(Event::Create(EventTypeNames::unload));
+ Event& unload_event = *Event::Create(EventTypeNames::unload);
if (document_loader &&
document_loader->GetTiming().UnloadEventStart().is_null() &&
document_loader->GetTiming().UnloadEventEnd().is_null()) {
@@ -3627,7 +3720,7 @@ void Document::DispatchFreezeEvent() {
DCHECK(RuntimeEnabledFeatures::PageLifecycleEnabled());
const TimeTicks freeze_event_start = CurrentTimeTicks();
SetFreezingInProgress(true);
- DispatchEvent(Event::Create(EventTypeNames::freeze));
+ DispatchEvent(*Event::Create(EventTypeNames::freeze));
SetFreezingInProgress(false);
const TimeTicks freeze_event_end = CurrentTimeTicks();
DEFINE_STATIC_LOCAL(CustomCountHistogram, freeze_histogram,
@@ -3748,19 +3841,22 @@ void Document::write(const String& text,
bool has_insertion_point = parser_ && parser_->HasInsertionPoint();
- if (!has_insertion_point && ignore_destructive_write_count_) {
- AddConsoleMessage(
- ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
- ExceptionMessages::FailedToExecute(
- "write", "Document",
- "It isn't possible to write into a document "
- "from an asynchronously-loaded external "
- "script unless it is explicitly opened.")));
- return;
- }
+ if (!has_insertion_point) {
+ if (ignore_destructive_write_count_) {
+ AddConsoleMessage(ConsoleMessage::Create(
+ kJSMessageSource, kWarningMessageLevel,
+ ExceptionMessages::FailedToExecute(
+ "write", "Document",
+ "It isn't possible to write into a document "
+ "from an asynchronously-loaded external "
+ "script unless it is explicitly opened.")));
+ return;
+ }
+ if (ignore_opens_during_unload_count_)
+ return;
- if (!has_insertion_point)
open(entered_document, ASSERT_NO_EXCEPTION);
+ }
DCHECK(parser_);
PerformanceMonitor::ReportGenericViolation(
@@ -4152,7 +4248,7 @@ ReferrerPolicy Document::GetReferrerPolicy() const {
// For srcdoc documents without their own policy, walk up the frame
// tree to find the document that is either not a srcdoc or doesn't
// have its own policy. This algorithm is defined in
- // https://html.spec.whatwg.org/multipage/browsers.html#set-up-a-browsing-context-environment-settings-object.
+ // https://html.spec.whatwg.org/multipage/window-object.html#set-up-a-window-environment-settings-object.
if (!frame_ || policy != kReferrerPolicyDefault || !IsSrcdocDocument()) {
return policy;
}
@@ -4674,7 +4770,7 @@ bool Document::SetFocusedElement(Element* new_focused_element,
if (!focus_change_blocked && focused_element_) {
// Create the AXObject cache in a focus change because Chromium relies on
// it.
- if (AXObjectCache* cache = GetOrCreateAXObjectCache()) {
+ if (AXObjectCache* cache = ExistingAXObjectCache()) {
cache->HandleFocusedUIElementChanged(old_focused_element,
new_focused_element);
}
@@ -4976,7 +5072,7 @@ const OriginAccessEntry& Document::AccessEntryFromURL() {
if (!access_entry_from_url_) {
access_entry_from_url_ = std::make_unique<OriginAccessEntry>(
Url().Protocol(), Url().Host(),
- OriginAccessEntry::kAllowRegisterableDomains);
+ network::cors::OriginAccessEntry::kAllowRegisterableDomains);
}
return *access_entry_from_url_;
}
@@ -5264,17 +5360,19 @@ void Document::setDomain(const String& raw_domain,
// string "null". https://crbug.com/733150
if (!RuntimeEnabledFeatures::NullableDocumentDomainEnabled() ||
new_domain != "null") {
- OriginAccessEntry access_entry(GetSecurityOrigin()->Protocol(), new_domain,
- OriginAccessEntry::kAllowSubdomains);
- OriginAccessEntry::MatchResult result =
+ OriginAccessEntry access_entry(
+ GetSecurityOrigin()->Protocol(), new_domain,
+ network::cors::OriginAccessEntry::kAllowSubdomains);
+ network::cors::OriginAccessEntry::MatchResult result =
access_entry.MatchesOrigin(*GetSecurityOrigin());
- if (result == OriginAccessEntry::kDoesNotMatchOrigin) {
+ if (result == network::cors::OriginAccessEntry::kDoesNotMatchOrigin) {
exception_state.ThrowSecurityError(
"'" + new_domain + "' is not a suffix of '" + domain() + "'.");
return;
}
- if (result == OriginAccessEntry::kMatchesOriginButIsPublicSuffix) {
+ if (result ==
+ network::cors::OriginAccessEntry::kMatchesOriginButIsPublicSuffix) {
exception_state.ThrowSecurityError("'" + new_domain +
"' is a top-level domain.");
return;
@@ -5359,12 +5457,16 @@ const KURL Document::SiteForCookies() const {
// document's SecurityOrigin. A sandboxed document has a unique opaque
// origin, but that shouldn't affect first-/third-party status for cookies
// and site data.
+ base::Optional<OriginAccessEntry> remote_entry;
+ if (!top.IsLocalFrame()) {
+ remote_entry.emplace(
+ top_document_url.Protocol(), top_document_url.Host(),
+ network::cors::OriginAccessEntry::kAllowRegisterableDomains);
+ }
const OriginAccessEntry& access_entry =
- top.IsLocalFrame()
- ? ToLocalFrame(top).GetDocument()->AccessEntryFromURL()
- : OriginAccessEntry(top_document_url.Protocol(),
- top_document_url.Host(),
- OriginAccessEntry::kAllowRegisterableDomains);
+ remote_entry ? *remote_entry
+ : ToLocalFrame(top).GetDocument()->AccessEntryFromURL();
+
const Frame* current_frame = GetFrame();
while (current_frame) {
// Skip over srcdoc documents, as they are always same-origin with their
@@ -5375,11 +5477,10 @@ const KURL Document::SiteForCookies() const {
DCHECK(current_frame);
// We use 'matchesDomain' here, as it turns out that some folks embed HTTPS
- // login forms
- // into HTTP pages; we should allow this kind of upgrade.
+ // login forms into HTTP pages; we should allow this kind of upgrade.
if (access_entry.MatchesDomain(
*current_frame->GetSecurityContext()->GetSecurityOrigin()) ==
- OriginAccessEntry::kDoesNotMatchOrigin)
+ network::cors::OriginAccessEntry::kDoesNotMatchOrigin)
return SecurityOrigin::UrlWithUniqueOpaqueOrigin();
current_frame = current_frame->Tree().Parent();
@@ -5861,7 +5962,7 @@ void Document::FinishedParsing() {
// dispatched in a queued task, see https://crbug.com/425790
if (document_timing_.DomContentLoadedEventStart().is_null())
document_timing_.MarkDomContentLoadedEventStart();
- DispatchEvent(Event::CreateBubble(EventTypeNames::DOMContentLoaded));
+ DispatchEvent(*Event::CreateBubble(EventTypeNames::DOMContentLoaded));
if (document_timing_.DomContentLoadedEventEnd().is_null())
document_timing_.MarkDomContentLoadedEventEnd();
SetParsingState(kFinishedParsing);
@@ -5928,8 +6029,6 @@ void Document::FinishedParsing() {
if (IsPrefetchOnly())
WebPrerenderingSupport::Current()->PrefetchFinished();
-
- FirstMeaningfulPaintDetector::From(*this).CheckNetworkStable();
}
void Document::ElementDataCacheClearTimerFired(TimerBase*) {
@@ -6084,6 +6183,10 @@ void Document::ApplyFeaturePolicy(const ParsedFeaturePolicy& declared_policy) {
InitializeFeaturePolicy(declared_policy, container_policy,
parent_feature_policy);
+ // At this point, the document will not have been installed in the frame's
+ // LocalDOMWindow, so we cannot call frame_->IsFeatureEnabled. This calls
+ // SecurityContext::IsFeatureEnabled instead, which cannot report, but we
+ // don't need reporting here in any case.
is_vertical_scroll_enforced_ =
RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
!GetFeaturePolicy()->IsFeatureEnabled(
@@ -6097,7 +6200,8 @@ bool Document::AllowedToUseDynamicMarkUpInsertion(
return true;
}
if (!frame_ ||
- frame_->IsFeatureEnabled(mojom::FeaturePolicyFeature::kDocumentWrite)) {
+ frame_->IsFeatureEnabled(mojom::FeaturePolicyFeature::kDocumentWrite,
+ ReportOptions::kReportOnFailure)) {
return true;
}
@@ -7396,6 +7500,7 @@ void Document::Trace(blink::Visitor* visitor) {
visitor->Trace(policy_);
visitor->Trace(slot_assignment_engine_);
visitor->Trace(viewport_data_);
+ visitor->Trace(lazy_load_image_observer_);
Supplementable<Document>::Trace(visitor);
TreeScope::Trace(visitor);
ContainerNode::Trace(visitor);
@@ -7442,6 +7547,22 @@ bool Document::NextFrameHasPendingRAF() const {
scripted_animation_controller_->NextFrameHasPendingRAF();
}
+void Document::NavigateLocalAdsFrames() {
+ // This navigates all the frames detected as an advertisement to about:blank.
+ DCHECK(frame_);
+ for (Frame* child = frame_->Tree().FirstChild(); child;
+ child = child->Tree().TraverseNext(frame_)) {
+ if (child->IsLocalFrame()) {
+ if (ToLocalFrame(child)->IsAdSubframe()) {
+ ToLocalFrame(child)->Navigate(
+ FrameLoadRequest(this, ResourceRequest(BlankURL())));
+ }
+ }
+ // TODO(yuzus): Once AdsTracker for remote frames is implemented and OOPIF
+ // is enabled on low-end devices, navigate remote ads as well.
+ }
+}
+
SlotAssignmentEngine& Document::GetSlotAssignmentEngine() {
if (!slot_assignment_engine_)
slot_assignment_engine_ = SlotAssignmentEngine::Create();
@@ -7458,6 +7579,12 @@ bool Document::IsSlotAssignmentOrLegacyDistributionDirty() {
return false;
}
+LazyLoadImageObserver& Document::EnsureLazyLoadImageObserver() {
+ if (!lazy_load_image_observer_)
+ lazy_load_image_observer_ = new LazyLoadImageObserver();
+ return *lazy_load_image_observer_;
+}
+
template class CORE_TEMPLATE_EXPORT Supplement<Document>;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/document.h b/chromium/third_party/blink/renderer/core/dom/document.h
index 9fdbca84a36..a9c05b9bd37 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.h
+++ b/chromium/third_party/blink/renderer/core/dom/document.h
@@ -36,10 +36,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/css/css_style_sheet_init.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/create_element_flags.h"
#include "third_party/blink/renderer/core/dom/document_encoding_data.h"
@@ -86,10 +83,12 @@ enum class PageVisibilityState : int32_t;
} // namespace mojom
class AnimationClock;
+class AXContext;
class AXObjectCache;
class Attr;
class CDATASection;
class CSSStyleSheet;
+class CSSStyleSheetInit;
class CanvasFontCache;
class ChromeClient;
class Comment;
@@ -138,6 +137,7 @@ class IntersectionObserverController;
class LayoutPoint;
class ReattachLegacyLayoutObjectList;
class LayoutView;
+class LazyLoadImageObserver;
class LiveNodeListBase;
class LocalDOMWindow;
class Locale;
@@ -159,6 +159,8 @@ class Range;
class ResizeObserverController;
class ResourceFetcher;
class RootScrollerController;
+class ScriptPromise;
+class ScriptValue;
class SVGDocumentExtensions;
class SVGUseElement;
class Text;
@@ -362,6 +364,12 @@ class CORE_EXPORT Document : public ContainerNode,
Element* CreateRawElement(const QualifiedName&,
const CreateElementFlags = CreateElementFlags());
+ CSSStyleSheet* createEmptyCSSStyleSheet(ScriptState*,
+ const CSSStyleSheetInit&,
+ ExceptionState&);
+
+ CSSStyleSheet* createEmptyCSSStyleSheet(ScriptState*, ExceptionState&);
+
ScriptPromise createCSSStyleSheet(ScriptState*,
const String&,
ExceptionState&);
@@ -586,9 +594,12 @@ class CORE_EXPORT Document : public ContainerNode,
LayoutView* GetLayoutView() const { return layout_view_; }
- Document& AXObjectCacheOwner() const;
+ // This will return an AXObjectCache only if there's one or more
+ // AXContext associated with this document. When all associated
+ // AXContexts are deleted, the AXObjectCache will be removed.
AXObjectCache* ExistingAXObjectCache() const;
- AXObjectCache* GetOrCreateAXObjectCache() const;
+
+ Document& AXObjectCacheOwner() const;
void ClearAXObjectCache();
// to get visually ordered hebrew and arabic pages right
@@ -702,6 +713,12 @@ class CORE_EXPORT Document : public ContainerNode,
String UserAgent() const final;
void DisableEval(const String& error_message) final;
+ // TODO(https://crbug.com/880986): Implement Document's HTTPS state in more
+ // spec-conformant way.
+ HttpsState GetHttpsState() const final {
+ return CalculateHttpsState(GetSecurityOrigin());
+ }
+
CSSStyleSheet& ElementSheet();
virtual DocumentParser* CreateParser();
@@ -1427,6 +1444,7 @@ class CORE_EXPORT Document : public ContainerNode,
StylePropertyMapReadOnly* ComputedStyleMap(Element*);
void AddComputedStyleMapItem(Element*, StylePropertyMapReadOnly*);
StylePropertyMapReadOnly* RemoveComputedStyleMapItem(Element*);
+ void NavigateLocalAdsFrames();
SlotAssignmentEngine& GetSlotAssignmentEngine();
@@ -1445,6 +1463,20 @@ class CORE_EXPORT Document : public ContainerNode,
bool IsVerticalScrollEnforced() const { return is_vertical_scroll_enforced_; }
+ LazyLoadImageObserver& EnsureLazyLoadImageObserver();
+
+ // TODO(binji): See http://crbug.com/798572. This implementation shares the
+ // same agent cluster ID for any one document. The proper implementation of
+ // this function must follow the rules described here:
+ // https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-agent-cluster-formalism.
+ //
+ // Even with this simple implementation, we can prevent sharing
+ // SharedArrayBuffers and WebAssembly modules with workers that happen to be
+ // in the same process.
+ const base::UnguessableToken& GetAgentClusterID() const final {
+ return agent_cluster_id_;
+ }
+
protected:
Document(const DocumentInit&, DocumentClassFlags = kDefaultDocumentClass);
@@ -1462,11 +1494,16 @@ class CORE_EXPORT Document : public ContainerNode,
private:
friend class IgnoreDestructiveWriteCountIncrementer;
friend class ThrowOnDynamicMarkupInsertionCountIncrementer;
+ friend class IgnoreOpensDuringUnloadCountIncrementer;
friend class NthIndexCache;
FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest,
DuringOnFreeze);
class NetworkStateObserver;
+ friend class AXContext;
+ void AddAXContext(AXContext*);
+ void RemoveAXContext(AXContext*);
+
bool IsDocumentFragment() const =
delete; // This will catch anyone doing an unnecessary check.
bool IsDocumentNode() const =
@@ -1687,15 +1724,18 @@ class CORE_EXPORT Document : public ContainerNode,
bool contains_validity_style_rules_;
bool contains_plugins_;
- // http://www.whatwg.org/specs/web-apps/current-work/#ignore-destructive-writes-counter
+ // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#ignore-destructive-writes-counter
unsigned ignore_destructive_write_count_;
- // https://html.spec.whatwg.org/#throw-on-dynamic-markup-insertion-counter
+ // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter
unsigned throw_on_dynamic_markup_insertion_count_;
+ // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#ignore-opens-during-unload-counter
+ unsigned ignore_opens_during_unload_count_;
String title_;
String raw_title_;
Member<Element> title_element_;
+ Vector<AXContext*> ax_contexts_;
Member<AXObjectCache> ax_object_cache_;
Member<DocumentMarkerController> markers_;
@@ -1871,6 +1911,11 @@ class CORE_EXPORT Document : public ContainerNode,
// This is set through feature policy 'vertical-scroll'.
bool is_vertical_scroll_enforced_ = false;
+
+ Member<LazyLoadImageObserver> lazy_load_image_observer_;
+
+ // https://tc39.github.io/ecma262/#sec-agent-clusters
+ const base::UnguessableToken agent_cluster_id_;
};
extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<Document>;
diff --git a/chromium/third_party/blink/renderer/core/dom/document.idl b/chromium/third_party/blink/renderer/core/dom/document.idl
index 7f86ca16454..7956e34b566 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.idl
+++ b/chromium/third_party/blink/renderer/core/dom/document.idl
@@ -76,6 +76,8 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
[NewObject] Range createRange();
[CallWith=ScriptState, NewObject, RaisesException, RuntimeEnabled=ConstructableStylesheets] Promise<CSSStyleSheet> createCSSStyleSheet(DOMString text, optional CSSStyleSheetInit options);
+ [CallWith=ScriptState, NewObject, RaisesException, RuntimeEnabled=ConstructableStylesheets] CSSStyleSheet createEmptyCSSStyleSheet(optional CSSStyleSheetInit options);
+
// NodeFilter.SHOW_ALL = 0xFFFFFFFF
[NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
@@ -172,7 +174,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
// Custom Elements
// https://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-register
// FIXME: The registerElement return type should be Function.
- [RuntimeEnabled=CustomElementsV0, CallWith=ScriptState, CustomElementCallbacks, RaisesException, MeasureAs=DocumentRegisterElement] CustomElementConstructor registerElement(DOMString type, optional ElementRegistrationOptions options);
+ [RuntimeEnabled=CustomElementsV0, CallWith=ScriptState, CustomElementCallbacks, RaisesException, DeprecateAs=DocumentRegisterElement] CustomElementConstructor registerElement(DOMString type, optional ElementRegistrationOptions options);
// https://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-instantiate
// FIXME: The typeExtension arguments should not be nullable.
[CustomElementCallbacks, PerWorldBindings, RaisesException, ImplementedAs=CreateElementForBinding] Element createElement(DOMString localName, (DOMString or Dictionary)? options);
diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.cc b/chromium/third_party/blink/renderer/core/dom/document_init.cc
index 0dbe2895684..b1793b5c8bb 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_init.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_init.cc
@@ -40,10 +40,11 @@
namespace blink {
// FIXME: Broken with OOPI.
-static Document* ParentDocument(LocalFrame* frame) {
- DCHECK(frame);
+static Document* ParentDocument(DocumentLoader* loader) {
+ DCHECK(loader);
+ DCHECK(loader->GetFrame());
- Element* owner_element = frame->DeprecatedLocalOwner();
+ Element* owner_element = loader->GetFrame()->DeprecatedLocalOwner();
if (!owner_element)
return nullptr;
return &owner_element->GetDocument();
@@ -71,33 +72,37 @@ DocumentInit::DocumentInit(const DocumentInit&) = default;
DocumentInit::~DocumentInit() = default;
bool DocumentInit::ShouldSetURL() const {
- LocalFrame* frame = FrameForSecurityContext();
- return (frame && frame->Tree().Parent()) || !url_.IsEmpty();
+ DocumentLoader* loader = MasterDocumentLoader();
+ return (loader && loader->GetFrame()->Tree().Parent()) || !url_.IsEmpty();
}
bool DocumentInit::ShouldTreatURLAsSrcdocDocument() const {
return parent_document_ &&
- frame_->Loader().ShouldTreatURLAsSrcdocDocument(url_);
-}
-
-LocalFrame* DocumentInit::FrameForSecurityContext() const {
- if (frame_)
- return frame_;
- if (imports_controller_)
- return imports_controller_->Master()->GetFrame();
+ document_loader_->GetFrame()->Loader().ShouldTreatURLAsSrcdocDocument(
+ url_);
+}
+
+DocumentLoader* DocumentInit::MasterDocumentLoader() const {
+ if (document_loader_)
+ return document_loader_;
+ if (imports_controller_) {
+ return imports_controller_->Master()
+ ->GetFrame()
+ ->Loader()
+ .GetDocumentLoader();
+ }
return nullptr;
}
SandboxFlags DocumentInit::GetSandboxFlags() const {
- DCHECK(FrameForSecurityContext());
- FrameLoader* loader = &FrameForSecurityContext()->Loader();
- SandboxFlags flags = loader->EffectiveSandboxFlags();
+ DCHECK(MasterDocumentLoader());
+ DocumentLoader* loader = MasterDocumentLoader();
+ SandboxFlags flags = loader->GetFrame()->Loader().EffectiveSandboxFlags();
// If the load was blocked by CSP, force the Document's origin to be unique,
// so that the blocked document appears to be a normal cross-origin document's
// load per CSP spec: https://www.w3.org/TR/CSP3/#directive-frame-ancestors.
- if (loader->GetDocumentLoader() &&
- loader->GetDocumentLoader()->WasBlockedAfterCSP()) {
+ if (loader->WasBlockedAfterCSP()) {
flags |= kSandboxOrigin;
}
@@ -105,48 +110,50 @@ SandboxFlags DocumentInit::GetSandboxFlags() const {
}
WebInsecureRequestPolicy DocumentInit::GetInsecureRequestPolicy() const {
- DCHECK(FrameForSecurityContext());
- return FrameForSecurityContext()->Loader().GetInsecureRequestPolicy();
+ DCHECK(MasterDocumentLoader());
+ Frame* parent_frame = MasterDocumentLoader()->GetFrame()->Tree().Parent();
+ if (!parent_frame)
+ return kLeaveInsecureRequestsAlone;
+ return parent_frame->GetSecurityContext()->GetInsecureRequestPolicy();
}
SecurityContext::InsecureNavigationsSet*
DocumentInit::InsecureNavigationsToUpgrade() const {
- DCHECK(FrameForSecurityContext());
- return FrameForSecurityContext()->Loader().InsecureNavigationsToUpgrade();
+ DCHECK(MasterDocumentLoader());
+ Frame* parent_frame = MasterDocumentLoader()->GetFrame()->Tree().Parent();
+ if (!parent_frame)
+ return nullptr;
+ return parent_frame->GetSecurityContext()->InsecureNavigationsToUpgrade();
}
bool DocumentInit::IsHostedInReservedIPRange() const {
- if (LocalFrame* frame = FrameForSecurityContext()) {
- if (DocumentLoader* loader =
- frame->Loader().GetProvisionalDocumentLoader()
- ? frame->Loader().GetProvisionalDocumentLoader()
- : frame->Loader().GetDocumentLoader()) {
- if (!loader->GetResponse().RemoteIPAddress().IsEmpty())
- return NetworkUtils::IsReservedIPAddress(
- loader->GetResponse().RemoteIPAddress());
+ if (DocumentLoader* loader = MasterDocumentLoader()) {
+ if (!loader->GetResponse().RemoteIPAddress().IsEmpty()) {
+ return NetworkUtils::IsReservedIPAddress(
+ loader->GetResponse().RemoteIPAddress());
}
}
return false;
}
Settings* DocumentInit::GetSettings() const {
- DCHECK(FrameForSecurityContext());
- return FrameForSecurityContext()->GetSettings();
+ DCHECK(MasterDocumentLoader());
+ return MasterDocumentLoader()->GetFrame()->GetSettings();
}
-KURL DocumentInit::ParentBaseURL() const {
- return parent_document_->BaseURL();
-}
-
-DocumentInit& DocumentInit::WithFrame(LocalFrame* frame) {
- DCHECK(!frame_);
+DocumentInit& DocumentInit::WithDocumentLoader(DocumentLoader* loader) {
+ DCHECK(!document_loader_);
DCHECK(!imports_controller_);
- frame_ = frame;
- if (frame_)
- parent_document_ = ParentDocument(frame_);
+ document_loader_ = loader;
+ if (document_loader_)
+ parent_document_ = ParentDocument(document_loader_);
return *this;
}
+LocalFrame* DocumentInit::GetFrame() const {
+ return document_loader_ ? document_loader_->GetFrame() : nullptr;
+}
+
DocumentInit& DocumentInit::WithContextDocument(Document* context_document) {
DCHECK(!context_document_);
context_document_ = context_document;
diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.h b/chromium/third_party/blink/renderer/core/dom/document_init.h
index 6ebf5351f89..e3d0dff0d3d 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_init.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_init.h
@@ -41,6 +41,7 @@
namespace blink {
class Document;
+class DocumentLoader;
class LocalFrame;
class HTMLImportsController;
class Settings;
@@ -56,7 +57,7 @@ class CORE_EXPORT DocumentInit final {
// Example:
//
// DocumentInit init = DocumentInit::Create()
- // .WithFrame(frame)
+ // .WithDocumentLoader(loader)
// .WithContextDocument(context_document)
// .WithURL(url);
// Document* document = Document::Create(init);
@@ -70,21 +71,18 @@ class CORE_EXPORT DocumentInit final {
return imports_controller_;
}
- bool HasSecurityContext() const { return FrameForSecurityContext(); }
+ bool HasSecurityContext() const { return MasterDocumentLoader(); }
bool ShouldTreatURLAsSrcdocDocument() const;
bool ShouldSetURL() const;
- bool IsSeamlessAllowedFor(Document* child) const;
SandboxFlags GetSandboxFlags() const;
bool IsHostedInReservedIPRange() const;
WebInsecureRequestPolicy GetInsecureRequestPolicy() const;
SecurityContext::InsecureNavigationsSet* InsecureNavigationsToUpgrade() const;
- KURL ParentBaseURL() const;
- LocalFrame* OwnerFrame() const;
Settings* GetSettings() const;
- DocumentInit& WithFrame(LocalFrame*);
- LocalFrame* GetFrame() const { return frame_; }
+ DocumentInit& WithDocumentLoader(DocumentLoader*);
+ LocalFrame* GetFrame() const;
// Used by the DOMImplementation and DOMParser to pass their parent Document
// so that the created Document will return the Document when the
@@ -106,9 +104,13 @@ class CORE_EXPORT DocumentInit final {
private:
DocumentInit(HTMLImportsController*);
- LocalFrame* FrameForSecurityContext() const;
+ // For a Document associated directly with a frame, this will be the
+ // DocumentLoader driving the commit. For an import, XSLT-generated
+ // document, etc., it will be the DocumentLoader that drove the commit
+ // of its owning Document.
+ DocumentLoader* MasterDocumentLoader() const;
- Member<LocalFrame> frame_;
+ Member<DocumentLoader> document_loader_;
Member<Document> parent_document_;
Member<HTMLImportsController> imports_controller_;
diff --git a/chromium/third_party/blink/renderer/core/dom/document_test.cc b/chromium/third_party/blink/renderer/core/dom/document_test.cc
index 723e114dc87..5dd461ec82f 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_test.cc
@@ -812,7 +812,7 @@ TEST_F(DocumentTest, ValidationMessageCleanup) {
MockDocumentValidationMessageClient* mock_client =
new MockDocumentValidationMessageClient();
GetDocument().GetSettings()->SetScriptEnabled(true);
- GetPage().SetValidationMessageClient(mock_client);
+ GetPage().SetValidationMessageClientForTesting(mock_client);
// ImplicitOpen()-CancelParsing() makes Document.loadEventFinished()
// true. It's necessary to kick unload process.
GetDocument().ImplicitOpen(kForceSynchronousParsing);
@@ -839,7 +839,7 @@ TEST_F(DocumentTest, ValidationMessageCleanup) {
// Unload handler tried to show a validation message, but it should fail.
EXPECT_FALSE(mock_client->show_validation_message_was_called);
- GetPage().SetValidationMessageClient(original_client);
+ GetPage().SetValidationMessageClientForTesting(original_client);
}
TEST_F(DocumentTest, SandboxDisablesAppCache) {
diff --git a/chromium/third_party/blink/renderer/core/dom/document_type.cc b/chromium/third_party/blink/renderer/core/dom/document_type.cc
index 805509670c0..e28838c6399 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_type.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_type.cc
@@ -49,7 +49,7 @@ Node* DocumentType::Clone(Document& factory, CloneChildrenFlag) const {
}
Node::InsertionNotificationRequest DocumentType::InsertedInto(
- ContainerNode* insertion_point) {
+ ContainerNode& insertion_point) {
Node::InsertedInto(insertion_point);
// DocumentType can only be inserted into a Document.
@@ -60,7 +60,7 @@ Node::InsertionNotificationRequest DocumentType::InsertedInto(
return kInsertionDone;
}
-void DocumentType::RemovedFrom(ContainerNode* insertion_point) {
+void DocumentType::RemovedFrom(ContainerNode& insertion_point) {
GetDocument().SetDoctype(nullptr);
Node::RemovedFrom(insertion_point);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/document_type.h b/chromium/third_party/blink/renderer/core/dom/document_type.h
index 229d94530f9..2a3648cf904 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_type.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_type.h
@@ -53,8 +53,9 @@ class DocumentType final : public Node {
NodeType getNodeType() const override;
Node* Clone(Document&, CloneChildrenFlag) const override;
- InsertionNotificationRequest InsertedInto(ContainerNode*) override;
- void RemovedFrom(ContainerNode*) override;
+ InsertionNotificationRequest InsertedInto(ContainerNode&) override;
+ void RemovedFrom(ContainerNode&) override;
+ void DetachLayoutTree(const AttachContext&) final {}
String name_;
String public_id_;
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc b/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
index a2fbf84747a..c360933eb10 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
@@ -262,8 +262,10 @@ Document* DOMImplementation::createDocument(const String& type,
init, plugin_data->PluginBackgroundColorForMimeType(type));
}
// multipart/x-mixed-replace is only supported for images.
- if (Image::SupportsType(type) || type == "multipart/x-mixed-replace")
+ if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(type) ||
+ type == "multipart/x-mixed-replace") {
return ImageDocument::Create(init);
+ }
// Check to see if the type can be played by our media player, if so create a
// MediaDocument
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_string_list.cc b/chromium/third_party/blink/renderer/core/dom/dom_string_list.cc
index 6d85109886b..b68fd084575 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_string_list.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dom_string_list.cc
@@ -29,7 +29,7 @@
namespace blink {
-String DOMStringList::item(unsigned index) const {
+String DOMStringList::item(uint32_t index) const {
if (index >= strings_.size())
return String();
return strings_[index];
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_string_list.h b/chromium/third_party/blink/renderer/core/dom/dom_string_list.h
index 903f3a25141..adb66dfa73f 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_string_list.h
+++ b/chromium/third_party/blink/renderer/core/dom/dom_string_list.h
@@ -48,9 +48,9 @@ class CORE_EXPORT DOMStringList final : public ScriptWrappable {
void Sort();
// Implements the IDL.
- size_t length() const { return strings_.size(); }
+ uint32_t length() const { return strings_.size(); }
- String item(unsigned index) const;
+ String item(uint32_t index) const;
bool contains(const String&) const;
operator const Vector<String>&() const { return strings_; }
diff --git a/chromium/third_party/blink/renderer/core/dom/element.cc b/chromium/third_party/blink/renderer/core/dom/element.cc
index 54a70a4fd9d..9ebd8b8d797 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script_url.h"
#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
+#include "third_party/blink/renderer/core/accessibility/ax_context.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
#include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
@@ -81,7 +82,6 @@
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
-#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/editing/set_selection_options.h"
@@ -119,6 +119,7 @@
#include "third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
+#include "third_party/blink/renderer/core/invisible_dom/activate_invisible_event.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -139,6 +140,8 @@
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
+#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
+#include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"
#include "third_party/blink/renderer/core/svg/svg_a_element.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg_names.h"
@@ -153,8 +156,6 @@
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
-#include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h"
#include "third_party/blink/renderer/platform/wtf/bit_vector.h"
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
@@ -1403,17 +1404,21 @@ DOMRect* Element::getBoundingClientRect() {
}
const AtomicString& Element::computedRole() {
- GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(this);
- std::unique_ptr<ScopedAXObjectCache> cache =
- ScopedAXObjectCache::Create(GetDocument());
- return cache->Get()->ComputedRoleForNode(this);
+ Document& document = GetDocument();
+ if (!document.IsActive())
+ return g_null_atom;
+ document.UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(this);
+ AXContext ax_context(document);
+ return ax_context.GetAXObjectCache().ComputedRoleForNode(this);
}
String Element::computedName() {
- GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(this);
- std::unique_ptr<ScopedAXObjectCache> cache =
- ScopedAXObjectCache::Create(GetDocument());
- return cache->Get()->ComputedNameForNode(this);
+ Document& document = GetDocument();
+ if (!document.IsActive())
+ return String();
+ document.UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(this);
+ AXContext ax_context(document);
+ return ax_context.GetAXObjectCache().ComputedNameForNode(this);
}
AccessibleNode* Element::ExistingAccessibleNode() const {
@@ -1434,6 +1439,57 @@ AccessibleNode* Element::accessibleNode() {
return rare_data.EnsureAccessibleNode(this);
}
+const AtomicString& Element::invisible() const {
+ return FastGetAttribute(invisibleAttr);
+}
+
+void Element::setInvisible(const AtomicString& value) {
+ setAttribute(invisibleAttr, value);
+}
+
+void Element::DispatchActivateInvisibleEventIfNeeded() {
+ if (!RuntimeEnabledFeatures::InvisibleDOMEnabled())
+ return;
+ // Traverse all inclusive flat-tree ancestor and send activateinvisible
+ // on the ones that have the invisible attribute. Default event handler
+ // will remove invisible attribute of all invisible element if the event is
+ // not canceled, making this element and all ancestors visible again.
+ // We're saving them and the retargeted activated element as DOM structure
+ // may change due to event handlers.
+ HeapVector<Member<Element>> invisible_ancestors;
+ HeapVector<Member<Element>> activated_elements;
+ for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(*this)) {
+ if (ancestor.IsElementNode() && ToElement(ancestor).invisible()) {
+ invisible_ancestors.push_back(ToElement(ancestor));
+ activated_elements.push_back(ancestor.GetTreeScope().Retarget(*this));
+ }
+ }
+ auto* activated_element_iterator = activated_elements.begin();
+ for (Element* ancestor : invisible_ancestors) {
+ DCHECK(activated_element_iterator != activated_elements.end());
+ ancestor->DispatchEvent(
+ *ActivateInvisibleEvent::Create(*activated_element_iterator));
+ ++activated_element_iterator;
+ }
+}
+
+void Element::InvisibleAttributeChanged() {
+ SetNeedsStyleRecalc(
+ kLocalStyleChange,
+ StyleChangeReasonForTracing::Create(StyleChangeReason::kInvisibleChange));
+}
+
+void Element::DefaultEventHandler(Event& event) {
+ if (RuntimeEnabledFeatures::InvisibleDOMEnabled() &&
+ event.type() == EventTypeNames::activateinvisible &&
+ event.target() == this) {
+ removeAttribute(invisibleAttr);
+ event.SetDefaultHandled();
+ return;
+ }
+ ContainerNode::DefaultEventHandler(event);
+}
+
bool Element::toggleAttribute(const AtomicString& qualified_name,
ExceptionState& exception_state) {
// https://dom.spec.whatwg.org/#dom-element-toggleattribute
@@ -1581,19 +1637,11 @@ void Element::SetSynchronizedLazyAttribute(const QualifiedName& name,
void Element::setAttribute(const QualifiedName& name,
const StringOrTrustedHTML& stringOrHTML,
ExceptionState& exception_state) {
- DCHECK(stringOrHTML.IsString() ||
- RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
- if (stringOrHTML.IsString() && GetDocument().RequireTrustedTypes()) {
- exception_state.ThrowTypeError(
- "This document requires `TrustedHTML` assignment.");
- return;
+ String valueString =
+ TrustedHTML::GetString(stringOrHTML, &GetDocument(), exception_state);
+ if (!exception_state.HadException()) {
+ setAttribute(name, AtomicString(valueString));
}
-
- String valueString = stringOrHTML.IsString()
- ? stringOrHTML.GetAsString()
- : stringOrHTML.GetAsTrustedHTML()->toString();
-
- setAttribute(name, AtomicString(valueString));
}
void Element::setAttribute(const QualifiedName& name,
@@ -1617,19 +1665,11 @@ void Element::setAttribute(const QualifiedName& name,
void Element::setAttribute(const QualifiedName& name,
const USVStringOrTrustedURL& stringOrURL,
ExceptionState& exception_state) {
- DCHECK(stringOrURL.IsUSVString() ||
- RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
- if (stringOrURL.IsUSVString() && GetDocument().RequireTrustedTypes()) {
- exception_state.ThrowTypeError(
- "This document requires `TrustedURL` assignment.");
- return;
+ String url =
+ TrustedURL::GetString(stringOrURL, &GetDocument(), exception_state);
+ if (!exception_state.HadException()) {
+ setAttribute(name, AtomicString(url));
}
-
- String valueString = stringOrURL.IsUSVString()
- ? stringOrURL.GetAsUSVString()
- : stringOrURL.GetAsTrustedURL()->toString();
-
- setAttribute(name, AtomicString(valueString));
}
ALWAYS_INLINE void Element::SetAttributeInternal(
@@ -1722,6 +1762,10 @@ void Element::AttributeChanged(const AttributeModificationParams& params) {
GetElementData()->presentation_attribute_style_is_dirty_ = true;
SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::FromAttribute(name));
+ } else if (RuntimeEnabledFeatures::InvisibleDOMEnabled() &&
+ name == HTMLNames::invisibleAttr &&
+ params.old_value.IsNull() != params.new_value.IsNull()) {
+ InvisibleAttributeChanged();
}
}
@@ -1969,14 +2013,14 @@ LayoutObject* Element::CreateLayoutObject(const ComputedStyle& style) {
}
Node::InsertionNotificationRequest Element::InsertedInto(
- ContainerNode* insertion_point) {
+ ContainerNode& insertion_point) {
// need to do superclass processing first so isConnected() is true
// by the time we reach updateId
ContainerNode::InsertedInto(insertion_point);
DCHECK(!HasRareData() || !GetElementRareData()->HasPseudoElements());
- if (!insertion_point->IsInTreeScope())
+ if (!insertion_point.IsInTreeScope())
return kInsertionDone;
if (HasRareData()) {
@@ -1995,7 +2039,7 @@ Node::InsertionNotificationRequest Element::InsertedInto(
CustomElement::TryToUpgrade(this);
}
- TreeScope& scope = insertion_point->GetTreeScope();
+ TreeScope& scope = insertion_point.GetTreeScope();
if (scope != GetTreeScope())
return kInsertionDone;
@@ -2013,8 +2057,8 @@ Node::InsertionNotificationRequest Element::InsertedInto(
return kInsertionDone;
}
-void Element::RemovedFrom(ContainerNode* insertion_point) {
- bool was_in_document = insertion_point->isConnected();
+void Element::RemovedFrom(ContainerNode& insertion_point) {
+ bool was_in_document = insertion_point.isConnected();
if (HasRareData()) {
// If we detached the layout tree with LazyReattachIfAttached, we might not
// have cleared the pseudo elements if we remove the element before calling
@@ -2026,10 +2070,10 @@ void Element::RemovedFrom(ContainerNode* insertion_point) {
if (Fullscreen::IsFullscreenElement(*this)) {
SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
- if (insertion_point->IsElementNode()) {
- ToElement(insertion_point)->SetContainsFullScreenElement(false);
+ if (insertion_point.IsElementNode()) {
+ ToElement(insertion_point).SetContainsFullScreenElement(false);
ToElement(insertion_point)
- ->SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(
+ .SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(
false);
}
}
@@ -2039,10 +2083,10 @@ void Element::RemovedFrom(ContainerNode* insertion_point) {
SetSavedLayerScrollOffset(ScrollOffset());
- if (insertion_point->IsInTreeScope() && GetTreeScope() == GetDocument()) {
+ if (insertion_point.IsInTreeScope() && GetTreeScope() == GetDocument()) {
const AtomicString& id_value = GetIdAttribute();
if (!id_value.IsNull())
- UpdateId(insertion_point->GetTreeScope(), id_value, g_null_atom);
+ UpdateId(insertion_point.GetTreeScope(), id_value, g_null_atom);
const AtomicString& name_value = GetNameAttribute();
if (!name_value.IsNull())
@@ -2057,7 +2101,7 @@ void Element::RemovedFrom(ContainerNode* insertion_point) {
if (GetCustomElementState() == CustomElementState::kCustom)
CustomElement::EnqueueDisconnectedCallback(this);
else if (IsUpgradedV0CustomElement())
- V0CustomElement::DidDetach(this, insertion_point->GetDocument());
+ V0CustomElement::DidDetach(this, insertion_point.GetDocument());
if (NeedsStyleInvalidation()) {
GetDocument()
@@ -2130,8 +2174,6 @@ void Element::AttachLayoutTree(AttachContext& context) {
rare_data->ClearPseudoElements();
}
- SelectorFilterParentScope filter_scope(*this);
-
AttachContext children_context(context);
LayoutObject* layout_object = GetLayoutObject();
@@ -2155,16 +2197,8 @@ void Element::AttachLayoutTree(AttachContext& context) {
AttachPseudoElement(kPseudoIdAfter, children_context);
AttachPseudoElement(kPseudoIdBackdrop, children_context);
- // We create the first-letter element after the :before, :after and
- // children are attached because the first letter text could come
- // from any of them.
- //
- // TODO(futhark@chromium.org: Replace with AttachPseudoElement when we create
- // ::first-letter elements during style recalc.
- if (PseudoElement* first_letter =
- CreatePseudoElementIfNeeded(kPseudoIdFirstLetter)) {
- first_letter->AttachLayoutTree(children_context);
- }
+ UpdateFirstLetterPseudoElement(StyleUpdatePhase::kAttachLayoutTree);
+ AttachPseudoElement(kPseudoIdFirstLetter, children_context);
if (layout_object) {
if (!layout_object->IsFloatingOrOutOfFlowPositioned())
@@ -2180,9 +2214,7 @@ void Element::DetachLayoutTree(const AttachContext& context) {
RemoveCallbackSelectors();
if (HasRareData()) {
ElementRareData* data = GetElementRareData();
- if (context.performing_reattach)
- data->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
- else
+ if (!context.performing_reattach)
data->ClearPseudoElements();
// attachLayoutTree() will clear the computed style for us when inside
@@ -2217,6 +2249,7 @@ void Element::DetachLayoutTree(const AttachContext& context) {
DetachPseudoElement(kPseudoIdAfter, context);
DetachPseudoElement(kPseudoIdBackdrop, context);
+ DetachPseudoElement(kPseudoIdFirstLetter, context);
if (!context.performing_reattach && IsUserActionElement()) {
if (IsHovered())
@@ -2251,8 +2284,7 @@ scoped_refptr<ComputedStyle> Element::StyleForLayoutObject() {
? CustomStyleForLayoutObject()
: OriginalStyleForLayoutObject();
if (!style) {
- DCHECK(IsBeforePseudoElement() || IsAfterPseudoElement() ||
- GetPseudoId() == kPseudoIdBackdrop);
+ DCHECK(IsPseudoElement());
return nullptr;
}
@@ -2299,7 +2331,16 @@ bool Element::ShouldCallRecalcStyleForChildren(StyleRecalcChange change) {
void Element::RecalcStyle(StyleRecalcChange change) {
DCHECK(GetDocument().InStyleRecalc());
DCHECK(!GetDocument().Lifecycle().InDetach());
- DCHECK(!ParentOrShadowHostNode()->NeedsStyleRecalc());
+ // If we are re-attaching in a Shadow DOM v0 tree, we recalc down to the
+ // distributed nodes to propagate kReattach down the flat tree (See
+ // V0InsertionPoint::DidRecalcStyle). That means we may have a shadow-
+ // including parent (V0InsertionPoint) with dirty recalc bit in the case where
+ // fallback content has been redistributed to a different insertion point.
+ // This will not happen for Shadow DOM v1 because we walk assigned nodes and
+ // slots themselves are assigned and part of the flat tree.
+ DCHECK(
+ !ParentOrShadowHostNode()->NeedsStyleRecalc() ||
+ (ParentOrShadowHostNode()->IsV0InsertionPoint() && change == kReattach));
DCHECK(InActiveDocument());
if (HasCustomStyleCallbacks())
@@ -2348,6 +2389,8 @@ void Element::RecalcStyle(StyleRecalcChange change) {
change = kReattach;
if (change == kReattach)
SetNeedsReattachLayoutTree();
+ else if (GetStyleChangeType() == kSubtreeStyleChange)
+ change = kForce;
}
// Needed because the RebuildLayoutTree code needs to see what the
@@ -2365,14 +2408,11 @@ void Element::RecalcStyle(StyleRecalcChange change) {
}
if (ShouldCallRecalcStyleForChildren(change)) {
- // TODO(futhark@chromium.org): Pseudo elements are feature-less and match
- // the same features as their originating element. Move the filter scope
- // inside the if-block for shadow-including descendants below.
- SelectorFilterParentScope filter_scope(*this);
UpdatePseudoElement(kPseudoIdBefore, change);
if (change > kUpdatePseudoElements || ChildNeedsStyleRecalc()) {
+ SelectorFilterParentScope filter_scope(*this);
if (ShadowRoot* root = GetShadowRoot()) {
if (root->ShouldCallRecalcStyle(change))
root->RecalcStyle(change);
@@ -2382,13 +2422,11 @@ void Element::RecalcStyle(StyleRecalcChange change) {
UpdatePseudoElement(kPseudoIdAfter, change);
- // If our children have changed then we need to force the first-letter
- // checks as we don't know if they effected the first letter or not.
- // This can be seen when a child transitions from floating to
- // non-floating we have to take it into account for the first letter.
- UpdatePseudoElement(
- kPseudoIdFirstLetter,
- change < kForce && ChildNeedsStyleRecalc() ? kForce : change);
+ // If we are re-attaching us or any of our descendants, we need to attach
+ // the descendants before we know if this element generates a ::first-letter
+ // and which element the ::first-letter inherits style from.
+ if (change < kReattach && !ChildNeedsReattachLayoutTree())
+ UpdateFirstLetterPseudoElement(StyleUpdatePhase::kRecalc);
ClearChildNeedsStyleRecalc();
}
@@ -2421,7 +2459,6 @@ scoped_refptr<ComputedStyle> Element::PropagateInheritedProperties(
StyleRecalcChange Element::RecalcOwnStyle(StyleRecalcChange change) {
DCHECK(GetDocument().InStyleRecalc());
- DCHECK(!ParentOrShadowHostNode()->NeedsStyleRecalc());
DCHECK(change >= kIndependentInherit || NeedsStyleRecalc());
DCHECK(ParentComputedStyle());
DCHECK(!GetNonAttachedStyle());
@@ -2519,7 +2556,6 @@ void Element::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
whitespace_attacher.DidReattachElement(this,
reattach_context.previous_in_flow);
} else {
- SelectorFilterParentScope filter_scope(*this);
// We create a local WhitespaceAttacher when rebuilding children of an
// element with a LayoutObject since whitespace nodes do not rely on layout
// objects further up the tree. Also, if this Element's layout object is an
@@ -2545,7 +2581,8 @@ void Element::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
RebuildChildrenLayoutTrees(*child_attacher);
RebuildPseudoElementLayoutTree(kPseudoIdBefore, *child_attacher);
RebuildPseudoElementLayoutTree(kPseudoIdBackdrop, *child_attacher);
- RebuildPseudoElementLayoutTree(kPseudoIdFirstLetter, *child_attacher);
+ RebuildFirstLetterLayoutTree();
+ ClearChildNeedsReattachLayoutTree();
}
DCHECK(!NeedsStyleRecalc());
DCHECK(!ChildNeedsStyleRecalc());
@@ -2565,30 +2602,33 @@ void Element::RebuildShadowRootLayoutTree(
void Element::RebuildPseudoElementLayoutTree(
PseudoId pseudo_id,
WhitespaceAttacher& whitespace_attacher) {
- PseudoElement* element = GetPseudoElement(pseudo_id);
- if (pseudo_id == kPseudoIdFirstLetter) {
- // Need to create a ::first-letter element here for the following case:
- //
- // <style>#outer::first-letter {...}</style>
- // <div id=outer><div id=inner style="display:none">Text</div></div>
- // <script> outer.offsetTop; inner.style.display = "block" </script>
- //
- // The creation of FirstLetterPseudoElement relies on the layout tree of the
- // block contents. In this case, the ::first-letter element is not created
- // initially since the #inner div is not displayed. On RecalcStyle it's not
- // created since the layout tree is still not built, and AttachLayoutTree
- // for #inner will not update the ::first-letter of outer. However, we end
- // up here for #outer after AttachLayoutTree is called on #inner at which
- // point the layout sub-tree is available for deciding on creating the
- // ::first-letter.
- if (!element)
- element = CreatePseudoElementIfNeeded(pseudo_id);
- else if (UpdateFirstLetter(element))
- return;
+ if (PseudoElement* element = GetPseudoElement(pseudo_id)) {
+ if (element->NeedsRebuildLayoutTree(whitespace_attacher))
+ element->RebuildLayoutTree(whitespace_attacher);
}
+}
- if (element && element->NeedsRebuildLayoutTree(whitespace_attacher))
- element->RebuildLayoutTree(whitespace_attacher);
+void Element::RebuildFirstLetterLayoutTree() {
+ // Need to create a ::first-letter element here for the following case:
+ //
+ // <style>#outer::first-letter {...}</style>
+ // <div id=outer><div id=inner style="display:none">Text</div></div>
+ // <script> outer.offsetTop; inner.style.display = "block" </script>
+ //
+ // The creation of FirstLetterPseudoElement relies on the layout tree of the
+ // block contents. In this case, the ::first-letter element is not created
+ // initially since the #inner div is not displayed. On RecalcStyle it's not
+ // created since the layout tree is still not built, and AttachLayoutTree
+ // for #inner will not update the ::first-letter of outer. However, we end
+ // up here for #outer after AttachLayoutTree is called on #inner at which
+ // point the layout sub-tree is available for deciding on creating the
+ // ::first-letter.
+ UpdateFirstLetterPseudoElement(StyleUpdatePhase::kRebuildLayoutTree);
+ if (PseudoElement* element = GetPseudoElement(kPseudoIdFirstLetter)) {
+ WhitespaceAttacher whitespace_attacher;
+ if (element->NeedsRebuildLayoutTree(whitespace_attacher))
+ element->RebuildLayoutTree(whitespace_attacher);
+ }
}
void Element::UpdateCallbackSelectors(const ComputedStyle* old_style,
@@ -2642,7 +2682,7 @@ ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) {
shadow_root->SetNeedsDistributionRecalc();
}
- shadow_root->InsertedInto(this);
+ shadow_root->InsertedInto(*this);
SetChildNeedsStyleRecalc();
SetNeedsStyleRecalc(kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
StyleChangeReason::kShadow));
@@ -2827,7 +2867,8 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit& shadow_root_init_dict,
DCHECK(!shadow_root_init_dict.hasMode() || !GetShadowRoot());
bool delegates_focus = shadow_root_init_dict.hasDelegatesFocus() &&
shadow_root_init_dict.delegatesFocus();
- return &AttachShadowRootInternal(type, delegates_focus);
+ bool manual_slotting = shadow_root_init_dict.slotting() == "manual";
+ return &AttachShadowRootInternal(type, delegates_focus, manual_slotting);
}
ShadowRoot& Element::CreateShadowRootInternal() {
@@ -2844,7 +2885,8 @@ ShadowRoot& Element::CreateUserAgentShadowRoot() {
}
ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
- bool delegates_focus) {
+ bool delegates_focus,
+ bool manual_slotting) {
// SVG <use> is a special case for using this API to create a closed shadow
// root.
DCHECK(CanAttachShadowRoot() || IsSVGUseElement(*this));
@@ -2855,6 +2897,8 @@ ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
GetDocument().SetShadowCascadeOrder(ShadowCascadeOrder::kShadowCascadeV1);
ShadowRoot& shadow_root = CreateAndAttachShadowRoot(type);
shadow_root.SetDelegatesFocus(delegates_focus);
+ shadow_root.SetSlotting(manual_slotting ? ShadowRootSlotting::kManual
+ : ShadowRootSlotting::kAuto);
return shadow_root;
}
@@ -2955,7 +2999,6 @@ void Element::ChildrenChanged(const ChildrenChange& change) {
ToElement(change.sibling_changed), change.sibling_before_change,
change.sibling_after_change);
- // TODO(hayato): Confirm that we can skip this if a shadow tree is v1.
if (ShadowRoot* shadow_root = GetShadowRoot())
shadow_root->SetNeedsDistributionRecalcWillBeSetNeedsAssignmentRecalc();
}
@@ -3400,17 +3443,17 @@ Element* Element::AdjustedFocusedElementInTreeScope() const {
void Element::DispatchFocusEvent(Element* old_focused_element,
WebFocusType type,
InputDeviceCapabilities* source_capabilities) {
- DispatchEvent(FocusEvent::Create(EventTypeNames::focus, Event::Bubbles::kNo,
- GetDocument().domWindow(), 0,
- old_focused_element, source_capabilities));
+ DispatchEvent(*FocusEvent::Create(EventTypeNames::focus, Event::Bubbles::kNo,
+ GetDocument().domWindow(), 0,
+ old_focused_element, source_capabilities));
}
void Element::DispatchBlurEvent(Element* new_focused_element,
WebFocusType type,
InputDeviceCapabilities* source_capabilities) {
- DispatchEvent(FocusEvent::Create(EventTypeNames::blur, Event::Bubbles::kNo,
- GetDocument().domWindow(), 0,
- new_focused_element, source_capabilities));
+ DispatchEvent(*FocusEvent::Create(EventTypeNames::blur, Event::Bubbles::kNo,
+ GetDocument().domWindow(), 0,
+ new_focused_element, source_capabilities));
}
void Element::DispatchFocusInEvent(
@@ -3423,7 +3466,7 @@ void Element::DispatchFocusInEvent(
#endif
DCHECK(event_type == EventTypeNames::focusin ||
event_type == EventTypeNames::DOMFocusIn);
- DispatchScopedEvent(FocusEvent::Create(
+ DispatchScopedEvent(*FocusEvent::Create(
event_type, Event::Bubbles::kYes, GetDocument().domWindow(), 0,
old_focused_element, source_capabilities));
}
@@ -3437,7 +3480,7 @@ void Element::DispatchFocusOutEvent(
#endif
DCHECK(event_type == EventTypeNames::focusout ||
event_type == EventTypeNames::DOMFocusOut);
- DispatchScopedEvent(FocusEvent::Create(
+ DispatchScopedEvent(*FocusEvent::Create(
event_type, Event::Bubbles::kYes, GetDocument().domWindow(), 0,
new_focused_element, source_capabilities));
}
@@ -3480,20 +3523,11 @@ void Element::SetInnerHTMLFromString(const String& html) {
void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html,
ExceptionState& exception_state) {
- DCHECK(string_or_html.IsString() ||
- RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
- if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
- exception_state.ThrowTypeError(
- "This document requires `TrustedHTML` assignment.");
- return;
+ String html =
+ TrustedHTML::GetString(string_or_html, &GetDocument(), exception_state);
+ if (!exception_state.HadException()) {
+ SetInnerHTMLFromString(html, exception_state);
}
-
- String html = string_or_html.IsString()
- ? string_or_html.GetAsString()
- : string_or_html.GetAsTrustedHTML()->toString();
-
- SetInnerHTMLFromString(html, exception_state);
}
void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html) {
@@ -3537,20 +3571,11 @@ void Element::SetOuterHTMLFromString(const String& html,
void Element::setOuterHTML(const StringOrTrustedHTML& string_or_html,
ExceptionState& exception_state) {
- DCHECK(string_or_html.IsString() ||
- RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
- if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
- exception_state.ThrowTypeError(
- "This document requires `TrustedHTML` assignment.");
- return;
+ String html =
+ TrustedHTML::GetString(string_or_html, &GetDocument(), exception_state);
+ if (!exception_state.HadException()) {
+ SetOuterHTMLFromString(html, exception_state);
}
-
- String html = string_or_html.IsString()
- ? string_or_html.GetAsString()
- : string_or_html.GetAsTrustedHTML()->toString();
-
- SetOuterHTMLFromString(html, exception_state);
}
Node* Element::InsertAdjacent(const String& where,
@@ -3697,20 +3722,11 @@ void Element::insertAdjacentHTML(const String& where,
void Element::insertAdjacentHTML(const String& where,
const StringOrTrustedHTML& string_or_html,
ExceptionState& exception_state) {
- DCHECK(string_or_html.IsString() ||
- RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
- if (string_or_html.IsString() && GetDocument().RequireTrustedTypes()) {
- exception_state.ThrowTypeError(
- "This document requires `TrustedHTML` assignment.");
- return;
+ String markup =
+ TrustedHTML::GetString(string_or_html, &GetDocument(), exception_state);
+ if (!exception_state.HadException()) {
+ insertAdjacentHTML(where, markup, exception_state);
}
-
- String markup = string_or_html.IsString()
- ? string_or_html.GetAsString()
- : string_or_html.GetAsTrustedHTML()->toString();
-
- insertAdjacentHTML(where, markup, exception_state);
}
void Element::setPointerCapture(int pointer_id,
@@ -3760,19 +3776,6 @@ bool Element::HasProcessedPointerCapture(int pointer_id) const {
pointer_id, this);
}
-String Element::innerText() {
- // We need to update layout, since plainText uses line boxes in the layout
- // tree.
- GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(this);
-
- if (!GetLayoutObject() && !HasDisplayContentsStyle())
- return textContent(true);
-
- return PlainText(
- EphemeralRange::RangeOfContents(*this),
- TextIteratorBehavior::Builder().SetForInnerText(true).Build());
-}
-
String Element::outerText() {
// Getting outerText is the same as getting innerText, only
// setting is different. You would think this should get the plain
@@ -3979,35 +3982,99 @@ void Element::CancelFocusAppearanceUpdate() {
GetDocument().CancelFocusAppearanceUpdate();
}
-void Element::UpdatePseudoElement(PseudoId pseudo_id,
- StyleRecalcChange change) {
- // TODO(futhark@chromium.org): Update ::first-letter pseudo elements and style
- // as part of style recalc also when re-attaching.
- if (change == kReattach && pseudo_id == kPseudoIdFirstLetter)
+void Element::UpdateFirstLetterPseudoElement(StyleUpdatePhase phase) {
+ // Update the ::first-letter pseudo elements presence and its style. This
+ // method may be called from style recalc or layout tree rebuilding/
+ // reattachment. In order to know if an element generates a ::first-letter
+ // element, we need to know if:
+ //
+ // * The element generates a block level box to which ::first-letter applies.
+ // * The element's layout subtree generates any first letter text.
+ // * None of the descendant blocks generate a ::first-letter element.
+ // (This is not correct according to spec as all block containers should be
+ // able to generate ::first-letter elements around the first letter of the
+ // first formatted text, but Blink is only supporting a single
+ // ::first-letter element which is the innermost block generating a
+ // ::first-letter).
+ //
+ // We do not always do this at style recalc time as that would have required
+ // us to collect the information about how the layout tree will look like
+ // after the layout tree is attached. So, instead we will wait until we have
+ // an up-to-date layout sub-tree for the element we are considering for
+ // ::first-letter.
+ //
+ // The StyleUpdatePhase tells where we are in the process of updating style
+ // and layout tree.
+
+ PseudoElement* element = GetPseudoElement(kPseudoIdFirstLetter);
+ if (!element) {
+ element = CreatePseudoElementIfNeeded(kPseudoIdFirstLetter);
+ // If we are in Element::AttachLayoutTree, don't mess up the ancestor flags
+ // for layout tree attachment/rebuilding. We will unconditionally call
+ // AttachLayoutTree for the created pseudo element immediately after this
+ // call.
+ if (element && phase != StyleUpdatePhase::kAttachLayoutTree)
+ element->SetNeedsReattachLayoutTree();
+ return;
+ }
+
+ if (phase == StyleUpdatePhase::kRebuildLayoutTree &&
+ element->NeedsReattachLayoutTree()) {
+ // We were already updated in RecalcStyle and ready for reattach.
+ DCHECK(element->GetNonAttachedStyle());
+ return;
+ }
+
+ if (!CanGeneratePseudoElement(kPseudoIdFirstLetter)) {
+ GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
+ return;
+ }
+
+ LayoutObject* remaining_text_layout_object =
+ FirstLetterPseudoElement::FirstLetterTextLayoutObject(*element);
+
+ if (!remaining_text_layout_object) {
+ GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
+ return;
+ }
+
+ bool text_node_changed =
+ remaining_text_layout_object !=
+ ToFirstLetterPseudoElement(element)->RemainingTextLayoutObject();
+
+ if (phase == StyleUpdatePhase::kAttachLayoutTree) {
+ // RemainingTextLayoutObject should have been cleared from DetachLayoutTree.
+ DCHECK(!ToFirstLetterPseudoElement(element)->RemainingTextLayoutObject());
+ DCHECK(text_node_changed);
+ scoped_refptr<ComputedStyle> pseudo_style = element->StyleForLayoutObject();
+ if (PseudoElementLayoutObjectIsNeeded(pseudo_style.get()))
+ element->SetNonAttachedStyle(std::move(pseudo_style));
+ else
+ GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
return;
+ }
+
+ element->RecalcStyle(text_node_changed ? kReattach : kForce);
+
+ if (element->NeedsReattachLayoutTree() &&
+ !PseudoElementLayoutObjectIsNeeded(element->GetNonAttachedStyle())) {
+ GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
+ }
+}
+void Element::UpdatePseudoElement(PseudoId pseudo_id,
+ StyleRecalcChange change) {
PseudoElement* element = GetPseudoElement(pseudo_id);
if (!element) {
- if (change >= kUpdatePseudoElements)
- element = CreatePseudoElementIfNeeded(pseudo_id);
- // TODO(futhark@chromium.org): We cannot SetNeedsReattachLayoutTree() for
- // ::first-letter inside CreatePseudoElementIfNeeded() because it may be
- // called from layout tree attachment.
- if (element && pseudo_id == kPseudoIdFirstLetter)
+ if (change < kUpdatePseudoElements)
+ return;
+ if ((element = CreatePseudoElementIfNeeded(pseudo_id)))
element->SetNeedsReattachLayoutTree();
return;
}
if (change == kUpdatePseudoElements ||
element->ShouldCallRecalcStyle(change)) {
- if (pseudo_id == kPseudoIdFirstLetter) {
- if (UpdateFirstLetter(element))
- return;
- // Need to clear the cached style if the PseudoElement wants a recalc so
- // it computes a new style.
- if (element->NeedsStyleRecalc())
- MutableComputedStyle()->RemoveCachedPseudoStyle(kPseudoIdFirstLetter);
- }
if (CanGeneratePseudoElement(pseudo_id)) {
element->RecalcStyle(change == kUpdatePseudoElements ? kForce : change);
if (!element->NeedsReattachLayoutTree())
@@ -4016,54 +4083,22 @@ void Element::UpdatePseudoElement(PseudoId pseudo_id,
return;
}
GetElementRareData()->SetPseudoElement(pseudo_id, nullptr);
- } else if (pseudo_id == kPseudoIdFirstLetter &&
- change >= kUpdatePseudoElements &&
- !FirstLetterPseudoElement::FirstLetterTextLayoutObject(*element)) {
- // We can end up here if we change to a float, for example. We need to
- // cleanup the first-letter PseudoElement and then fix the text of the
- // original remaining text LayoutObject. This can be seen in Test 7 of
- // fast/css/first-letter-removed-added.html
- GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
}
}
-// If we're updating first letter, and the current first letter layoutObject
-// is not the same as the one we're currently using we need to re-create
-// the first letter layoutObject.
-bool Element::UpdateFirstLetter(Element* element) {
- LayoutObject* remaining_text_layout_object =
- FirstLetterPseudoElement::FirstLetterTextLayoutObject(*element);
- if (!remaining_text_layout_object ||
- remaining_text_layout_object !=
- ToFirstLetterPseudoElement(element)->RemainingTextLayoutObject()) {
- // We have to clear out the old first letter here because when it is
- // disposed it will set the original text back on the remaining text
- // layoutObject. If we dispose after creating the new one we will get
- // incorrect results due to setting the first letter back.
- if (remaining_text_layout_object)
- element->ReattachLayoutTree();
- else
- GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
- return true;
- }
- return false;
-}
-
PseudoElement* Element::CreatePseudoElementIfNeeded(PseudoId pseudo_id) {
if (IsPseudoElement())
return nullptr;
if (!CanGeneratePseudoElement(pseudo_id))
return nullptr;
if (pseudo_id == kPseudoIdFirstLetter) {
- if (IsSVGElement())
- return nullptr;
if (!FirstLetterPseudoElement::FirstLetterTextLayoutObject(*this))
return nullptr;
}
PseudoElement* pseudo_element = PseudoElement::Create(this, pseudo_id);
EnsureElementRareData().SetPseudoElement(pseudo_id, pseudo_element);
- pseudo_element->InsertedInto(this);
+ pseudo_element->InsertedInto(*this);
scoped_refptr<ComputedStyle> pseudo_style =
pseudo_element->StyleForLayoutObject();
@@ -4077,12 +4112,6 @@ PseudoElement* Element::CreatePseudoElementIfNeeded(PseudoId pseudo_id) {
pseudo_element->SetNonAttachedStyle(std::move(pseudo_style));
- // TODO(futhark@chromium.org): We cannot SetNeedsReattachLayoutTree() for
- // ::first-letter inside CreatePseudoElementIfNeeded() because it may be
- // called from layout tree attachment.
- if (pseudo_id != kPseudoIdFirstLetter)
- pseudo_element->SetNeedsReattachLayoutTree();
-
probe::pseudoElementCreated(pseudo_element);
return pseudo_element;
@@ -4143,9 +4172,14 @@ scoped_refptr<ComputedStyle> Element::StyleForPseudoElement(
if (is_before_or_after) {
const ComputedStyle* layout_parent_style = style;
if (style->Display() == EDisplay::kContents) {
- Node* layout_parent = LayoutTreeBuilderTraversal::LayoutParent(*this);
- DCHECK(layout_parent);
- layout_parent_style = layout_parent->GetComputedStyle();
+ // TODO(futhark@chromium.org): Calling getComputedStyle for elements
+ // outside the flat tree should return empty styles, but currently we do
+ // not. See issue https://crbug.com/831568. We can replace the if-test
+ // with DCHECK(layout_parent) when that issue is fixed.
+ if (Node* layout_parent =
+ LayoutTreeBuilderTraversal::LayoutParent(*this)) {
+ layout_parent_style = layout_parent->GetComputedStyle();
+ }
}
return GetDocument().EnsureStyleResolver().PseudoStyleForElement(
this, request, style, layout_parent_style);
@@ -4169,6 +4203,8 @@ scoped_refptr<ComputedStyle> Element::StyleForPseudoElement(
bool Element::CanGeneratePseudoElement(PseudoId pseudo_id) const {
if (pseudo_id == kPseudoIdBackdrop && !IsInTopLayer())
return false;
+ if (pseudo_id == kPseudoIdFirstLetter && IsSVGElement())
+ return false;
if (const ComputedStyle* style = GetComputedStyle())
return style->CanGeneratePseudoElement(pseudo_id);
return false;
@@ -4469,9 +4505,9 @@ inline void Element::UpdateId(TreeScope& scope,
DCHECK_NE(old_id, new_id);
if (!old_id.IsEmpty())
- scope.RemoveElementById(old_id, this);
+ scope.RemoveElementById(old_id, *this);
if (!new_id.IsEmpty())
- scope.AddElementById(new_id, this);
+ scope.AddElementById(new_id, *this);
NamedItemType type = GetNamedItemType();
if (type == NamedItemType::kNameOrId ||
@@ -4689,37 +4725,37 @@ void Element::DetachAllAttrNodesFromElement() {
}
Node::InsertionNotificationRequest Node::InsertedInto(
- ContainerNode* insertion_point) {
+ ContainerNode& insertion_point) {
DCHECK(!ChildNeedsStyleInvalidation());
DCHECK(!NeedsStyleInvalidation());
- DCHECK(insertion_point->isConnected() || insertion_point->IsInShadowTree() ||
+ DCHECK(insertion_point.isConnected() || insertion_point.IsInShadowTree() ||
IsContainerNode());
- if (insertion_point->isConnected()) {
+ if (insertion_point.isConnected()) {
SetFlag(kIsConnectedFlag);
- insertion_point->GetDocument().IncrementNodeCount();
+ insertion_point.GetDocument().IncrementNodeCount();
}
if (ParentOrShadowHostNode()->IsInShadowTree())
SetFlag(kIsInShadowTreeFlag);
if (ChildNeedsDistributionRecalc() &&
- !insertion_point->ChildNeedsDistributionRecalc())
- insertion_point->MarkAncestorsWithChildNeedsDistributionRecalc();
+ !insertion_point.ChildNeedsDistributionRecalc())
+ insertion_point.MarkAncestorsWithChildNeedsDistributionRecalc();
if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
- cache->ChildrenChanged(insertion_point);
+ cache->ChildrenChanged(&insertion_point);
return kInsertionDone;
}
-void Node::RemovedFrom(ContainerNode* insertion_point) {
- DCHECK(insertion_point->isConnected() || IsContainerNode() ||
+void Node::RemovedFrom(ContainerNode& insertion_point) {
+ DCHECK(insertion_point.isConnected() || IsContainerNode() ||
IsInShadowTree());
- if (insertion_point->isConnected()) {
+ if (insertion_point.isConnected()) {
ClearFlag(kIsConnectedFlag);
- insertion_point->GetDocument().DecrementNodeCount();
+ insertion_point.GetDocument().DecrementNodeCount();
}
if (IsInShadowTree() && !ContainingTreeScope().RootNode().IsShadowRoot())
ClearFlag(kIsInShadowTreeFlag);
if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) {
cache->Remove(this);
- cache->ChildrenChanged(insertion_point);
+ cache->ChildrenChanged(&insertion_point);
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/element.h b/chromium/third_party/blink/renderer/core/dom/element.h
index f7d403771c1..7bf4971b625 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.h
+++ b/chromium/third_party/blink/renderer/core/dom/element.h
@@ -36,9 +36,9 @@
#include "third_party/blink/renderer/core/html/focus_options.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
+#include "third_party/blink/renderer/core/scroll/scroll_customization.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/scroll/scroll_customization.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -121,6 +121,7 @@ enum class NamedItemType {
struct FocusParams {
STACK_ALLOCATED();
+ public:
FocusParams() = default;
FocusParams(SelectionBehaviorOnFocus selection,
WebFocusType focus_type,
@@ -315,6 +316,12 @@ class CORE_EXPORT Element : public ContainerNode {
AccessibleNode* ExistingAccessibleNode() const;
AccessibleNode* accessibleNode();
+ const AtomicString& invisible() const;
+ void setInvisible(const AtomicString&);
+ void DispatchActivateInvisibleEventIfNeeded();
+
+ void DefaultEventHandler(Event&) override;
+
void DidMoveToNewDocument(Document&) override;
void removeAttribute(const AtomicString& name);
@@ -421,6 +428,8 @@ class CORE_EXPORT Element : public ContainerNode {
enum class AttributeModificationReason { kDirectly, kByParser, kByCloning };
struct AttributeModificationParams {
STACK_ALLOCATED();
+
+ public:
AttributeModificationParams(const QualifiedName& qname,
const AtomicString& old_value,
const AtomicString& new_value,
@@ -511,7 +520,8 @@ class CORE_EXPORT Element : public ContainerNode {
}
ShadowRoot& CreateUserAgentShadowRoot();
ShadowRoot& AttachShadowRootInternal(ShadowRootType,
- bool delegates_focus = false);
+ bool delegates_focus = false,
+ bool manual_slotting = false);
// Returns the shadow root attached to this element if it is a shadow host.
ShadowRoot* GetShadowRoot() const;
@@ -653,7 +663,8 @@ class CORE_EXPORT Element : public ContainerNode {
Element* new_focused_element,
InputDeviceCapabilities* source_capabilities = nullptr);
- virtual String innerText();
+ // The implementation of |innerText()| is found in "element_inner_text.cc".
+ String innerText();
String outerText();
String InnerHTMLAsString() const;
String OuterHTMLAsString() const;
@@ -894,8 +905,8 @@ class CORE_EXPORT Element : public ContainerNode {
CSSPropertyID,
const CSSValue&);
- InsertionNotificationRequest InsertedInto(ContainerNode*) override;
- void RemovedFrom(ContainerNode*) override;
+ InsertionNotificationRequest InsertedInto(ContainerNode&) override;
+ void RemovedFrom(ContainerNode&) override;
void ChildrenChanged(const ChildrenChange&) override;
virtual void WillRecalcStyle(StyleRecalcChange);
@@ -964,6 +975,8 @@ class CORE_EXPORT Element : public ContainerNode {
void InlineStyleChanged();
void SetInlineStyleFromString(const AtomicString&);
+ void InvisibleAttributeChanged();
+
// If the only inherited changes in the parent element are independent,
// these changes can be directly propagated to this element (the child).
// If these conditions are met, propagates the changes to the current style
@@ -977,12 +990,20 @@ class CORE_EXPORT Element : public ContainerNode {
bool ShouldCallRecalcStyleForChildren(StyleRecalcChange);
void RebuildPseudoElementLayoutTree(PseudoId, WhitespaceAttacher&);
+ void RebuildFirstLetterLayoutTree();
void RebuildShadowRootLayoutTree(WhitespaceAttacher&);
inline void CheckForEmptyStyleChange(const Node* node_before_change,
const Node* node_after_change);
void UpdatePseudoElement(PseudoId, StyleRecalcChange);
- bool UpdateFirstLetter(Element*);
+
+ enum class StyleUpdatePhase {
+ kRecalc,
+ kRebuildLayoutTree,
+ kAttachLayoutTree,
+ };
+
+ void UpdateFirstLetterPseudoElement(StyleUpdatePhase);
inline PseudoElement* CreatePseudoElementIfNeeded(PseudoId);
void AttachPseudoElement(PseudoId, AttachContext&);
diff --git a/chromium/third_party/blink/renderer/core/dom/element.idl b/chromium/third_party/blink/renderer/core/dom/element.idl
index 534f5d1b009..8c6d62d2c88 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.idl
+++ b/chromium/third_party/blink/renderer/core/dom/element.idl
@@ -125,7 +125,7 @@ interface Element : Node {
// Non-standard API
[MeasureAs=ElementScrollIntoViewIfNeeded] void scrollIntoViewIfNeeded(optional boolean centerIfNeeded);
- [RuntimeEnabled=ShadowDOMV0, RaisesException, MeasureAs=ElementCreateShadowRoot] ShadowRoot createShadowRoot();
+ [RuntimeEnabled=ShadowDOMV0, RaisesException, DeprecateAs=ElementCreateShadowRoot] ShadowRoot createShadowRoot();
[RuntimeEnabled=ShadowDOMV0] NodeList getDestinationInsertionPoints();
// Experimental accessibility API
@@ -135,6 +135,8 @@ interface Element : Node {
// Accessibility Object Model
[RuntimeEnabled=AccessibilityObjectModel] readonly attribute AccessibleNode? accessibleNode;
+ [RuntimeEnabled=InvisibleDOM, CEReactions, CustomElementCallbacks] attribute DOMString invisible;
+
// Event handler attributes
attribute EventHandler onbeforecopy;
attribute EventHandler onbeforecut;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
index 14706ed5ef7..902d22a3f91 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
+#include "third_party/blink/renderer/core/event_names.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.cc b/chromium/third_party/blink/renderer/core/dom/events/event.cc
index bd42170486b..6668b23470f 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event.cc
@@ -22,13 +22,17 @@
#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
+#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/dom/events/window_event_context.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/events/focus_event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/hosts_using_features.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
@@ -95,6 +99,7 @@ Event::Event(const AtomicString& event_type,
is_trusted_(false),
executed_listener_or_default_action_(false),
prevent_default_called_on_uncancelable_event_(false),
+ legacy_did_listeners_throw_flag_(false),
handling_passive_(PassiveMode::kNotPassiveDefault),
event_phase_(0),
current_target_(nullptr),
@@ -216,6 +221,10 @@ bool Event::IsCompositionEvent() const {
return false;
}
+bool Event::IsActivateInvisibleEvent() const {
+ return false;
+}
+
bool Event::IsClipboardEvent() const {
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.h b/chromium/third_party/blink/renderer/core/dom/events/event.h
index 6c95dcf8773..4175d84ac4d 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event.h
@@ -26,19 +26,17 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
-#include "third_party/blink/renderer/core/dom/dom_time_stamp.h"
-#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
-#include "third_party/blink/renderer/core/dom/events/event_init.h"
-#include "third_party/blink/renderer/core/dom/events/event_path.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
class DOMWrapperWorld;
+class EventDispatcher;
+class EventInit;
+class EventPath;
class EventTarget;
class ScriptState;
class ScriptValue;
@@ -190,6 +188,8 @@ class CORE_EXPORT Event : public ScriptWrappable {
virtual bool IsBeforeUnloadEvent() const;
+ virtual bool IsActivateInvisibleEvent() const;
+
bool PropagationStopped() const {
return propagation_stopped_ || immediate_propagation_stopped_;
}
@@ -259,6 +259,14 @@ class CORE_EXPORT Event : public ScriptWrappable {
executed_listener_or_default_action_ = true;
}
+ bool LegacyDidListenersThrow() const {
+ return legacy_did_listeners_throw_flag_;
+ }
+
+ void LegacySetDidListenersThrowFlag() {
+ legacy_did_listeners_throw_flag_ = true;
+ }
+
virtual DispatchEventResult DispatchEvent(EventDispatcher&);
void Trace(blink::Visitor*) override;
@@ -318,6 +326,12 @@ class CORE_EXPORT Event : public ScriptWrappable {
// Whether preventDefault was called on uncancelable event.
unsigned prevent_default_called_on_uncancelable_event_ : 1;
+ // Whether any of listeners have thrown an exception or not.
+ // Corresponds to |legacyOutputDidListenersThrowFlag| in DOM standard.
+ // https://dom.spec.whatwg.org/#dispatching-events
+ // https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke
+ unsigned legacy_did_listeners_throw_flag_ : 1;
+
PassiveMode handling_passive_;
unsigned short event_phase_;
Member<EventTarget> current_target_;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index 533a4ecef9b..2119960822a 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/events/window_event_context.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
@@ -49,27 +50,26 @@
namespace blink {
-DispatchEventResult EventDispatcher::DispatchEvent(Node& node, Event* event) {
+DispatchEventResult EventDispatcher::DispatchEvent(Node& node, Event& event) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.debug"),
"EventDispatcher::dispatchEvent");
#if DCHECK_IS_ON()
DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
#endif
EventDispatcher dispatcher(node, event);
- return event->DispatchEvent(dispatcher);
+ return event.DispatchEvent(dispatcher);
}
-EventDispatcher::EventDispatcher(Node& node, Event* event)
+EventDispatcher::EventDispatcher(Node& node, Event& event)
: node_(node), event_(event) {
- DCHECK(event_.Get());
view_ = node.GetDocument().View();
event_->InitEventPath(*node_);
}
-void EventDispatcher::DispatchScopedEvent(Node& node, Event* event) {
+void EventDispatcher::DispatchScopedEvent(Node& node, Event& event) {
// We need to set the target here because it can go away by the time we
// actually fire the event.
- event->SetTarget(EventPath::EventTargetRespectingTargetRules(node));
+ event.SetTarget(EventPath::EventTargetRespectingTargetRules(node));
ScopedEventQueue::Instance()->EnqueueEvent(event);
}
@@ -95,20 +95,20 @@ void EventDispatcher::DispatchSimulatedClick(
nodes_dispatching_simulated_clicks.insert(&node);
if (mouse_event_options == kSendMouseOverUpDownEvents)
- EventDispatcher(node, MouseEvent::Create(EventTypeNames::mouseover,
- node.GetDocument().domWindow(),
- underlying_event, creation_scope))
+ EventDispatcher(node, *MouseEvent::Create(EventTypeNames::mouseover,
+ node.GetDocument().domWindow(),
+ underlying_event, creation_scope))
.Dispatch();
if (mouse_event_options != kSendNoEvents) {
- EventDispatcher(node, MouseEvent::Create(EventTypeNames::mousedown,
- node.GetDocument().domWindow(),
- underlying_event, creation_scope))
+ EventDispatcher(node, *MouseEvent::Create(EventTypeNames::mousedown,
+ node.GetDocument().domWindow(),
+ underlying_event, creation_scope))
.Dispatch();
node.SetActive(true);
- EventDispatcher(node, MouseEvent::Create(EventTypeNames::mouseup,
- node.GetDocument().domWindow(),
- underlying_event, creation_scope))
+ EventDispatcher(node, *MouseEvent::Create(EventTypeNames::mouseup,
+ node.GetDocument().domWindow(),
+ underlying_event, creation_scope))
.Dispatch();
}
// Some elements (e.g. the color picker) may set active state to true before
@@ -116,9 +116,9 @@ void EventDispatcher::DispatchSimulatedClick(
node.SetActive(false);
// always send click
- EventDispatcher(node, MouseEvent::Create(EventTypeNames::click,
- node.GetDocument().domWindow(),
- underlying_event, creation_scope))
+ EventDispatcher(node, *MouseEvent::Create(EventTypeNames::click,
+ node.GetDocument().domWindow(),
+ underlying_event, creation_scope))
.Dispatch();
nodes_dispatching_simulated_clicks.erase(&node);
@@ -207,7 +207,7 @@ inline EventDispatchContinuation EventDispatcher::DispatchEventPreProcess(
// legacy-pre-activation behavior.
if (activation_target) {
pre_dispatch_event_handler_result =
- activation_target->PreDispatchEventHandler(event_.Get());
+ activation_target->PreDispatchEventHandler(*event_);
}
return (event_->GetEventPath().IsEmpty() || event_->PropagationStopped())
? kDoneDispatching
@@ -293,7 +293,7 @@ inline void EventDispatcher::DispatchEventPostProcess(
// This may dispatch an event, and node_ and event_ might be altered.
if (activation_target) {
activation_target->PostDispatchEventHandler(
- event_.Get(), pre_dispatch_event_handler_result);
+ *event_, pre_dispatch_event_handler_result);
}
// TODO(tkent): Is it safe to kick DefaultEventHandler() with such altered
// event_?
@@ -325,7 +325,7 @@ inline void EventDispatcher::DispatchEventPostProcess(
// Non-bubbling events call only one default event handler, the one for the
// target.
node_->WillCallDefaultEventHandler(*event_);
- node_->DefaultEventHandler(event_.Get());
+ node_->DefaultEventHandler(*event_);
DCHECK(!event_->defaultPrevented());
// For bubbling events, call default event handlers on the same targets in
// the same order as the bubbling phase.
@@ -334,7 +334,7 @@ inline void EventDispatcher::DispatchEventPostProcess(
for (size_t i = 1; i < size; ++i) {
event_->GetEventPath()[i].GetNode()->WillCallDefaultEventHandler(
*event_);
- event_->GetEventPath()[i].GetNode()->DefaultEventHandler(event_.Get());
+ event_->GetEventPath()[i].GetNode()->DefaultEventHandler(*event_);
DCHECK(!event_->defaultPrevented());
if (event_->DefaultHandled())
break;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h
index 5504bea4c64..e09e49f4584 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h
@@ -52,8 +52,8 @@ class EventDispatcher {
STACK_ALLOCATED();
public:
- static DispatchEventResult DispatchEvent(Node&, Event*);
- static void DispatchScopedEvent(Node&, Event*);
+ static DispatchEventResult DispatchEvent(Node&, Event&);
+ static void DispatchScopedEvent(Node&, Event&);
static void DispatchSimulatedClick(Node&,
Event* underlying_event,
@@ -65,7 +65,7 @@ class EventDispatcher {
Event& GetEvent() const { return *event_; }
private:
- EventDispatcher(Node&, Event*);
+ EventDispatcher(Node&, Event&);
EventDispatchContinuation DispatchEventPreProcess(
Node* activation_target,
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_listener.h b/chromium/third_party/blink/renderer/core/dom/events/event_listener.h
index 018acd55347..70942bb3d21 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_listener.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_listener.h
@@ -21,6 +21,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_H_
+#include "third_party/blink/renderer/bindings/core/v8/custom_wrappable_adapter.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -28,12 +29,11 @@
namespace blink {
+class DOMWrapperWorld;
class Event;
class ExecutionContext;
-class CORE_EXPORT EventListener
- : public GarbageCollectedFinalized<EventListener>,
- public NameClient {
+class CORE_EXPORT EventListener : public CustomWrappableAdapter {
public:
enum ListenerType {
kJSEventListenerType,
@@ -42,7 +42,7 @@ class CORE_EXPORT EventListener
kConditionEventListenerType,
};
- virtual ~EventListener() = default;
+ ~EventListener() override = default;
virtual bool operator==(const EventListener&) const = 0;
virtual void handleEvent(ExecutionContext*, Event*) = 0;
virtual const String& Code() const { return g_empty_string; }
@@ -52,9 +52,18 @@ class CORE_EXPORT EventListener
}
virtual bool IsAttribute() const { return false; }
+ // Only DevTools is allowed to use this method.
+ // This method may return an empty handle.
+ virtual v8::Local<v8::Object> GetListenerObjectForInspector(
+ ExecutionContext* execution_context) {
+ return v8::Local<v8::Object>();
+ }
+
+ // Only DevTools is allowed to use this method.
+ virtual DOMWrapperWorld* GetWorldForInspector() const { return nullptr; }
+
ListenerType GetType() const { return type_; }
- virtual void Trace(blink::Visitor* visitor) {}
const char* NameInHeapSnapshot() const override { return "EventListener"; }
protected:
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc
index f7c8c459c89..d4c14740d3c 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/dom/events/event_listener_map.h"
+#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_path.cc b/chromium/third_party/blink/renderer/core/dom/events/event_path.cc
index 1f29d1b8562..fecad3ad96c 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_path.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_path.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/window_event_context.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
#include "third_party/blink/renderer/core/event_names.h"
@@ -101,7 +102,7 @@ void EventPath::CalculatePath() {
nodes_in_path.push_back(current);
while (current) {
- if (event_ && current->KeepEventInNode(event_))
+ if (event_ && current->KeepEventInNode(*event_))
break;
HeapVector<Member<V0InsertionPoint>, 8> insertion_points;
CollectDestinationInsertionPoints(*current, insertion_points);
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_path.h b/chromium/third_party/blink/renderer/core/dom/events/event_path.h
index e66ea981547..27754e73c0b 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_path.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_path.h
@@ -31,10 +31,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/node_event_context.h"
#include "third_party/blink/renderer/core/dom/events/tree_scope_event_context.h"
-#include "third_party/blink/renderer/core/dom/events/window_event_context.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -44,6 +41,7 @@ class Node;
class TouchEvent;
class TouchList;
class TreeScope;
+class WindowEventContext;
class CORE_EXPORT EventPath final
: public GarbageCollectedFinalized<EventPath> {
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc b/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc
index 53166a98285..78bea34c911 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc
@@ -53,16 +53,16 @@ void EventQueue::Trace(blink::Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-bool EventQueue::EnqueueEvent(const base::Location& from_here, Event* event) {
+bool EventQueue::EnqueueEvent(const base::Location& from_here, Event& event) {
if (is_closed_)
return false;
- DCHECK(event->target());
+ DCHECK(event.target());
DCHECK(GetExecutionContext());
- probe::AsyncTaskScheduled(GetExecutionContext(), event->type(), event);
+ probe::AsyncTaskScheduled(GetExecutionContext(), event.type(), &event);
- bool was_added = queued_events_.insert(event).is_new_entry;
+ bool was_added = queued_events_.insert(&event).is_new_entry;
DCHECK(was_added); // It should not have already been in the list.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
@@ -72,7 +72,7 @@ bool EventQueue::EnqueueEvent(const base::Location& from_here, Event* event) {
// object like IDBTransaction as soon as possible.
task_runner->PostTask(
FROM_HERE, WTF::Bind(&EventQueue::DispatchEvent, WrapPersistent(this),
- WrapWeakPersistent(event)));
+ WrapWeakPersistent(&event)));
return true;
}
@@ -85,8 +85,8 @@ void EventQueue::CancelAllEvents() {
DoCancelAllEvents(GetExecutionContext());
}
-bool EventQueue::RemoveEvent(Event* event) {
- auto found = queued_events_.find(event);
+bool EventQueue::RemoveEvent(Event& event) {
+ auto found = queued_events_.find(&event);
if (found == queued_events_.end())
return false;
queued_events_.erase(found);
@@ -94,7 +94,7 @@ bool EventQueue::RemoveEvent(Event* event) {
}
void EventQueue::DispatchEvent(Event* event) {
- if (!event || !RemoveEvent(event))
+ if (!event || !RemoveEvent(*event))
return;
DCHECK(GetExecutionContext());
@@ -102,9 +102,9 @@ void EventQueue::DispatchEvent(Event* event) {
probe::AsyncTask async_task(GetExecutionContext(), event);
EventTarget* target = event->target();
if (LocalDOMWindow* window = target->ToLocalDOMWindow())
- window->DispatchEvent(event, nullptr);
+ window->DispatchEvent(*event, nullptr);
else
- target->DispatchEvent(event);
+ target->DispatchEvent(*event);
}
void EventQueue::ContextDestroyed(ExecutionContext* context) {
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_queue.h b/chromium/third_party/blink/renderer/core/dom/events/event_queue.h
index cc446451d61..1906634e688 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_queue.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_queue.h
@@ -46,14 +46,14 @@ class CORE_EXPORT EventQueue final
~EventQueue();
void Trace(blink::Visitor*) override;
- bool EnqueueEvent(const base::Location&, Event*);
+ bool EnqueueEvent(const base::Location&, Event&);
void CancelAllEvents();
bool HasPendingEvents() const;
private:
EventQueue(ExecutionContext*, TaskType);
- bool RemoveEvent(Event*);
+ bool RemoveEvent(Event&);
void DispatchEvent(Event*);
void ContextDestroyed(ExecutionContext*) override;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target.cc b/chromium/third_party/blink/renderer/core/dom/events/event_target.cc
index e934b6afe4e..80ceabc0900 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_target.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_target.cc
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/bindings/core/v8/event_listener_options_or_boolean.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/event_target_impl.h"
@@ -97,10 +98,14 @@ bool IsTouchScrollBlockingEvent(const AtomicString& event_type) {
event_type == EventTypeNames::touchmove;
}
+bool IsWheelScrollBlockingEvent(const AtomicString& event_type) {
+ return event_type == EventTypeNames::mousewheel ||
+ event_type == EventTypeNames::wheel;
+}
+
bool IsScrollBlockingEvent(const AtomicString& event_type) {
return IsTouchScrollBlockingEvent(event_type) ||
- event_type == EventTypeNames::mousewheel ||
- event_type == EventTypeNames::wheel;
+ IsWheelScrollBlockingEvent(event_type);
}
bool IsInstrumentedForAsyncStack(const AtomicString& event_type) {
@@ -109,17 +114,17 @@ bool IsInstrumentedForAsyncStack(const AtomicString& event_type) {
}
base::TimeDelta BlockedEventsWarningThreshold(ExecutionContext* context,
- const Event* event) {
- if (!event->cancelable())
+ const Event& event) {
+ if (!event.cancelable())
return base::TimeDelta();
- if (!IsScrollBlockingEvent(event->type()))
+ if (!IsScrollBlockingEvent(event.type()))
return base::TimeDelta();
return PerformanceMonitor::Threshold(context,
PerformanceMonitor::kBlockedEvent);
}
void ReportBlockedEvent(ExecutionContext* context,
- const Event* event,
+ const Event& event,
RegisteredEventListener* registered_listener,
base::TimeDelta delayed) {
if (registered_listener->Callback()->GetType() !=
@@ -131,7 +136,7 @@ void ReportBlockedEvent(ExecutionContext* context,
" ms due to main thread being busy. "
"Consider marking event handler as 'passive' to make the page more "
"responsive.",
- event->type().GetString().Utf8().data(), delayed.InMilliseconds());
+ event.type().GetString().Utf8().data(), delayed.InMilliseconds());
PerformanceMonitor::ReportGenericViolation(
context, PerformanceMonitor::kBlockedEvent, message_text, delayed,
@@ -141,11 +146,11 @@ void ReportBlockedEvent(ExecutionContext* context,
// UseCounts the event if it has the specified type. Returns true iff the event
// type matches.
-bool CheckTypeThenUseCount(const Event* event,
+bool CheckTypeThenUseCount(const Event& event,
const AtomicString& event_type_to_count,
const WebFeature feature,
const Document* document) {
- if (event->type() != event_type_to_count)
+ if (event.type() != event_type_to_count)
return false;
UseCounter::Count(*document, feature);
return true;
@@ -208,6 +213,22 @@ inline LocalDOMWindow* EventTarget::ExecutingWindow() {
return nullptr;
}
+bool EventTarget::IsTopLevelNode() {
+ if (ToLocalDOMWindow())
+ return true;
+
+ Node* node = ToNode();
+ if (!node)
+ return false;
+
+ if (node->IsDocumentNode() || node->GetDocument().documentElement() == node ||
+ node->GetDocument().body() == node) {
+ return true;
+ }
+
+ return false;
+}
+
void EventTarget::SetDefaultAddEventListenerOptions(
const AtomicString& event_type,
EventListener* event_listener,
@@ -232,16 +253,29 @@ void EventTarget::SetDefaultAddEventListenerOptions(
if (RuntimeEnabledFeatures::PassiveDocumentEventListenersEnabled() &&
IsTouchScrollBlockingEvent(event_type)) {
- if (!options.hasPassive()) {
- if (Node* node = ToNode()) {
- if (node->IsDocumentNode() ||
- node->GetDocument().documentElement() == node ||
- node->GetDocument().body() == node) {
- options.setPassive(true);
- options.SetPassiveForcedForDocumentTarget(true);
- return;
- }
- } else if (ToLocalDOMWindow()) {
+ if (!options.hasPassive() && IsTopLevelNode()) {
+ options.setPassive(true);
+ options.SetPassiveForcedForDocumentTarget(true);
+ return;
+ }
+ }
+
+ if (IsWheelScrollBlockingEvent(event_type) && IsTopLevelNode()) {
+ if (options.hasPassive()) {
+ if (executing_window) {
+ UseCounter::Count(
+ executing_window->document(),
+ options.passive()
+ ? WebFeature::kAddDocumentLevelPassiveTrueWheelEventListener
+ : WebFeature::kAddDocumentLevelPassiveFalseWheelEventListener);
+ }
+ } else { // !options.hasPassive()
+ if (executing_window) {
+ UseCounter::Count(
+ executing_window->document(),
+ WebFeature::kAddDocumentLevelPassiveDefaultWheelEventListener);
+ }
+ if (RuntimeEnabledFeatures::PassiveDocumentWheelEventListenersEnabled()) {
options.setPassive(true);
options.SetPassiveForcedForDocumentTarget(true);
return;
@@ -544,40 +578,38 @@ bool EventTarget::dispatchEventForBindings(Event* event,
// Return whether the event was cancelled or not to JS not that it
// might have actually been default handled; so check only against
// CanceledByEventHandler.
- return DispatchEventInternal(event) !=
+ return DispatchEventInternal(*event) !=
DispatchEventResult::kCanceledByEventHandler;
}
-DispatchEventResult EventTarget::DispatchEvent(Event* event) {
- event->SetTrusted(true);
+DispatchEventResult EventTarget::DispatchEvent(Event& event) {
+ event.SetTrusted(true);
return DispatchEventInternal(event);
}
-DispatchEventResult EventTarget::DispatchEventInternal(Event* event) {
- event->SetTarget(this);
- event->SetCurrentTarget(this);
- event->SetEventPhase(Event::kAtTarget);
+DispatchEventResult EventTarget::DispatchEventInternal(Event& event) {
+ event.SetTarget(this);
+ event.SetCurrentTarget(this);
+ event.SetEventPhase(Event::kAtTarget);
DispatchEventResult dispatch_result = FireEventListeners(event);
- event->SetEventPhase(0);
+ event.SetEventPhase(0);
return dispatch_result;
}
-void EventTarget::UncaughtExceptionInEventHandler() {}
-
-static const AtomicString& LegacyType(const Event* event) {
- if (event->type() == EventTypeNames::transitionend)
+static const AtomicString& LegacyType(const Event& event) {
+ if (event.type() == EventTypeNames::transitionend)
return EventTypeNames::webkitTransitionEnd;
- if (event->type() == EventTypeNames::animationstart)
+ if (event.type() == EventTypeNames::animationstart)
return EventTypeNames::webkitAnimationStart;
- if (event->type() == EventTypeNames::animationend)
+ if (event.type() == EventTypeNames::animationend)
return EventTypeNames::webkitAnimationEnd;
- if (event->type() == EventTypeNames::animationiteration)
+ if (event.type() == EventTypeNames::animationiteration)
return EventTypeNames::webkitAnimationIteration;
- if (event->type() == EventTypeNames::wheel)
+ if (event.type() == EventTypeNames::wheel)
return EventTypeNames::mousewheel;
return g_empty_atom;
@@ -632,12 +664,11 @@ void EventTarget::CountLegacyEvents(
}
}
-DispatchEventResult EventTarget::FireEventListeners(Event* event) {
+DispatchEventResult EventTarget::FireEventListeners(Event& event) {
#if DCHECK_IS_ON()
DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
#endif
- DCHECK(event);
- DCHECK(event->WasInitialized());
+ DCHECK(event.WasInitialized());
EventTargetData* d = GetEventTargetData();
if (!d)
@@ -649,33 +680,33 @@ DispatchEventResult EventTarget::FireEventListeners(Event* event) {
legacy_listeners_vector = d->event_listener_map.Find(legacy_type_name);
EventListenerVector* listeners_vector =
- d->event_listener_map.Find(event->type());
+ d->event_listener_map.Find(event.type());
bool fired_event_listeners = false;
if (listeners_vector) {
fired_event_listeners = FireEventListeners(event, d, *listeners_vector);
- } else if (event->isTrusted() && legacy_listeners_vector) {
- AtomicString unprefixed_type_name = event->type();
- event->SetType(legacy_type_name);
+ } else if (event.isTrusted() && legacy_listeners_vector) {
+ AtomicString unprefixed_type_name = event.type();
+ event.SetType(legacy_type_name);
fired_event_listeners =
FireEventListeners(event, d, *legacy_listeners_vector);
- event->SetType(unprefixed_type_name);
+ event.SetType(unprefixed_type_name);
}
// Only invoke the callback if event listeners were fired for this phase.
if (fired_event_listeners) {
- event->DoneDispatchingEventAtCurrentTarget();
- event->SetExecutedListenerOrDefaultAction();
+ event.DoneDispatchingEventAtCurrentTarget();
+ event.SetExecutedListenerOrDefaultAction();
// Only count uma metrics if we really fired an event listener.
Editor::CountEvent(GetExecutionContext(), event);
CountLegacyEvents(legacy_type_name, listeners_vector,
legacy_listeners_vector);
}
- return GetDispatchEventResult(*event);
+ return GetDispatchEventResult(event);
}
-bool EventTarget::FireEventListeners(Event* event,
+bool EventTarget::FireEventListeners(Event& event,
EventTargetData* d,
EventListenerVector& entry) {
// Fire all listeners registered for this event. Don't fire listeners removed
@@ -721,8 +752,8 @@ bool EventTarget::FireEventListeners(Event* event,
} else if (CheckTypeThenUseCount(event, EventTypeNames::pointerdown,
WebFeature::kPointerDownFired,
document)) {
- if (event->IsPointerEvent() &&
- static_cast<PointerEvent*>(event)->pointerType() == "touch") {
+ if (event.IsPointerEvent() &&
+ static_cast<PointerEvent&>(event).pointerType() == "touch") {
UseCounter::Count(*document, WebFeature::kPointerDownFiredForTouch);
}
} else if (CheckTypeThenUseCount(event, EventTypeNames::pointerenter,
@@ -737,8 +768,8 @@ bool EventTarget::FireEventListeners(Event* event,
} else if (CheckTypeThenUseCount(event, EventTypeNames::pointerout,
WebFeature::kPointerOverOutFired,
document)) {
- } else if (event->eventPhase() == Event::kCapturingPhase ||
- event->eventPhase() == Event::kBubblingPhase) {
+ } else if (event.eventPhase() == Event::kCapturingPhase ||
+ event.eventPhase() == Event::kBubblingPhase) {
if (CheckTypeThenUseCount(
event, EventTypeNames::DOMNodeRemoved,
WebFeature::kDOMNodeRemovedEventListenedAtNonTarget,
@@ -762,7 +793,7 @@ bool EventTarget::FireEventListeners(Event* event,
if (!d->firing_event_iterators)
d->firing_event_iterators = std::make_unique<FiringEventIteratorVector>();
d->firing_event_iterators->push_back(
- FiringEventIterator(event->type(), i, size));
+ FiringEventIterator(event.type(), i, size));
base::TimeDelta blocked_event_threshold =
BlockedEventsWarningThreshold(context, event);
@@ -771,7 +802,7 @@ bool EventTarget::FireEventListeners(Event* event,
if (!blocked_event_threshold.is_zero()) {
now = CurrentTimeTicks();
should_report_blocked_event =
- now - event->PlatformTimeStamp() > blocked_event_threshold;
+ now - event.PlatformTimeStamp() > blocked_event_threshold;
}
bool fired_listener = false;
@@ -783,10 +814,10 @@ bool EventTarget::FireEventListeners(Event* event,
// EventTarget::removeEventListener.
++i;
- if (event->eventPhase() == Event::kCapturingPhase &&
+ if (event.eventPhase() == Event::kCapturingPhase &&
!registered_listener.Capture())
continue;
- if (event->eventPhase() == Event::kBubblingPhase &&
+ if (event.eventPhase() == Event::kBubblingPhase &&
registered_listener.Capture())
continue;
@@ -795,25 +826,24 @@ bool EventTarget::FireEventListeners(Event* event,
// registeredListener, i and size are updated with the firing event iterator
// in case the listener is removed from the listener vector below.
if (registered_listener.Once())
- removeEventListener(event->type(), listener,
+ removeEventListener(event.type(), listener,
registered_listener.Capture());
// If stopImmediatePropagation has been called, we just break out
// immediately, without handling any more events on this target.
- if (event->ImmediatePropagationStopped())
+ if (event.ImmediatePropagationStopped())
break;
- event->SetHandlingPassive(EventPassiveMode(registered_listener));
+ event.SetHandlingPassive(EventPassiveMode(registered_listener));
bool passive_forced = registered_listener.PassiveForcedForDocumentTarget();
- probe::UserCallback probe(context, nullptr, event->type(), false, this);
- probe::AsyncTask async_task(
- context, V8AbstractEventListener::Cast(listener), "event",
- IsInstrumentedForAsyncStack(event->type()));
+ probe::UserCallback probe(context, nullptr, event.type(), false, this);
+ probe::AsyncTask async_task(context, listener, "event",
+ IsInstrumentedForAsyncStack(event.type()));
// To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
// event listeners, even though that violates some versions of the DOM spec.
- listener->handleEvent(context, event);
+ listener->handleEvent(context, &event);
fired_listener = true;
// If we're about to report this event listener as blocking, make sure it
@@ -821,9 +851,9 @@ bool EventTarget::FireEventListeners(Event* event,
if (should_report_blocked_event && i > 0 &&
entry[i - 1].Callback() == listener && !entry[i - 1].Passive() &&
!entry[i - 1].BlockedEventWarningEmitted() &&
- !event->defaultPrevented()) {
+ !event.defaultPrevented()) {
ReportBlockedEvent(context, event, &entry[i - 1],
- now - event->PlatformTimeStamp());
+ now - event.PlatformTimeStamp());
}
if (passive_forced) {
@@ -831,13 +861,13 @@ bool EventTarget::FireEventListeners(Event* event,
("Event.PassiveForcedEventDispatchCancelled",
kPassiveForcedListenerResultTypeMax));
PassiveForcedListenerResultType breakage_type = kPreventDefaultNotCalled;
- if (event->PreventDefaultCalledDuringPassive())
+ if (event.PreventDefaultCalledDuringPassive())
breakage_type = kDocumentLevelTouchPreventDefaultCalled;
passive_forced_histogram.Count(breakage_type);
}
- event->SetHandlingPassive(Event::PassiveMode::kNotPassive);
+ event.SetHandlingPassive(Event::PassiveMode::kNotPassive);
CHECK_LE(i, size);
}
@@ -882,15 +912,15 @@ void EventTarget::RemoveAllEventListeners() {
}
}
-void EventTarget::EnqueueEvent(Event* event, TaskType task_type) {
+void EventTarget::EnqueueEvent(Event& event, TaskType task_type) {
ExecutionContext* context = GetExecutionContext();
if (!context)
return;
- probe::AsyncTaskScheduled(context, event->type(), event);
+ probe::AsyncTaskScheduled(context, event.type(), &event);
context->GetTaskRunner(task_type)->PostTask(
FROM_HERE,
WTF::Bind(&EventTarget::DispatchEnqueuedEvent, WrapPersistent(this),
- WrapPersistent(event), WrapPersistent(context)));
+ WrapPersistent(&event), WrapPersistent(context)));
}
void EventTarget::DispatchEnqueuedEvent(Event* event,
@@ -900,7 +930,7 @@ void EventTarget::DispatchEnqueuedEvent(Event* event,
return;
}
probe::AsyncTask async_task(context, event);
- DispatchEvent(event);
+ DispatchEvent(*event);
}
STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kFalse,
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target.h b/chromium/third_party/blink/renderer/core/dom/events/event_target.h
index eb021cc39e2..f8f2d5fa709 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_target.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_target.h
@@ -55,6 +55,7 @@ class DOMWindow;
class Event;
class EventListenerOptionsOrBoolean;
class ExceptionState;
+class ExecutionContext;
class LocalDOMWindow;
class MessagePort;
class Node;
@@ -153,15 +154,14 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
EventListenerOptions&);
virtual void RemoveAllEventListeners();
- DispatchEventResult DispatchEvent(Event*);
+ DispatchEventResult DispatchEvent(Event&);
- void EnqueueEvent(Event*, TaskType);
+ void EnqueueEvent(Event&, TaskType);
// dispatchEventForBindings is intended to only be called from
// javascript originated calls. This method will validate and may adjust
// the Event object before dispatching.
bool dispatchEventForBindings(Event*, ExceptionState&);
- virtual void UncaughtExceptionInEventHandler();
// Used for legacy "onEvent" attribute APIs.
bool SetAttributeEventListener(const AtomicString& event_type,
@@ -174,11 +174,15 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
EventListenerVector* GetEventListeners(const AtomicString& event_type);
Vector<AtomicString> EventTypes();
- DispatchEventResult FireEventListeners(Event*);
+ DispatchEventResult FireEventListeners(Event&);
static DispatchEventResult GetDispatchEventResult(const Event&);
- virtual bool KeepEventInNode(Event*) { return false; }
+ virtual bool KeepEventInNode(const Event&) const { return false; }
+
+ // Returns true if the target is window, window.document, or
+ // window.document.body.
+ bool IsTopLevelNode();
protected:
EventTarget();
@@ -199,7 +203,7 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
virtual void RemovedEventListener(const AtomicString& event_type,
const RegisteredEventListener&);
- virtual DispatchEventResult DispatchEventInternal(Event*);
+ virtual DispatchEventResult DispatchEventInternal(Event&);
// Subclasses should likely not override these themselves; instead, they
// should subclass EventTargetWithInlineData.
@@ -215,7 +219,7 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
RegisteredEventListener* GetAttributeRegisteredEventListener(
const AtomicString& event_type);
- bool FireEventListeners(Event*, EventTargetData*, EventListenerVector&);
+ bool FireEventListeners(Event&, EventTargetData*, EventListenerVector&);
void CountLegacyEvents(const AtomicString& legacy_type_name,
EventListenerVector*,
EventListenerVector*);
diff --git a/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc b/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc
index af89d3ba474..fc03321c529 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc
@@ -55,7 +55,7 @@ void ScopedEventQueue::Initialize() {
instance_ = instance.release();
}
-void ScopedEventQueue::EnqueueEvent(Event* event) {
+void ScopedEventQueue::EnqueueEvent(Event& event) {
if (ShouldQueueEvents())
queued_events_.push_back(event);
else
@@ -67,12 +67,12 @@ void ScopedEventQueue::DispatchAllEvents() {
queued_events.swap(queued_events_);
for (auto& event : queued_events)
- DispatchEvent(event);
+ DispatchEvent(*event);
}
-void ScopedEventQueue::DispatchEvent(Event* event) const {
- DCHECK(event->target());
- Node* node = event->target()->ToNode();
+void ScopedEventQueue::DispatchEvent(Event& event) const {
+ DCHECK(event.target());
+ Node* node = event.target()->ToNode();
EventDispatcher::DispatchEvent(*node, event);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.h b/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.h
index e91711d6e6a..a90b9a0188c 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/scoped_event_queue.h
@@ -46,7 +46,7 @@ class CORE_EXPORT ScopedEventQueue {
public:
~ScopedEventQueue();
- void EnqueueEvent(Event*);
+ void EnqueueEvent(Event&);
static ScopedEventQueue* Instance();
void IncrementScopingLevel();
@@ -57,7 +57,7 @@ class CORE_EXPORT ScopedEventQueue {
ScopedEventQueue();
static void Initialize();
void DispatchAllEvents();
- void DispatchEvent(Event*) const;
+ void DispatchEvent(Event&) const;
PersistentHeapVector<Member<Event>> queued_events_;
unsigned scoping_level_;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc b/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc
index d5171971b5d..866c2a6d20d 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc
@@ -27,9 +27,11 @@
#include "third_party/blink/renderer/core/dom/events/tree_scope_event_context.h"
#include "third_party/blink/renderer/core/dom/events/event_path.h"
+#include "third_party/blink/renderer/core/dom/events/window_event_context.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/events/touch_event_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/dom/events/window_event_context.cc b/chromium/third_party/blink/renderer/core/dom/events/window_event_context.cc
index ebddd9b5663..cf6ac7fe210 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/window_event_context.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/window_event_context.cc
@@ -53,7 +53,7 @@ bool WindowEventContext::HandleLocalEvents(Event& event) {
event.SetTarget(Target());
event.SetCurrentTarget(Window());
- window_->FireEventListeners(&event);
+ window_->FireEventListeners(event);
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/events/window_event_context.h b/chromium/third_party/blink/renderer/core/dom/events/window_event_context.h
index ffc31ba0f56..133a6096df6 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/window_event_context.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/window_event_context.h
@@ -28,14 +28,13 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_WINDOW_EVENT_CONTEXT_H_
#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
class EventTarget;
class Event;
+class LocalDOMWindow;
class NodeEventContext;
class WindowEventContext : public GarbageCollected<WindowEventContext> {
diff --git a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
index ca96e0d1f9a..70d6fc35a7e 100644
--- a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
@@ -26,11 +26,13 @@
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/layout/generated_children.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -94,7 +96,7 @@ static bool IsInvalidFirstLetterLayoutObject(const LayoutObject* obj) {
return (obj->IsBR() || (obj->IsText() && ToLayoutText(obj)->IsWordBreak()));
}
-LayoutObject* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
+LayoutText* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
const Element& element) {
LayoutObject* parent_layout_object = nullptr;
@@ -113,6 +115,10 @@ LayoutObject* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
!parent_layout_object->BehavesLikeBlockContainer())
return nullptr;
+ LayoutObject* marker =
+ parent_layout_object->IsLayoutNGListItem()
+ ? ToLayoutNGListItem(parent_layout_object)->Marker()
+ : nullptr;
// Drill down into our children and look for our first text child.
LayoutObject* first_letter_text_layout_object =
parent_layout_object->SlowFirstChild();
@@ -139,7 +145,8 @@ LayoutObject* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
break;
first_letter_text_layout_object =
first_letter_text_layout_object->NextSibling();
- } else if (first_letter_text_layout_object->IsListMarker()) {
+ } else if (first_letter_text_layout_object->IsListMarker() ||
+ first_letter_text_layout_object == marker) {
first_letter_text_layout_object =
first_letter_text_layout_object->NextSibling();
} else if (first_letter_text_layout_object
@@ -170,6 +177,9 @@ LayoutObject* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
// setting up the first letter then.
return nullptr;
} else {
+ if (first_letter_text_layout_object->IsLayoutNGListItem())
+ marker = ToLayoutNGListItem(first_letter_text_layout_object)->Marker();
+
first_letter_text_layout_object =
first_letter_text_layout_object->SlowFirstChild();
}
@@ -184,7 +194,7 @@ LayoutObject* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
IsInvalidFirstLetterLayoutObject(first_letter_text_layout_object))
return nullptr;
- return first_letter_text_layout_object;
+ return ToLayoutText(first_letter_text_layout_object);
}
FirstLetterPseudoElement::FirstLetterPseudoElement(Element* parent)
@@ -241,8 +251,10 @@ void FirstLetterPseudoElement::SetRemainingTextLayoutObject(
}
void FirstLetterPseudoElement::AttachLayoutTree(AttachContext& context) {
+ LayoutText* first_letter_text =
+ FirstLetterPseudoElement::FirstLetterTextLayoutObject(*this);
PseudoElement::AttachLayoutTree(context);
- AttachFirstLetterTextLayoutObjects();
+ AttachFirstLetterTextLayoutObjects(first_letter_text);
}
void FirstLetterPseudoElement::DetachLayoutTree(const AttachContext& context) {
@@ -260,51 +272,28 @@ void FirstLetterPseudoElement::DetachLayoutTree(const AttachContext& context) {
PseudoElement::DetachLayoutTree(context);
}
-ComputedStyle* FirstLetterPseudoElement::StyleForFirstLetter(
- LayoutObject* layout_object_container) {
- DCHECK(layout_object_container);
-
- LayoutObject* style_container =
- ParentOrShadowHostElement()->GetLayoutObject();
- DCHECK(style_container);
-
- // We always force the pseudo style to recompute as the first-letter style
- // computed by the style container may not have taken the layoutObjects styles
- // into account.
- style_container->MutableStyle()->RemoveCachedPseudoStyle(
- kPseudoIdFirstLetter);
-
- ComputedStyle* pseudo_style = style_container->GetCachedPseudoStyle(
- kPseudoIdFirstLetter, layout_object_container->FirstLineStyle());
- DCHECK(pseudo_style);
- pseudo_style->UpdateIsStackingContext(false /* is_document_element */,
- false /* is_in_top_layer */,
- false /* is_svg_stacking */);
- return pseudo_style;
+scoped_refptr<ComputedStyle>
+FirstLetterPseudoElement::CustomStyleForLayoutObject() {
+ LayoutObject* first_letter_text =
+ FirstLetterPseudoElement::FirstLetterTextLayoutObject(*this);
+ if (!first_letter_text)
+ return nullptr;
+ DCHECK(first_letter_text->Parent());
+ return ParentOrShadowHostElement()->StyleForPseudoElement(
+ PseudoStyleRequest(GetPseudoId()),
+ first_letter_text->Parent()->FirstLineStyle());
}
-void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects() {
- LayoutObject* next_layout_object =
- FirstLetterPseudoElement::FirstLetterTextLayoutObject(*this);
- DCHECK(next_layout_object);
- DCHECK(next_layout_object->IsText());
+void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects(LayoutText* first_letter_text) {
+ DCHECK(first_letter_text);
// The original string is going to be either a generated content string or a
// DOM node's string. We want the original string before it got transformed in
// case first-letter has no text-transform or a different text-transform
// applied to it.
- String old_text =
- ToLayoutText(next_layout_object)->IsTextFragment()
- ? ToLayoutTextFragment(next_layout_object)->CompleteText()
- : ToLayoutText(next_layout_object)->OriginalText();
+ String old_text = first_letter_text->IsTextFragment() ? ToLayoutTextFragment(first_letter_text)->CompleteText() : first_letter_text->OriginalText();
DCHECK(old_text.Impl());
- // :first-letter inherits from the parent of the text. It may not be
- // this->Parent() when e.g., <div><span>text</span></div>.
- ComputedStyle* pseudo_style =
- StyleForFirstLetter(next_layout_object->Parent());
- GetLayoutObject()->SetStyle(pseudo_style);
-
// FIXME: This would already have been calculated in firstLetterLayoutObject.
// Can we pass the length through?
unsigned length = FirstLetterPseudoElement::FirstLetterLength(old_text);
@@ -314,9 +303,9 @@ void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects() {
// This text fragment might be empty.
LayoutTextFragment* remaining_text;
- if (next_layout_object->GetNode()) {
+ if (first_letter_text->GetNode()) {
remaining_text =
- new LayoutTextFragment(next_layout_object->GetNode(), old_text.Impl(),
+ new LayoutTextFragment(first_letter_text->GetNode(), old_text.Impl(),
length, remaining_length);
} else {
remaining_text = LayoutTextFragment::CreateAnonymous(
@@ -325,7 +314,7 @@ void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects() {
remaining_text->SetFirstLetterPseudoElement(this);
remaining_text->SetIsRemainingTextLayoutObject(true);
- remaining_text->SetStyle(next_layout_object->MutableStyle());
+ remaining_text->SetStyle(first_letter_text->MutableStyle());
if (remaining_text->GetNode())
remaining_text->GetNode()->SetLayoutObject(remaining_text);
@@ -339,10 +328,10 @@ void FirstLetterPseudoElement::AttachFirstLetterTextLayoutObjects() {
LayoutTextFragment* letter =
LayoutTextFragment::CreateAnonymous(*this, old_text.Impl(), 0, length);
letter->SetFirstLetterPseudoElement(this);
- letter->SetStyle(pseudo_style);
+ letter->SetStyle(MutableComputedStyle());
GetLayoutObject()->AddChild(letter);
- next_layout_object->Destroy();
+ first_letter_text->Destroy();
}
void FirstLetterPseudoElement::DidRecalcStyle(StyleRecalcChange) {
@@ -350,30 +339,15 @@ void FirstLetterPseudoElement::DidRecalcStyle(StyleRecalcChange) {
if (!layout_object)
return;
- // :first-letter inherits from the parent of the text. It may not be
- // this->Parent() when e.g., <div><span>text</span></div>.
- DCHECK(remaining_text_layout_object_);
- ComputedStyle* pseudo_style =
- StyleForFirstLetter(remaining_text_layout_object_->Parent());
- DCHECK(pseudo_style);
- // TODO(kojii): While setting to GetLayoutObject() looks correct all the time,
- // as we do so in AttachFirstLetterTextLayoutObjects(), it is required only
- // when inline box has text children, and can break layout tree when changing
- // :first-letter to floats. The check in Element::UpdatePseudoElement() does
- // not catch all such cases.
- if (!pseudo_style->IsDisplayBlockContainer())
- layout_object->SetStyle(pseudo_style);
-
- // The layoutObjects inside pseudo elements are anonymous so they don't get
- // notified of recalcStyle and must have
- // the style propagated downward manually similar to
- // LayoutObject::propagateStyleToAnonymousChildren.
+ // The layout objects inside pseudo elements are anonymous so they don't get
+ // notified of RecalcStyle and must have the style propagated downward
+ // manually similar to LayoutObject::PropagateStyleToAnonymousChildren.
for (LayoutObject* child = layout_object->NextInPreOrder(layout_object);
child; child = child->NextInPreOrder(layout_object)) {
// We need to re-calculate the correct style for the first letter element
// and then apply that to the container and the text fragment inside.
if (child->Style()->StyleType() == kPseudoIdFirstLetter) {
- child->SetPseudoStyle(pseudo_style);
+ child->SetPseudoStyle(layout_object->MutableStyle());
continue;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h
index d2794b029cd..6c8b5b1ccf8 100644
--- a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h
+++ b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.h
@@ -33,7 +33,7 @@
namespace blink {
class Element;
-class LayoutObject;
+class LayoutText;
class LayoutTextFragment;
class CORE_EXPORT FirstLetterPseudoElement final : public PseudoElement {
@@ -44,7 +44,7 @@ class CORE_EXPORT FirstLetterPseudoElement final : public PseudoElement {
~FirstLetterPseudoElement() override;
- static LayoutObject* FirstLetterTextLayoutObject(const Element&);
+ static LayoutText* FirstLetterTextLayoutObject(const Element&);
static unsigned FirstLetterLength(const String&);
void SetRemainingTextLayoutObject(LayoutTextFragment*);
@@ -60,10 +60,10 @@ class CORE_EXPORT FirstLetterPseudoElement final : public PseudoElement {
private:
explicit FirstLetterPseudoElement(Element*);
+ scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() override;
void DidRecalcStyle(StyleRecalcChange) override;
- void AttachFirstLetterTextLayoutObjects();
- ComputedStyle* StyleForFirstLetter(LayoutObject*);
+ void AttachFirstLetterTextLayoutObjects(LayoutText* first_letter_text);
LayoutTextFragment* remaining_text_layout_object_;
DISALLOW_COPY_AND_ASSIGN(FirstLetterPseudoElement);
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc
index 35b1842e3c6..f98a8b5775a 100644
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc
@@ -32,42 +32,36 @@
namespace blink {
+bool CanBeDistributedToV0InsertionPoint(const Node& node) {
+ return node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost();
+}
+
Node* FlatTreeTraversal::TraverseChild(const Node& node,
TraversalDirection direction) {
+ if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(node)) {
+ if (slot->AssignedNodes().IsEmpty()) {
+ return direction == kTraversalDirectionForward ? slot->firstChild()
+ : slot->lastChild();
+ }
+ return direction == kTraversalDirectionForward ? slot->FirstAssignedNode()
+ : slot->LastAssignedNode();
+ }
+ Node* child;
if (ShadowRoot* shadow_root = node.GetShadowRoot()) {
- return ResolveDistributionStartingAt(direction == kTraversalDirectionForward
- ? shadow_root->firstChild()
- : shadow_root->lastChild(),
- direction);
+ child = direction == kTraversalDirectionForward ? shadow_root->firstChild()
+ : shadow_root->lastChild();
+ } else {
+ child = direction == kTraversalDirectionForward ? node.firstChild()
+ : node.lastChild();
}
- return ResolveDistributionStartingAt(direction == kTraversalDirectionForward
- ? node.firstChild()
- : node.lastChild(),
- direction);
-}
-Node* FlatTreeTraversal::ResolveDistributionStartingAt(
- const Node* node,
- TraversalDirection direction) {
- if (!node)
+ if (!child)
return nullptr;
- for (const Node* sibling = node; sibling;
- sibling = (direction == kTraversalDirectionForward
- ? sibling->nextSibling()
- : sibling->previousSibling())) {
- if (const HTMLSlotElement* slot =
- ToHTMLSlotElementIfSupportsAssignmentOrNull(*sibling)) {
- if (Node* found = (direction == kTraversalDirectionForward
- ? slot->FirstDistributedNode()
- : slot->LastDistributedNode()))
- return found;
- continue;
- }
- if (node->IsInV0ShadowTree())
- return V0ResolveDistributionStartingAt(*sibling, direction);
- return const_cast<Node*>(sibling);
+
+ if (child->IsInV0ShadowTree()) {
+ return V0ResolveDistributionStartingAt(*child, direction);
}
- return nullptr;
+ return child;
}
Node* FlatTreeTraversal::V0ResolveDistributionStartingAt(
@@ -103,35 +97,29 @@ Node* FlatTreeTraversal::TraverseSiblings(const Node& node,
if (ShadowRootWhereNodeCanBeDistributedForV0(node))
return TraverseSiblingsForV0Distribution(node, direction);
- if (Node* found = ResolveDistributionStartingAt(
- direction == kTraversalDirectionForward ? node.nextSibling()
- : node.previousSibling(),
- direction))
- return found;
+ Node* sibling = direction == kTraversalDirectionForward
+ ? node.nextSibling()
+ : node.previousSibling();
- // Slotted nodes are already handled in traverseSiblingsForV1HostChild()
- // above, here is for fallback contents.
- if (auto* slot =
- ToHTMLSlotElementIfSupportsAssignmentOrNull(node.parentElement())) {
- if (slot->AssignedNodes().IsEmpty())
- return TraverseSiblings(*slot, direction);
- }
+ if (!node.IsInV0ShadowTree())
+ return sibling;
+ if (sibling) {
+ if (Node* found = V0ResolveDistributionStartingAt(*sibling, direction))
+ return found;
+ }
return nullptr;
}
Node* FlatTreeTraversal::TraverseSiblingsForV1HostChild(
const Node& node,
TraversalDirection direction) {
- HTMLSlotElement* slot = node.FinalDestinationSlot();
+ HTMLSlotElement* slot = node.AssignedSlot();
if (!slot)
return nullptr;
- if (Node* sibling_in_distributed_nodes =
- (direction == kTraversalDirectionForward
- ? slot->DistributedNodeNextTo(node)
- : slot->DistributedNodePreviousTo(node)))
- return sibling_in_distributed_nodes;
- return TraverseSiblings(*slot, direction);
+ return direction == kTraversalDirectionForward
+ ? slot->AssignedNodeNextTo(node)
+ : slot->AssignedNodePreviousTo(node);
}
Node* FlatTreeTraversal::TraverseSiblingsForV0Distribution(
@@ -155,18 +143,14 @@ ContainerNode* FlatTreeTraversal::TraverseParent(
if (node.IsPseudoElement())
return node.ParentOrShadowHostNode();
- if (node.IsChildOfV1ShadowHost()) {
- HTMLSlotElement* slot = node.FinalDestinationSlot();
- if (!slot)
- return nullptr;
- return TraverseParent(*slot);
- }
+ if (node.IsChildOfV1ShadowHost())
+ return node.AssignedSlot();
- if (auto* slot =
+ if (auto* parent_slot =
ToHTMLSlotElementIfSupportsAssignmentOrNull(node.parentElement())) {
- if (!slot->AssignedNodes().IsEmpty())
+ if (!parent_slot->AssignedNodes().IsEmpty())
return nullptr;
- return TraverseParent(*slot, details);
+ return parent_slot;
}
if (CanBeDistributedToV0InsertionPoint(node))
@@ -208,8 +192,6 @@ ContainerNode* FlatTreeTraversal::TraverseParentOrHost(const Node& node) {
}
Node* FlatTreeTraversal::ChildAt(const Node& node, unsigned index) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::ChildAt(node, index);
AssertPrecondition(node);
Node* child = TraverseFirstChild(node);
while (child && index--)
@@ -219,8 +201,6 @@ Node* FlatTreeTraversal::ChildAt(const Node& node, unsigned index) {
}
Node* FlatTreeTraversal::NextSkippingChildren(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::NextSkippingChildren(node);
if (Node* next_sibling = TraverseNextSibling(node))
return next_sibling;
return TraverseNextAncestorSibling(node);
@@ -229,8 +209,6 @@ Node* FlatTreeTraversal::NextSkippingChildren(const Node& node) {
bool FlatTreeTraversal::ContainsIncludingPseudoElement(
const ContainerNode& container,
const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::ContainsIncludingPseudoElement(container, node);
AssertPrecondition(container);
AssertPrecondition(node);
// This can be slower than FlatTreeTraversal::contains() because we
@@ -244,8 +222,6 @@ bool FlatTreeTraversal::ContainsIncludingPseudoElement(
}
Node* FlatTreeTraversal::PreviousSkippingChildren(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::PreviousSkippingChildren(node);
if (Node* previous_sibling = TraversePreviousSibling(node))
return previous_sibling;
return TraversePreviousAncestorSibling(node);
@@ -269,8 +245,6 @@ Node* FlatTreeTraversal::PreviousAncestorSiblingPostOrder(
// between DOM tree traversal and flat tree tarversal.
Node* FlatTreeTraversal::PreviousPostOrder(const Node& current,
const Node* stay_within) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::PreviousPostOrder(current, stay_within);
AssertPrecondition(current);
if (stay_within)
AssertPrecondition(*stay_within);
@@ -288,8 +262,6 @@ Node* FlatTreeTraversal::PreviousPostOrder(const Node& current,
}
bool FlatTreeTraversal::IsDescendantOf(const Node& node, const Node& other) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::IsDescendantOf(node, other);
AssertPrecondition(node);
AssertPrecondition(other);
if (!HasChildren(other) || node.isConnected() != other.isConnected())
@@ -304,8 +276,6 @@ bool FlatTreeTraversal::IsDescendantOf(const Node& node, const Node& other) {
Node* FlatTreeTraversal::CommonAncestor(const Node& node_a,
const Node& node_b) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::CommonAncestor(node_a, node_b);
AssertPrecondition(node_a);
AssertPrecondition(node_b);
Node* result = node_a.CommonAncestor(
@@ -335,8 +305,6 @@ Node* FlatTreeTraversal::TraversePreviousAncestorSibling(const Node& node) {
}
unsigned FlatTreeTraversal::Index(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::Index(node);
AssertPrecondition(node);
unsigned count = 0;
for (Node* runner = TraversePreviousSibling(node); runner;
@@ -346,8 +314,6 @@ unsigned FlatTreeTraversal::Index(const Node& node) {
}
unsigned FlatTreeTraversal::CountChildren(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::CountChildren(node);
AssertPrecondition(node);
unsigned count = 0;
for (Node* runner = TraverseFirstChild(node); runner;
@@ -357,8 +323,6 @@ unsigned FlatTreeTraversal::CountChildren(const Node& node) {
}
Node* FlatTreeTraversal::LastWithin(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::LastWithin(node);
AssertPrecondition(node);
Node* descendant = TraverseLastChild(node);
for (Node* child = descendant; child; child = LastChild(*child))
@@ -368,8 +332,6 @@ Node* FlatTreeTraversal::LastWithin(const Node& node) {
}
Node& FlatTreeTraversal::LastWithinOrSelf(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::LastWithinOrSelf(node);
AssertPrecondition(node);
Node* last_descendant = LastWithin(node);
Node& result = last_descendant ? *last_descendant : const_cast<Node&>(node);
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h
index 829bde11117..31054b6bba6 100644
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -41,6 +40,8 @@ namespace blink {
class ContainerNode;
class Node;
+bool CanBeDistributedToV0InsertionPoint(const Node& node);
+
// Flat tree version of |NodeTraversal|.
//
// None of member functions takes a |ShadowRoot| or an active insertion point,
@@ -48,9 +49,6 @@ class Node;
// |InsertionPoint::isActive()| for details of active insertion points, since
// they aren't appeared in the flat tree. |assertPrecondition()| and
// |assertPostCondition()| check this condition.
-//
-// FIXME: Make some functions inline to optimise the performance.
-// https://bugs.webkit.org/show_bug.cgi?id=82702
class CORE_EXPORT FlatTreeTraversal {
STATIC_ONLY(FlatTreeTraversal);
@@ -98,8 +96,6 @@ class CORE_EXPORT FlatTreeTraversal {
static bool IsDescendantOf(const Node& /*node*/, const Node& other);
static bool Contains(const ContainerNode& container, const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::Contains(container, node);
AssertPrecondition(container);
AssertPrecondition(node);
return container == node || IsDescendantOf(node, container);
@@ -194,8 +190,6 @@ class CORE_EXPORT FlatTreeTraversal {
inline ContainerNode* FlatTreeTraversal::Parent(
const Node& node,
ParentTraversalDetails* details) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::Parent(node, details);
AssertPrecondition(node);
ContainerNode* result = TraverseParent(node, details);
AssertPostcondition(result);
@@ -203,15 +197,11 @@ inline ContainerNode* FlatTreeTraversal::Parent(
}
inline Element* FlatTreeTraversal::ParentElement(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::ParentElement(node);
ContainerNode* parent = FlatTreeTraversal::Parent(node);
return parent && parent->IsElementNode() ? ToElement(parent) : nullptr;
}
inline Node* FlatTreeTraversal::NextSibling(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::NextSibling(node);
AssertPrecondition(node);
Node* result = TraverseSiblings(node, kTraversalDirectionForward);
AssertPostcondition(result);
@@ -219,8 +209,6 @@ inline Node* FlatTreeTraversal::NextSibling(const Node& node) {
}
inline Node* FlatTreeTraversal::PreviousSibling(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::PreviousSibling(node);
AssertPrecondition(node);
Node* result = TraverseSiblings(node, kTraversalDirectionBackward);
AssertPostcondition(result);
@@ -228,8 +216,6 @@ inline Node* FlatTreeTraversal::PreviousSibling(const Node& node) {
}
inline Node* FlatTreeTraversal::Next(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::Next(node);
AssertPrecondition(node);
Node* result = TraverseNext(node);
AssertPostcondition(result);
@@ -238,8 +224,6 @@ inline Node* FlatTreeTraversal::Next(const Node& node) {
inline Node* FlatTreeTraversal::Next(const Node& node,
const Node* stay_within) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::Next(node, stay_within);
AssertPrecondition(node);
Node* result = TraverseNext(node, stay_within);
AssertPostcondition(result);
@@ -248,8 +232,6 @@ inline Node* FlatTreeTraversal::Next(const Node& node,
inline Node* FlatTreeTraversal::NextSkippingChildren(const Node& node,
const Node* stay_within) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::NextSkippingChildren(node, stay_within);
AssertPrecondition(node);
Node* result = TraverseNextSkippingChildren(node, stay_within);
AssertPostcondition(result);
@@ -286,8 +268,6 @@ inline Node* FlatTreeTraversal::TraverseNextSkippingChildren(
}
inline Node* FlatTreeTraversal::Previous(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::Previous(node);
AssertPrecondition(node);
Node* result = TraversePrevious(node);
AssertPostcondition(result);
@@ -304,8 +284,6 @@ inline Node* FlatTreeTraversal::TraversePrevious(const Node& node) {
}
inline Node* FlatTreeTraversal::FirstChild(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::FirstChild(node);
AssertPrecondition(node);
Node* result = TraverseChild(node, kTraversalDirectionForward);
AssertPostcondition(result);
@@ -313,8 +291,6 @@ inline Node* FlatTreeTraversal::FirstChild(const Node& node) {
}
inline Node* FlatTreeTraversal::LastChild(const Node& node) {
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled())
- return FlatTreeTraversalNg::LastChild(node);
AssertPrecondition(node);
Node* result = TraverseLastChild(node);
AssertPostcondition(result);
@@ -360,4 +336,4 @@ FlatTreeTraversal::InclusiveAncestorsOf(const Node& node) {
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc
deleted file mode 100644
index c6500a0c739..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h"
-
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/html/html_shadow_element.h"
-#include "third_party/blink/renderer/core/html/html_slot_element.h"
-
-namespace blink {
-
-bool CanBeDistributedToV0InsertionPoint(const Node& node) {
- return node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost();
-}
-
-Node* FlatTreeTraversalNg::TraverseChild(const Node& node,
- TraversalDirection direction) {
- if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(node)) {
- if (slot->AssignedNodes().IsEmpty()) {
- return direction == kTraversalDirectionForward ? slot->firstChild()
- : slot->lastChild();
- }
- return direction == kTraversalDirectionForward ? slot->FirstAssignedNode()
- : slot->LastAssignedNode();
- }
-
- Node* child;
- if (ShadowRoot* shadow_root = node.GetShadowRoot()) {
- child = direction == kTraversalDirectionForward ? shadow_root->firstChild()
- : shadow_root->lastChild();
- } else {
- child = direction == kTraversalDirectionForward ? node.firstChild()
- : node.lastChild();
- }
-
- if (!child)
- return nullptr;
-
- if (child->IsInV0ShadowTree()) {
- return V0ResolveDistributionStartingAt(*child, direction);
- }
- return child;
-}
-
-// This needs only for v0
-// Node* FlatTreeTraversalNg::ResolveDistributionStartingAt(
-// const Node* node,
-// TraversalDirection direction) {
-// if (!node)
-// return nullptr;
-// for (const Node* sibling = node; sibling;
-// sibling = (direction == kTraversalDirectionForward
-// ? sibling->nextSibling()
-// : sibling->previousSibling())) {
-// if (node->IsInV0ShadowTree())
-// return V0ResolveDistributionStartingAt(*sibling, direction);
-// return const_cast<Node*>(sibling);
-// }
-// return nullptr;
-// }
-
-Node* FlatTreeTraversalNg::V0ResolveDistributionStartingAt(
- const Node& node,
- TraversalDirection direction) {
- DCHECK(!ToHTMLSlotElementIfSupportsAssignmentOrNull(node));
- for (const Node* sibling = &node; sibling;
- sibling = (direction == kTraversalDirectionForward
- ? sibling->nextSibling()
- : sibling->previousSibling())) {
- if (!IsActiveV0InsertionPoint(*sibling))
- return const_cast<Node*>(sibling);
- const V0InsertionPoint& insertion_point = ToV0InsertionPoint(*sibling);
- if (Node* found = (direction == kTraversalDirectionForward
- ? insertion_point.FirstDistributedNode()
- : insertion_point.LastDistributedNode()))
- return found;
- DCHECK(IsHTMLShadowElement(insertion_point) ||
- (IsHTMLContentElement(insertion_point) &&
- !insertion_point.HasChildren()));
- }
- return nullptr;
-}
-
-// TODO(hayato): This may return a wrong result for a node which is not in a
-// document flat tree. See FlatTreeTraversalNgTest's redistribution test for
-// details.
-Node* FlatTreeTraversalNg::TraverseSiblings(const Node& node,
- TraversalDirection direction) {
- if (node.IsChildOfV1ShadowHost())
- return TraverseSiblingsForV1HostChild(node, direction);
-
- if (ShadowRootWhereNodeCanBeDistributedForV0(node))
- return TraverseSiblingsForV0Distribution(node, direction);
-
- Node* sibling = direction == kTraversalDirectionForward
- ? node.nextSibling()
- : node.previousSibling();
-
- if (!node.IsInV0ShadowTree())
- return sibling;
-
- if (sibling) {
- if (Node* found = V0ResolveDistributionStartingAt(*sibling, direction))
- return found;
- }
-
- // // Slotted nodes are already handled in traverseSiblingsForV1HostChild()
- // // above, here is for fallback contents.
- // if (auto* slot = ToHTMLSlotElementOrNull(node.parentElement())) {
- // if (slot->SupportsAssignment() && slot->AssignedNodes().IsEmpty())
- // return TraverseSiblings(*slot, direction);
- // }
- return nullptr;
-}
-
-Node* FlatTreeTraversalNg::TraverseSiblingsForV1HostChild(
- const Node& node,
- TraversalDirection direction) {
- HTMLSlotElement* slot = node.AssignedSlot();
- if (!slot)
- return nullptr;
- return direction == kTraversalDirectionForward
- ? slot->AssignedNodeNextTo(node)
- : slot->AssignedNodePreviousTo(node);
-}
-
-Node* FlatTreeTraversalNg::TraverseSiblingsForV0Distribution(
- const Node& node,
- TraversalDirection direction) {
- const V0InsertionPoint* final_destination = ResolveReprojection(&node);
- if (!final_destination)
- return nullptr;
- if (Node* found = (direction == kTraversalDirectionForward
- ? final_destination->DistributedNodeNextTo(&node)
- : final_destination->DistributedNodePreviousTo(&node)))
- return found;
- return TraverseSiblings(*final_destination, direction);
-}
-
-ContainerNode* FlatTreeTraversalNg::TraverseParent(
- const Node& node,
- ParentTraversalDetails* details) {
- // TODO(hayato): Stop this hack for a pseudo element because a pseudo element
- // is not a child of its parentOrShadowHostNode() in a flat tree.
- if (node.IsPseudoElement())
- return node.ParentOrShadowHostNode();
-
- if (node.IsChildOfV1ShadowHost())
- return node.AssignedSlot();
-
- if (auto* parent_slot =
- ToHTMLSlotElementIfSupportsAssignmentOrNull(node.parentElement())) {
- if (!parent_slot->AssignedNodes().IsEmpty())
- return nullptr;
- return parent_slot;
- }
-
- if (CanBeDistributedToV0InsertionPoint(node))
- return TraverseParentForV0(node, details);
-
- DCHECK(!ShadowRootWhereNodeCanBeDistributedForV0(node));
- return TraverseParentOrHost(node);
-}
-
-ContainerNode* FlatTreeTraversalNg::TraverseParentForV0(
- const Node& node,
- ParentTraversalDetails* details) {
- if (ShadowRootWhereNodeCanBeDistributedForV0(node)) {
- if (const V0InsertionPoint* insertion_point = ResolveReprojection(&node)) {
- if (details)
- details->DidTraverseInsertionPoint(insertion_point);
- // The node is distributed. But the distribution was stopped at this
- // insertion point.
- if (ShadowRootWhereNodeCanBeDistributedForV0(*insertion_point))
- return nullptr;
- return TraverseParent(*insertion_point);
- }
- return nullptr;
- }
- ContainerNode* parent = TraverseParentOrHost(node);
- if (IsActiveV0InsertionPoint(*parent))
- return nullptr;
- return parent;
-}
-
-ContainerNode* FlatTreeTraversalNg::TraverseParentOrHost(const Node& node) {
- ContainerNode* parent = node.parentNode();
- if (!parent)
- return nullptr;
- if (!parent->IsShadowRoot())
- return parent;
- ShadowRoot* shadow_root = ToShadowRoot(parent);
- return &shadow_root->host();
-}
-
-Node* FlatTreeTraversalNg::ChildAt(const Node& node, unsigned index) {
- AssertPrecondition(node);
- Node* child = TraverseFirstChild(node);
- while (child && index--)
- child = NextSibling(*child);
- AssertPostcondition(child);
- return child;
-}
-
-Node* FlatTreeTraversalNg::NextSkippingChildren(const Node& node) {
- if (Node* next_sibling = TraverseNextSibling(node))
- return next_sibling;
- return TraverseNextAncestorSibling(node);
-}
-
-bool FlatTreeTraversalNg::ContainsIncludingPseudoElement(
- const ContainerNode& container,
- const Node& node) {
- AssertPrecondition(container);
- AssertPrecondition(node);
- // This can be slower than FlatTreeTraversalNg::contains() because we
- // can't early exit even when container doesn't have children.
- for (const Node* current = &node; current;
- current = TraverseParent(*current)) {
- if (current == &container)
- return true;
- }
- return false;
-}
-
-Node* FlatTreeTraversalNg::PreviousSkippingChildren(const Node& node) {
- if (Node* previous_sibling = TraversePreviousSibling(node))
- return previous_sibling;
- return TraversePreviousAncestorSibling(node);
-}
-
-Node* FlatTreeTraversalNg::PreviousAncestorSiblingPostOrder(
- const Node& current,
- const Node* stay_within) {
- DCHECK(!FlatTreeTraversalNg::PreviousSibling(current));
- for (Node* parent = FlatTreeTraversalNg::Parent(current); parent;
- parent = FlatTreeTraversalNg::Parent(*parent)) {
- if (parent == stay_within)
- return nullptr;
- if (Node* previous_sibling = FlatTreeTraversalNg::PreviousSibling(*parent))
- return previous_sibling;
- }
- return nullptr;
-}
-
-// TODO(yosin) We should consider introducing template class to share code
-// between DOM tree traversal and flat tree tarversal.
-Node* FlatTreeTraversalNg::PreviousPostOrder(const Node& current,
- const Node* stay_within) {
- AssertPrecondition(current);
- if (stay_within)
- AssertPrecondition(*stay_within);
- if (Node* last_child = TraverseLastChild(current)) {
- AssertPostcondition(last_child);
- return last_child;
- }
- if (current == stay_within)
- return nullptr;
- if (Node* previous_sibling = TraversePreviousSibling(current)) {
- AssertPostcondition(previous_sibling);
- return previous_sibling;
- }
- return PreviousAncestorSiblingPostOrder(current, stay_within);
-}
-
-bool FlatTreeTraversalNg::IsDescendantOf(const Node& node, const Node& other) {
- AssertPrecondition(node);
- AssertPrecondition(other);
- if (!HasChildren(other) || node.isConnected() != other.isConnected())
- return false;
- for (const ContainerNode* n = TraverseParent(node); n;
- n = TraverseParent(*n)) {
- if (n == other)
- return true;
- }
- return false;
-}
-
-Node* FlatTreeTraversalNg::CommonAncestor(const Node& node_a,
- const Node& node_b) {
- AssertPrecondition(node_a);
- AssertPrecondition(node_b);
- Node* result = node_a.CommonAncestor(node_b, [](const Node& node) {
- return FlatTreeTraversalNg::Parent(node);
- });
- AssertPostcondition(result);
- return result;
-}
-
-Node* FlatTreeTraversalNg::TraverseNextAncestorSibling(const Node& node) {
- DCHECK(!TraverseNextSibling(node));
- for (Node* parent = TraverseParent(node); parent;
- parent = TraverseParent(*parent)) {
- if (Node* next_sibling = TraverseNextSibling(*parent))
- return next_sibling;
- }
- return nullptr;
-}
-
-Node* FlatTreeTraversalNg::TraversePreviousAncestorSibling(const Node& node) {
- DCHECK(!TraversePreviousSibling(node));
- for (Node* parent = TraverseParent(node); parent;
- parent = TraverseParent(*parent)) {
- if (Node* previous_sibling = TraversePreviousSibling(*parent))
- return previous_sibling;
- }
- return nullptr;
-}
-
-unsigned FlatTreeTraversalNg::Index(const Node& node) {
- AssertPrecondition(node);
- unsigned count = 0;
- for (Node* runner = TraversePreviousSibling(node); runner;
- runner = PreviousSibling(*runner))
- ++count;
- return count;
-}
-
-unsigned FlatTreeTraversalNg::CountChildren(const Node& node) {
- AssertPrecondition(node);
- unsigned count = 0;
- for (Node* runner = TraverseFirstChild(node); runner;
- runner = TraverseNextSibling(*runner))
- ++count;
- return count;
-}
-
-Node* FlatTreeTraversalNg::LastWithin(const Node& node) {
- AssertPrecondition(node);
- Node* descendant = TraverseLastChild(node);
- for (Node* child = descendant; child; child = LastChild(*child))
- descendant = child;
- AssertPostcondition(descendant);
- return descendant;
-}
-
-Node& FlatTreeTraversalNg::LastWithinOrSelf(const Node& node) {
- AssertPrecondition(node);
- Node* last_descendant = LastWithin(node);
- Node& result = last_descendant ? *last_descendant : const_cast<Node&>(node);
- AssertPostcondition(&result);
- return result;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h
deleted file mode 100644
index bb93d2a749f..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_NG_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_NG_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
-#include "third_party/blink/renderer/core/dom/node_traversal.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class ContainerNode;
-class Node;
-
-bool CanBeDistributedToV0InsertionPoint(const Node& node);
-
-// Flat tree version of |NodeTraversal|.
-//
-// None of member functions takes a |ShadowRoot| or an active insertion point,
-// e.g. roughly speaking <content> and <shadow> in the shadow tree, see
-// |InsertionPoint::isActive()| for details of active insertion points, since
-// they aren't appeared in the flat tree. |assertPrecondition()| and
-// |assertPostCondition()| check this condition.
-//
-// FIXME: Make some functions inline to optimise the performance.
-// https://bugs.webkit.org/show_bug.cgi?id=82702
-class CORE_EXPORT FlatTreeTraversalNg {
- STATIC_ONLY(FlatTreeTraversalNg);
-
- public:
- typedef LayoutTreeBuilderTraversal::ParentDetails ParentTraversalDetails;
- using TraversalNodeType = Node;
-
- static Node* Next(const Node&);
- static Node* Next(const Node&, const Node* stay_within);
- static Node* Previous(const Node&);
-
- static Node* FirstChild(const Node&);
- static Node* LastChild(const Node&);
- static bool HasChildren(const Node&);
-
- static ContainerNode* Parent(const Node&, ParentTraversalDetails* = nullptr);
- static Element* ParentElement(const Node&);
-
- static Node* NextSibling(const Node&);
- static Node* PreviousSibling(const Node&);
-
- // Returns a child node at |index|. If |index| is greater than or equal to
- // the children, this function returns |nullptr|.
- static Node* ChildAt(const Node&, unsigned index);
-
- // Flat tree version of |NodeTraversal::nextSkippingChildren()|. This
- // function is similar to |next()| but skips child nodes of a specified
- // node.
- static Node* NextSkippingChildren(const Node&);
- static Node* NextSkippingChildren(const Node&, const Node* stay_within);
-
- static Node* FirstWithin(const Node& current) { return FirstChild(current); }
-
- // Flat tree version of |NodeTraversal::previousSkippingChildren()|
- // similar to |previous()| but skipping child nodes of the specified node.
- static Node* PreviousSkippingChildren(const Node&);
-
- // Like previous, but visits parents before their children.
- static Node* PreviousPostOrder(const Node&,
- const Node* stay_within = nullptr);
-
- // Flat tree version of |Node::isDescendantOf(other)|. This function
- // returns true if |other| contains |node|, otherwise returns
- // false. If |other| is |node|, this function returns false.
- static bool IsDescendantOf(const Node& /*node*/, const Node& other);
-
- static bool Contains(const ContainerNode& container, const Node& node) {
- AssertPrecondition(container);
- AssertPrecondition(node);
- return container == node || IsDescendantOf(node, container);
- }
-
- static bool ContainsIncludingPseudoElement(const ContainerNode&, const Node&);
-
- // Returns a common ancestor of |nodeA| and |nodeB| if exists, otherwise
- // returns |nullptr|.
- static Node* CommonAncestor(const Node& node_a, const Node& node_b);
-
- // Flat tree version of |Node::nodeIndex()|. This function returns a
- // zero base position number of the specified node in child nodes list, or
- // zero if the specified node has no parent.
- static unsigned Index(const Node&);
-
- // Flat tree version of |ContainerNode::countChildren()|. This function
- // returns the number of the child nodes of the specified node in the
- // flat tree.
- static unsigned CountChildren(const Node&);
-
- static Node* LastWithin(const Node&);
- static Node& LastWithinOrSelf(const Node&);
-
- // Flat tree range helper functions for range based for statement.
- // TODO(dom-team): We should have following functions to match with
- // |NodeTraversal|:
- // - AncestorsOf()
- // - DescendantsOf()
- // - InclusiveAncestorsOf()
- // - InclusiveDescendantsOf()
- // - StartsAt()
- // - StartsAfter()
- static TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
- ChildrenOf(const Node&);
-
- private:
- enum TraversalDirection {
- kTraversalDirectionForward,
- kTraversalDirectionBackward
- };
-
- static void AssertPrecondition(const Node& node) {
- DCHECK(!node.NeedsDistributionRecalc());
- DCHECK(node.CanParticipateInFlatTree());
- }
-
- static void AssertPostcondition(const Node* node) {
-#if DCHECK_IS_ON()
- if (node)
- AssertPrecondition(*node);
-#endif
- }
-
- // static Node* ResolveDistributionStartingAt(const Node*,
- // TraversalDirection);
- static Node* V0ResolveDistributionStartingAt(const Node&, TraversalDirection);
-
- static Node* TraverseNext(const Node&);
- static Node* TraverseNext(const Node&, const Node* stay_within);
- static Node* TraverseNextSkippingChildren(const Node&,
- const Node* stay_within);
- static Node* TraversePrevious(const Node&);
-
- static Node* TraverseFirstChild(const Node&);
- static Node* TraverseLastChild(const Node&);
- static Node* TraverseChild(const Node&, TraversalDirection);
-
- static ContainerNode* TraverseParent(const Node&,
- ParentTraversalDetails* = nullptr);
- // TODO(hayato): Make ParentTraversalDetails be aware of slot elements too.
- static ContainerNode* TraverseParentForV0(const Node&,
- ParentTraversalDetails* = nullptr);
- static ContainerNode* TraverseParentOrHost(const Node&);
-
- static Node* TraverseNextSibling(const Node&);
- static Node* TraversePreviousSibling(const Node&);
-
- static Node* TraverseSiblings(const Node&, TraversalDirection);
- static Node* TraverseSiblingsForV1HostChild(const Node&, TraversalDirection);
- static Node* TraverseSiblingsForV0Distribution(const Node&,
- TraversalDirection);
-
- static Node* TraverseNextAncestorSibling(const Node&);
- static Node* TraversePreviousAncestorSibling(const Node&);
- static Node* PreviousAncestorSiblingPostOrder(const Node& current,
- const Node* stay_within);
-};
-
-inline ContainerNode* FlatTreeTraversalNg::Parent(
- const Node& node,
- ParentTraversalDetails* details) {
- AssertPrecondition(node);
- ContainerNode* result = TraverseParent(node, details);
- AssertPostcondition(result);
- return result;
-}
-
-inline Element* FlatTreeTraversalNg::ParentElement(const Node& node) {
- ContainerNode* parent = FlatTreeTraversalNg::Parent(node);
- return parent && parent->IsElementNode() ? ToElement(parent) : nullptr;
-}
-
-inline Node* FlatTreeTraversalNg::NextSibling(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseSiblings(node, kTraversalDirectionForward);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::PreviousSibling(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseSiblings(node, kTraversalDirectionBackward);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::Next(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseNext(node);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::Next(const Node& node,
- const Node* stay_within) {
- AssertPrecondition(node);
- Node* result = TraverseNext(node, stay_within);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::NextSkippingChildren(
- const Node& node,
- const Node* stay_within) {
- AssertPrecondition(node);
- Node* result = TraverseNextSkippingChildren(node, stay_within);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node) {
- if (Node* next = TraverseFirstChild(node))
- return next;
- for (const Node* next = &node; next; next = TraverseParent(*next)) {
- if (Node* sibling = TraverseNextSibling(*next))
- return sibling;
- }
- return nullptr;
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node,
- const Node* stay_within) {
- if (Node* next = TraverseFirstChild(node))
- return next;
- return TraverseNextSkippingChildren(node, stay_within);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNextSkippingChildren(
- const Node& node,
- const Node* stay_within) {
- for (const Node* next = &node; next; next = TraverseParent(*next)) {
- if (next == stay_within)
- return nullptr;
- if (Node* sibling = TraverseNextSibling(*next))
- return sibling;
- }
- return nullptr;
-}
-
-inline Node* FlatTreeTraversalNg::Previous(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraversePrevious(node);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::TraversePrevious(const Node& node) {
- if (Node* previous = TraversePreviousSibling(node)) {
- while (Node* child = TraverseLastChild(*previous))
- previous = child;
- return previous;
- }
- return TraverseParent(node);
-}
-
-inline Node* FlatTreeTraversalNg::FirstChild(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseChild(node, kTraversalDirectionForward);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::LastChild(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseLastChild(node);
- AssertPostcondition(result);
- return result;
-}
-
-inline bool FlatTreeTraversalNg::HasChildren(const Node& node) {
- return FirstChild(node);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNextSibling(const Node& node) {
- return TraverseSiblings(node, kTraversalDirectionForward);
-}
-
-inline Node* FlatTreeTraversalNg::TraversePreviousSibling(const Node& node) {
- return TraverseSiblings(node, kTraversalDirectionBackward);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseFirstChild(const Node& node) {
- return TraverseChild(node, kTraversalDirectionForward);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseLastChild(const Node& node) {
- return TraverseChild(node, kTraversalDirectionBackward);
-}
-
-// TraverseRange<T> implementations
-inline TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
-FlatTreeTraversalNg::ChildrenOf(const Node& parent) {
- return TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>(
- &parent);
-}
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_NG_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc
deleted file mode 100644
index 7f909cc882a..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc
+++ /dev/null
@@ -1,772 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h"
-
-#include <memory>
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/core/dom/node_traversal.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/html/html_element.h"
-#include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/blink/renderer/platform/wtf/compiler.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-// To avoid symbol collisions in jumbo builds.
-namespace flat_tree_traversal_ng_test {
-
-class FlatTreeTraversalNgTest : public PageTestBase,
- private ScopedSlotInFlatTreeForTest,
- ScopedIncrementalShadowDOMForTest {
- public:
- FlatTreeTraversalNgTest()
- : ScopedSlotInFlatTreeForTest(true),
- ScopedIncrementalShadowDOMForTest(true) {}
-
- protected:
- // Sets |mainHTML| to BODY element with |innerHTML| property and attaches
- // shadow root to child with |shadowHTML|, then update distribution for
- // calling member functions in |FlatTreeTraversalNg|.
- void SetupSampleHTML(const char* main_html,
- const char* shadow_html,
- unsigned);
-
- void SetupDocumentTree(const char* main_html);
-
- void AttachV0ShadowRoot(Element& shadow_host, const char* shadow_inner_html);
- void AttachOpenShadowRoot(Element& shadow_host,
- const char* shadow_inner_html);
-};
-
-void FlatTreeTraversalNgTest::SetupSampleHTML(const char* main_html,
- const char* shadow_html,
- unsigned index) {
- Element* body = GetDocument().body();
- body->SetInnerHTMLFromString(String::FromUTF8(main_html));
- Element* shadow_host = ToElement(NodeTraversal::ChildAt(*body, index));
- ShadowRoot& shadow_root = shadow_host->CreateV0ShadowRootForTesting();
- shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_html));
- body->UpdateDistributionForFlatTreeTraversal();
-}
-
-void FlatTreeTraversalNgTest::SetupDocumentTree(const char* main_html) {
- Element* body = GetDocument().body();
- body->SetInnerHTMLFromString(String::FromUTF8(main_html));
-}
-
-void FlatTreeTraversalNgTest::AttachV0ShadowRoot(
- Element& shadow_host,
- const char* shadow_inner_html) {
- ShadowRoot& shadow_root = shadow_host.CreateV0ShadowRootForTesting();
- shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
- GetDocument().body()->UpdateDistributionForFlatTreeTraversal();
-}
-
-void FlatTreeTraversalNgTest::AttachOpenShadowRoot(
- Element& shadow_host,
- const char* shadow_inner_html) {
- ShadowRoot& shadow_root =
- shadow_host.AttachShadowRootInternal(ShadowRootType::kOpen);
- shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
- GetDocument().body()->UpdateDistributionForFlatTreeTraversal();
-}
-
-namespace {
-
-void TestCommonAncestor(Node* expected_result,
- const Node& node_a,
- const Node& node_b) {
- Node* result1 = FlatTreeTraversalNg::CommonAncestor(node_a, node_b);
- EXPECT_EQ(expected_result, result1)
- << "commonAncestor(" << node_a.textContent() << ","
- << node_b.textContent() << ")";
- Node* result2 = FlatTreeTraversalNg::CommonAncestor(node_b, node_a);
- EXPECT_EQ(expected_result, result2)
- << "commonAncestor(" << node_b.textContent() << ","
- << node_a.textContent() << ")";
-}
-
-} // namespace
-
-// Test case for
-// - childAt
-// - countChildren
-// - hasChildren
-// - index
-// - isDescendantOf
-TEST_F(FlatTreeTraversalNgTest, childAt) {
- const char* main_html =
- "<div id='m0'>"
- "<span id='m00'>m00</span>"
- "<span id='m01'>m01</span>"
- "</div>";
- const char* shadow_html =
- "<a id='s00'>s00</a>"
- "<content select='#m01'></content>"
- "<a id='s02'>s02</a>"
- "<a id='s03'><content select='#m00'></content></a>"
- "<a id='s04'>s04</a>";
- SetupSampleHTML(main_html, shadow_html, 0);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m00 = m0->QuerySelector("#m00");
- Element* m01 = m0->QuerySelector("#m01");
-
- Element* shadow_host = m0;
- ShadowRoot* shadow_root = shadow_host->OpenShadowRoot();
- Element* s00 = shadow_root->QuerySelector("#s00");
- Element* s02 = shadow_root->QuerySelector("#s02");
- Element* s03 = shadow_root->QuerySelector("#s03");
- Element* s04 = shadow_root->QuerySelector("#s04");
-
- const unsigned kNumberOfChildNodes = 5;
- Node* expected_child_nodes[5] = {s00, m01, s02, s03, s04};
-
- ASSERT_EQ(kNumberOfChildNodes,
- FlatTreeTraversalNg::CountChildren(*shadow_host));
- EXPECT_TRUE(FlatTreeTraversalNg::HasChildren(*shadow_host));
-
- for (unsigned index = 0; index < kNumberOfChildNodes; ++index) {
- Node* child = FlatTreeTraversalNg::ChildAt(*shadow_host, index);
- EXPECT_EQ(expected_child_nodes[index], child)
- << "FlatTreeTraversalNg::childAt(*shadowHost, " << index << ")";
- EXPECT_EQ(index, FlatTreeTraversalNg::Index(*child))
- << "FlatTreeTraversalNg::index(FlatTreeTraversalNg(*shadowHost, "
- << index << "))";
- EXPECT_TRUE(FlatTreeTraversalNg::IsDescendantOf(*child, *shadow_host))
- << "FlatTreeTraversalNg::isDescendantOf(*FlatTreeTraversalNg(*"
- "shadowHost, "
- << index << "), *shadowHost)";
- }
- EXPECT_EQ(nullptr,
- FlatTreeTraversalNg::ChildAt(*shadow_host, kNumberOfChildNodes + 1))
- << "Out of bounds childAt() returns nullptr.";
-
- // Distribute node |m00| is child of node in shadow tree |s03|.
- EXPECT_EQ(m00, FlatTreeTraversalNg::ChildAt(*s03, 0));
-}
-
-TEST_F(FlatTreeTraversalNgTest, ChildrenOf) {
- SetupSampleHTML(
- "<p id=sample>ZERO<span slot=three>three</b><span "
- "slot=one>one</b>FOUR</p>",
- "zero<slot name=one></slot>two<slot name=three></slot>four", 0);
- Element* const sample = GetDocument().getElementById("sample");
-
- HeapVector<Member<Node>> expected_nodes;
- for (Node* runner = FlatTreeTraversalNg::FirstChild(*sample); runner;
- runner = FlatTreeTraversalNg::NextSibling(*runner)) {
- expected_nodes.push_back(runner);
- }
-
- HeapVector<Member<Node>> actual_nodes;
- for (Node& child : FlatTreeTraversalNg::ChildrenOf(*sample))
- actual_nodes.push_back(&child);
-
- EXPECT_EQ(expected_nodes, actual_nodes);
-}
-
-// Test case for
-// - commonAncestor
-// - isDescendantOf
-TEST_F(FlatTreeTraversalNgTest, commonAncestor) {
- // We build following flat tree:
- // ____BODY___
- // | | |
- // m0 m1 m2 m1 is shadow host having m10, m11, m12.
- // _|_ | __|__
- // | | | | |
- // m00 m01 | m20 m21
- // _____|_____________
- // | | | | |
- // s10 s11 s12 s13 s14
- // |
- // __|__
- // | | |
- // m12 m10 m11 <-- distributed
- // where: each symbol consists with prefix, child index, child-child index.
- // prefix "m" means node in main tree,
- // prefix "d" means node in main tree and distributed
- // prefix "s" means node in shadow tree
- const char* main_html =
- "<a id='m0'><b id='m00'>m00</b><b id='m01'>m01</b></a>"
- "<a id='m1'>"
- "<b id='m10'>m10</b>"
- "<b id='m11'>m11</b>"
- "<b id='m12'>m12</b>"
- "</a>"
- "<a id='m2'><b id='m20'>m20</b><b id='m21'>m21</b></a>";
- const char* shadow_html =
- "<a id='s10'>s10</a>"
- "<a id='s11'><content select='#m12'></content></a>"
- "<a id='s12'>s12</a>"
- "<a id='s13'>"
- "<content select='#m10'></content>"
- "<content select='#m11'></content>"
- "</a>"
- "<a id='s14'>s14</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m00 = body->QuerySelector("#m00");
- Element* m01 = body->QuerySelector("#m01");
- Element* m10 = body->QuerySelector("#m10");
- Element* m11 = body->QuerySelector("#m11");
- Element* m12 = body->QuerySelector("#m12");
- Element* m20 = body->QuerySelector("#m20");
- Element* m21 = body->QuerySelector("#m21");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s10 = shadow_root->QuerySelector("#s10");
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
- Element* s13 = shadow_root->QuerySelector("#s13");
- Element* s14 = shadow_root->QuerySelector("#s14");
-
- TestCommonAncestor(body, *m0, *m1);
- TestCommonAncestor(body, *m1, *m2);
- TestCommonAncestor(body, *m1, *m20);
- TestCommonAncestor(body, *s14, *m21);
-
- TestCommonAncestor(m0, *m0, *m0);
- TestCommonAncestor(m0, *m00, *m01);
-
- TestCommonAncestor(m1, *m1, *m1);
- TestCommonAncestor(m1, *s10, *s14);
- TestCommonAncestor(m1, *s10, *m12);
- TestCommonAncestor(m1, *s12, *m12);
- TestCommonAncestor(m1, *m10, *m12);
-
- TestCommonAncestor(m01, *m01, *m01);
- TestCommonAncestor(s11, *s11, *m12);
- TestCommonAncestor(s13, *m10, *m11);
-
- s12->remove(ASSERT_NO_EXCEPTION);
- TestCommonAncestor(s12, *s12, *s12);
- TestCommonAncestor(nullptr, *s12, *s11);
- TestCommonAncestor(nullptr, *s12, *m01);
- TestCommonAncestor(nullptr, *s12, *m20);
-
- m20->remove(ASSERT_NO_EXCEPTION);
- TestCommonAncestor(m20, *m20, *m20);
- TestCommonAncestor(nullptr, *m20, *s12);
- TestCommonAncestor(nullptr, *m20, *m1);
-}
-
-// Test case for
-// - nextSkippingChildren
-// - previousSkippingChildren
-TEST_F(FlatTreeTraversalNgTest, nextSkippingChildren) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html =
- "<content select='#m11'></content>"
- "<a id='s11'>s11</a>"
- "<a id='s12'>"
- "<b id='s120'>s120</b>"
- "<content select='#m10'></content>"
- "</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m10 = body->QuerySelector("#m10");
- Element* m11 = body->QuerySelector("#m11");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
- Element* s120 = shadow_root->QuerySelector("#s120");
-
- // Main tree node to main tree node
- EXPECT_EQ(*m1, FlatTreeTraversalNg::NextSkippingChildren(*m0));
- EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousSkippingChildren(*m1));
-
- // Distribute node to main tree node
- EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*m10));
- EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
-
- // Distribute node to node in shadow tree
- EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
- EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
-
- // Node in shadow tree to distributed node
- EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
- EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
-
- EXPECT_EQ(*m10, FlatTreeTraversalNg::NextSkippingChildren(*s120));
- EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousSkippingChildren(*m10));
-
- // Node in shadow tree to main tree
- EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*s12));
- EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
-}
-
-// Test case for
-// - lastWithin
-// - lastWithinOrSelf
-TEST_F(FlatTreeTraversalNgTest, lastWithin) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "<span id='m12'>m12</span>" // #m12 is not distributed.
- "</div>"
- "<div id='m2'></div>";
- const char* shadow_html =
- "<content select='#m11'></content>"
- "<a id='s11'>s11</a>"
- "<a id='s12'>"
- "<content select='#m10'></content>"
- "</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m10 = body->QuerySelector("#m10");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
-
- EXPECT_EQ(m0->firstChild(), FlatTreeTraversalNg::LastWithin(*m0));
- EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m0));
-
- EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*m1));
- EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m1));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::LastWithin(*m2));
- EXPECT_EQ(*m2, FlatTreeTraversalNg::LastWithinOrSelf(*m2));
-
- EXPECT_EQ(s11->firstChild(), FlatTreeTraversalNg::LastWithin(*s11));
- EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s11));
-
- EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*s12));
- EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s12));
-}
-
-TEST_F(FlatTreeTraversalNgTest, previousPostOrder) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html =
- "<content select='#m11'></content>"
- "<a id='s11'>s11</a>"
- "<a id='s12'>"
- "<b id='s120'>s120</b>"
- "<content select='#m10'></content>"
- "</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m10 = body->QuerySelector("#m10");
- Element* m11 = body->QuerySelector("#m11");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
- Element* s120 = shadow_root->QuerySelector("#s120");
-
- EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m0));
- EXPECT_EQ(*s12, FlatTreeTraversalNg::PreviousPostOrder(*m1));
- EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m10));
- EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild()));
- EXPECT_EQ(*s120,
- FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild(), s12));
- EXPECT_EQ(*m11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m11));
- EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild()));
- EXPECT_EQ(nullptr,
- FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild(), m11));
- EXPECT_EQ(*m2->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m2));
-
- EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s11));
- EXPECT_EQ(*m10, FlatTreeTraversalNg::PreviousPostOrder(*s12));
- EXPECT_EQ(*s120->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s120));
- EXPECT_EQ(*s11, FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild()));
- EXPECT_EQ(nullptr,
- FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild(), s12));
-}
-
-TEST_F(FlatTreeTraversalNgTest, nextSiblingNotInDocumentFlatTree) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html = "<content select='#m11'></content>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m10 = body->QuerySelector("#m10");
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*m10));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*m10));
-}
-
-TEST_F(FlatTreeTraversalNgTest, redistribution) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html1 =
- "<div id='s1'>"
- "<content></content>"
- "</div>";
-
- SetupSampleHTML(main_html, shadow_html1, 1);
-
- const char* shadow_html2 =
- "<div id='s2'>"
- "<content select='#m10'></content>"
- "<span id='s21'>s21</span>"
- "</div>";
-
- Element* body = GetDocument().body();
- Element* m1 = body->QuerySelector("#m1");
- Element* m10 = body->QuerySelector("#m10");
-
- ShadowRoot* shadow_root1 = m1->OpenShadowRoot();
- Element* s1 = shadow_root1->QuerySelector("#s1");
-
- AttachV0ShadowRoot(*s1, shadow_html2);
-
- ShadowRoot* shadow_root2 = s1->OpenShadowRoot();
- Element* s21 = shadow_root2->QuerySelector("#s21");
-
- EXPECT_EQ(s21, FlatTreeTraversalNg::NextSibling(*m10));
- EXPECT_EQ(m10, FlatTreeTraversalNg::PreviousSibling(*s21));
-
- // FlatTreeTraversalNg::traverseSiblings does not work for a node which is not
- // in a document flat tree.
- // e.g. The following test fails. The result of
- // FlatTreeTraversalNg::previousSibling(*m11)) will be #m10, instead of
- // nullptr. Element* m11 = body->querySelector("#m11"); EXPECT_EQ(nullptr,
- // FlatTreeTraversalNg::previousSibling(*m11));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1Simple) {
- const char* main_html =
- "<div id='host'>"
- "<div id='child1' slot='slot1'></div>"
- "<div id='child2' slot='slot2'></div>"
- "</div>";
- const char* shadow_html =
- "<div id='shadow-child1'></div>"
- "<slot name='slot1'></slot>"
- "<slot name='slot2'></slot>"
- "<div id='shadow-child2'></div>";
-
- SetupDocumentTree(main_html);
- Element* body = GetDocument().body();
- Element* host = body->QuerySelector("#host");
- Element* child1 = body->QuerySelector("#child1");
- Element* child2 = body->QuerySelector("#child2");
-
- AttachOpenShadowRoot(*host, shadow_html);
- ShadowRoot* shadow_root = host->OpenShadowRoot();
- Element* slot1 = shadow_root->QuerySelector("[name=slot1]");
- Element* slot2 = shadow_root->QuerySelector("[name=slot2]");
- Element* shadow_child1 = shadow_root->QuerySelector("#shadow-child1");
- Element* shadow_child2 = shadow_root->QuerySelector("#shadow-child2");
-
- EXPECT_TRUE(slot1);
- EXPECT_TRUE(slot2);
- EXPECT_EQ(shadow_child1, FlatTreeTraversalNg::FirstChild(*host));
- EXPECT_EQ(slot1, FlatTreeTraversalNg::NextSibling(*shadow_child1));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child1));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
- EXPECT_EQ(slot2, FlatTreeTraversalNg::NextSibling(*slot1));
- EXPECT_EQ(shadow_child2, FlatTreeTraversalNg::NextSibling(*slot2));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1Redistribution) {
- // composed tree:
- // d1
- // ├──/shadow-root
- // │ └── d1-1
- // │ ├──/shadow-root
- // │ │ ├── d1-1-1
- // │ │ ├── slot name=d1-1-s1
- // │ │ ├── slot name=d1-1-s2
- // │ │ └── d1-1-2
- // │ ├── d1-2
- // │ ├── slot id=d1-s0
- // │ ├── slot name=d1-s1 slot=d1-1-s1
- // │ ├── slot name=d1-s2
- // │ ├── d1-3
- // │ └── d1-4 slot=d1-1-s1
- // ├── d2 slot=d1-s1
- // ├── d3 slot=d1-s2
- // ├── d4 slot=nonexistent
- // └── d5
-
- // flat tree:
- // d1
- // └── d1-1
- // ├── d1-1-1
- // ├── slot name=d1-1-s1
- // │ ├── slot name=d1-s1 slot=d1-1-s1
- // │ │ └── d2 slot=d1-s1
- // │ └── d1-4 slot=d1-1-s1
- // ├── slot name=d1-1-s2
- // └── d1-1-2
- const char* main_html =
- "<div id='d1'>"
- "<div id='d2' slot='d1-s1'></div>"
- "<div id='d3' slot='d1-s2'></div>"
- "<div id='d4' slot='nonexistent'></div>"
- "<div id='d5'></div>"
- "</div>"
- "<div id='d6'></div>";
- const char* shadow_html1 =
- "<div id='d1-1'>"
- "<div id='d1-2'></div>"
- "<slot id='d1-s0'></slot>"
- "<slot name='d1-s1' slot='d1-1-s1'></slot>"
- "<slot name='d1-s2'></slot>"
- "<div id='d1-3'></div>"
- "<div id='d1-4' slot='d1-1-s1'></div>"
- "</div>";
- const char* shadow_html2 =
- "<div id='d1-1-1'></div>"
- "<slot name='d1-1-s1'></slot>"
- "<slot name='d1-1-s2'></slot>"
- "<div id='d1-1-2'></div>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
- Element* d2 = body->QuerySelector("#d2");
- Element* d3 = body->QuerySelector("#d3");
- Element* d4 = body->QuerySelector("#d4");
- Element* d5 = body->QuerySelector("#d5");
- Element* d6 = body->QuerySelector("#d6");
-
- AttachOpenShadowRoot(*d1, shadow_html1);
- ShadowRoot* shadow_root1 = d1->OpenShadowRoot();
- Element* d11 = shadow_root1->QuerySelector("#d1-1");
- Element* d12 = shadow_root1->QuerySelector("#d1-2");
- Element* d13 = shadow_root1->QuerySelector("#d1-3");
- Element* d14 = shadow_root1->QuerySelector("#d1-4");
- Element* d1s0 = shadow_root1->QuerySelector("#d1-s0");
- Element* d1s1 = shadow_root1->QuerySelector("[name=d1-s1]");
- Element* d1s2 = shadow_root1->QuerySelector("[name=d1-s2]");
-
- AttachOpenShadowRoot(*d11, shadow_html2);
- ShadowRoot* shadow_root2 = d11->OpenShadowRoot();
- Element* d111 = shadow_root2->QuerySelector("#d1-1-1");
- Element* d112 = shadow_root2->QuerySelector("#d1-1-2");
- Element* d11s1 = shadow_root2->QuerySelector("[name=d1-1-s1]");
- Element* d11s2 = shadow_root2->QuerySelector("[name=d1-1-s2]");
-
- EXPECT_TRUE(d5);
- EXPECT_TRUE(d12);
- EXPECT_TRUE(d13);
- EXPECT_TRUE(d1s0);
- EXPECT_TRUE(d1s1);
- EXPECT_TRUE(d1s2);
- EXPECT_TRUE(d11s1);
- EXPECT_TRUE(d11s2);
-
- EXPECT_EQ(d11, FlatTreeTraversalNg::Next(*d1));
- EXPECT_EQ(d111, FlatTreeTraversalNg::Next(*d11));
- EXPECT_EQ(d11s1, FlatTreeTraversalNg::Next(*d111));
- EXPECT_EQ(d1s1, FlatTreeTraversalNg::Next(*d11s1));
- EXPECT_EQ(d2, FlatTreeTraversalNg::Next(*d1s1));
- EXPECT_EQ(d14, FlatTreeTraversalNg::Next(*d2));
- EXPECT_EQ(d11s2, FlatTreeTraversalNg::Next(*d14));
- EXPECT_EQ(d112, FlatTreeTraversalNg::Next(*d11s2));
- EXPECT_EQ(d6, FlatTreeTraversalNg::Next(*d112));
-
- EXPECT_EQ(d112, FlatTreeTraversalNg::Previous(*d6));
-
- EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d111));
- EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d112));
- EXPECT_EQ(d1s1, FlatTreeTraversalNg::Parent(*d2));
- EXPECT_EQ(d11s1, FlatTreeTraversalNg::Parent(*d14));
- EXPECT_EQ(d1s2, FlatTreeTraversalNg::Parent(*d3));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*d4));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1SlotInDocumentTree) {
- const char* main_html =
- "<div id='parent'>"
- "<slot>"
- "<div id='child1'></div>"
- "<div id='child2'></div>"
- "</slot>"
- "</div>";
-
- SetupDocumentTree(main_html);
- Element* body = GetDocument().body();
- Element* parent = body->QuerySelector("#parent");
- Element* slot = body->QuerySelector("slot");
- Element* child1 = body->QuerySelector("#child1");
- Element* child2 = body->QuerySelector("#child2");
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::FirstChild(*parent));
- EXPECT_EQ(child1, FlatTreeTraversalNg::FirstChild(*slot));
- EXPECT_EQ(child2, FlatTreeTraversalNg::NextSibling(*child1));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child1));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child2));
- EXPECT_EQ(parent, FlatTreeTraversalNg::Parent(*slot));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1FallbackContent) {
- const char* main_html = "<div id='d1'></div>";
- const char* shadow_html =
- "<div id='before'></div>"
- "<slot><p>fallback content</p></slot>"
- "<div id='after'></div>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
-
- AttachOpenShadowRoot(*d1, shadow_html);
- ShadowRoot* shadow_root = d1->OpenShadowRoot();
- Element* before = shadow_root->QuerySelector("#before");
- Element* after = shadow_root->QuerySelector("#after");
- Element* fallback_content = shadow_root->QuerySelector("p");
- Element* slot = shadow_root->QuerySelector("slot");
-
- EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
- EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*fallback_content));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
- EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
- EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1FallbackContentSkippedInTraversal) {
- const char* main_html = "<div id='d1'><span></span></div>";
- const char* shadow_html =
- "<div id='before'></div>"
- "<slot><p>fallback content</p></slot>"
- "<div id='after'></div>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
- Element* span = body->QuerySelector("span");
-
- AttachOpenShadowRoot(*d1, shadow_html);
- ShadowRoot* shadow_root = d1->OpenShadowRoot();
- Element* before = shadow_root->QuerySelector("#before");
- Element* after = shadow_root->QuerySelector("#after");
- Element* fallback_content = shadow_root->QuerySelector("p");
- Element* slot = shadow_root->QuerySelector("slot");
-
- EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
- EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*span));
- EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
- EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
- EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1AllFallbackContent) {
- const char* main_html = "<div id='d1'></div>";
- const char* shadow_html =
- "<slot name='a'><p id='x'>fallback content X</p></slot>"
- "<slot name='b'><p id='y'>fallback content Y</p></slot>"
- "<slot name='c'><p id='z'>fallback content Z</p></slot>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
-
- AttachOpenShadowRoot(*d1, shadow_html);
- ShadowRoot* shadow_root = d1->OpenShadowRoot();
- Element* slot_a = shadow_root->QuerySelector("slot[name=a]");
- Element* slot_b = shadow_root->QuerySelector("slot[name=b]");
- Element* slot_c = shadow_root->QuerySelector("slot[name=c]");
- Element* fallback_x = shadow_root->QuerySelector("#x");
- Element* fallback_y = shadow_root->QuerySelector("#y");
- Element* fallback_z = shadow_root->QuerySelector("#z");
-
- EXPECT_EQ(slot_a, FlatTreeTraversalNg::FirstChild(*d1));
- EXPECT_EQ(slot_c, FlatTreeTraversalNg::LastChild(*d1));
-
- EXPECT_EQ(fallback_x, FlatTreeTraversalNg::FirstChild(*slot_a));
- EXPECT_EQ(fallback_y, FlatTreeTraversalNg::FirstChild(*slot_b));
- EXPECT_EQ(fallback_z, FlatTreeTraversalNg::FirstChild(*slot_c));
-
- EXPECT_EQ(slot_a, FlatTreeTraversalNg::Parent(*fallback_x));
- EXPECT_EQ(slot_b, FlatTreeTraversalNg::Parent(*fallback_y));
- EXPECT_EQ(slot_c, FlatTreeTraversalNg::Parent(*fallback_z));
- EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot_a));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_x));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_y));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_z));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_z));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_y));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_x));
-}
-
-} // namespace flat_tree_traversal_ng_test
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc
index 517360e43db..8c310ff0615 100644
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc
@@ -16,20 +16,20 @@
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
+// To avoid symbol collisions in jumbo builds.
+namespace flat_tree_traversal_test {
class FlatTreeTraversalTest : public PageTestBase,
- private ScopedSlotInFlatTreeForTest,
ScopedIncrementalShadowDOMForTest {
public:
- FlatTreeTraversalTest()
- : ScopedSlotInFlatTreeForTest(false),
- ScopedIncrementalShadowDOMForTest(false) {}
+ FlatTreeTraversalTest() : ScopedIncrementalShadowDOMForTest(true) {}
protected:
// Sets |mainHTML| to BODY element with |innerHTML| property and attaches
@@ -142,7 +142,8 @@ TEST_F(FlatTreeTraversalTest, childAt) {
<< "FlatTreeTraversal::index(FlatTreeTraversal(*shadowHost, " << index
<< "))";
EXPECT_TRUE(FlatTreeTraversal::IsDescendantOf(*child, *shadow_host))
- << "FlatTreeTraversal::isDescendantOf(*FlatTreeTraversal(*shadowHost, "
+ << "FlatTreeTraversal::isDescendantOf(*FlatTreeTraversal(*"
+ "shadowHost, "
<< index << "), *shadowHost)";
}
EXPECT_EQ(nullptr,
@@ -508,9 +509,9 @@ TEST_F(FlatTreeTraversalTest, redistribution) {
// FlatTreeTraversal::traverseSiblings does not work for a node which is not
// in a document flat tree.
// e.g. The following test fails. The result of
- // FlatTreeTraversal::previousSibling(*m11)) will be #m10, instead of nullptr.
- // Element* m11 = body->querySelector("#m11");
- // EXPECT_EQ(nullptr, FlatTreeTraversal::previousSibling(*m11));
+ // FlatTreeTraversal::previousSibling(*m11)) will be #m10, instead of
+ // nullptr. Element* m11 = body->querySelector("#m11"); EXPECT_EQ(nullptr,
+ // FlatTreeTraversal::previousSibling(*m11));
}
TEST_F(FlatTreeTraversalTest, v1Simple) {
@@ -541,12 +542,44 @@ TEST_F(FlatTreeTraversalTest, v1Simple) {
EXPECT_TRUE(slot1);
EXPECT_TRUE(slot2);
EXPECT_EQ(shadow_child1, FlatTreeTraversal::FirstChild(*host));
- EXPECT_EQ(child1, FlatTreeTraversal::NextSibling(*shadow_child1));
- EXPECT_EQ(child2, FlatTreeTraversal::NextSibling(*child1));
- EXPECT_EQ(shadow_child2, FlatTreeTraversal::NextSibling(*child2));
+ EXPECT_EQ(slot1, FlatTreeTraversal::NextSibling(*shadow_child1));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*child1));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*child2));
+ EXPECT_EQ(slot2, FlatTreeTraversal::NextSibling(*slot1));
+ EXPECT_EQ(shadow_child2, FlatTreeTraversal::NextSibling(*slot2));
}
TEST_F(FlatTreeTraversalTest, v1Redistribution) {
+ // composed tree:
+ // d1
+ // ├──/shadow-root
+ // │ └── d1-1
+ // │ ├──/shadow-root
+ // │ │ ├── d1-1-1
+ // │ │ ├── slot name=d1-1-s1
+ // │ │ ├── slot name=d1-1-s2
+ // │ │ └── d1-1-2
+ // │ ├── d1-2
+ // │ ├── slot id=d1-s0
+ // │ ├── slot name=d1-s1 slot=d1-1-s1
+ // │ ├── slot name=d1-s2
+ // │ ├── d1-3
+ // │ └── d1-4 slot=d1-1-s1
+ // ├── d2 slot=d1-s1
+ // ├── d3 slot=d1-s2
+ // ├── d4 slot=nonexistent
+ // └── d5
+
+ // flat tree:
+ // d1
+ // └── d1-1
+ // ├── d1-1-1
+ // ├── slot name=d1-1-s1
+ // │ ├── slot name=d1-s1 slot=d1-1-s1
+ // │ │ └── d2 slot=d1-s1
+ // │ └── d1-4 slot=d1-1-s1
+ // ├── slot name=d1-1-s2
+ // └── d1-1-2
const char* main_html =
"<div id='d1'>"
"<div id='d2' slot='d1-s1'></div>"
@@ -605,20 +638,24 @@ TEST_F(FlatTreeTraversalTest, v1Redistribution) {
EXPECT_TRUE(d1s2);
EXPECT_TRUE(d11s1);
EXPECT_TRUE(d11s2);
+
EXPECT_EQ(d11, FlatTreeTraversal::Next(*d1));
EXPECT_EQ(d111, FlatTreeTraversal::Next(*d11));
- EXPECT_EQ(d2, FlatTreeTraversal::Next(*d111));
+ EXPECT_EQ(d11s1, FlatTreeTraversal::Next(*d111));
+ EXPECT_EQ(d1s1, FlatTreeTraversal::Next(*d11s1));
+ EXPECT_EQ(d2, FlatTreeTraversal::Next(*d1s1));
EXPECT_EQ(d14, FlatTreeTraversal::Next(*d2));
- EXPECT_EQ(d112, FlatTreeTraversal::Next(*d14));
+ EXPECT_EQ(d11s2, FlatTreeTraversal::Next(*d14));
+ EXPECT_EQ(d112, FlatTreeTraversal::Next(*d11s2));
EXPECT_EQ(d6, FlatTreeTraversal::Next(*d112));
EXPECT_EQ(d112, FlatTreeTraversal::Previous(*d6));
EXPECT_EQ(d11, FlatTreeTraversal::Parent(*d111));
EXPECT_EQ(d11, FlatTreeTraversal::Parent(*d112));
- EXPECT_EQ(d11, FlatTreeTraversal::Parent(*d2));
- EXPECT_EQ(d11, FlatTreeTraversal::Parent(*d14));
- EXPECT_EQ(nullptr, FlatTreeTraversal::Parent(*d3));
+ EXPECT_EQ(d1s1, FlatTreeTraversal::Parent(*d2));
+ EXPECT_EQ(d11s1, FlatTreeTraversal::Parent(*d14));
+ EXPECT_EQ(d1s2, FlatTreeTraversal::Parent(*d3));
EXPECT_EQ(nullptr, FlatTreeTraversal::Parent(*d4));
}
@@ -664,17 +701,20 @@ TEST_F(FlatTreeTraversalTest, v1FallbackContent) {
Element* before = shadow_root->QuerySelector("#before");
Element* after = shadow_root->QuerySelector("#after");
Element* fallback_content = shadow_root->QuerySelector("p");
+ Element* slot = shadow_root->QuerySelector("slot");
EXPECT_EQ(before, FlatTreeTraversal::FirstChild(*d1));
EXPECT_EQ(after, FlatTreeTraversal::LastChild(*d1));
- EXPECT_EQ(d1, FlatTreeTraversal::Parent(*fallback_content));
+ EXPECT_EQ(slot, FlatTreeTraversal::Parent(*fallback_content));
- EXPECT_EQ(fallback_content, FlatTreeTraversal::NextSibling(*before));
- EXPECT_EQ(after, FlatTreeTraversal::NextSibling(*fallback_content));
+ EXPECT_EQ(slot, FlatTreeTraversal::NextSibling(*before));
+ EXPECT_EQ(after, FlatTreeTraversal::NextSibling(*slot));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*fallback_content));
EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*after));
- EXPECT_EQ(fallback_content, FlatTreeTraversal::PreviousSibling(*after));
- EXPECT_EQ(before, FlatTreeTraversal::PreviousSibling(*fallback_content));
+ EXPECT_EQ(slot, FlatTreeTraversal::PreviousSibling(*after));
+ EXPECT_EQ(before, FlatTreeTraversal::PreviousSibling(*slot));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::PreviousSibling(*fallback_content));
EXPECT_EQ(nullptr, FlatTreeTraversal::PreviousSibling(*before));
}
@@ -696,17 +736,19 @@ TEST_F(FlatTreeTraversalTest, v1FallbackContentSkippedInTraversal) {
Element* before = shadow_root->QuerySelector("#before");
Element* after = shadow_root->QuerySelector("#after");
Element* fallback_content = shadow_root->QuerySelector("p");
+ Element* slot = shadow_root->QuerySelector("slot");
EXPECT_EQ(before, FlatTreeTraversal::FirstChild(*d1));
EXPECT_EQ(after, FlatTreeTraversal::LastChild(*d1));
- EXPECT_EQ(d1, FlatTreeTraversal::Parent(*span));
+ EXPECT_EQ(slot, FlatTreeTraversal::Parent(*span));
+ EXPECT_EQ(d1, FlatTreeTraversal::Parent(*slot));
- EXPECT_EQ(span, FlatTreeTraversal::NextSibling(*before));
- EXPECT_EQ(after, FlatTreeTraversal::NextSibling(*span));
+ EXPECT_EQ(slot, FlatTreeTraversal::NextSibling(*before));
+ EXPECT_EQ(after, FlatTreeTraversal::NextSibling(*slot));
EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*after));
- EXPECT_EQ(span, FlatTreeTraversal::PreviousSibling(*after));
- EXPECT_EQ(before, FlatTreeTraversal::PreviousSibling(*span));
+ EXPECT_EQ(slot, FlatTreeTraversal::PreviousSibling(*after));
+ EXPECT_EQ(before, FlatTreeTraversal::PreviousSibling(*slot));
EXPECT_EQ(nullptr, FlatTreeTraversal::PreviousSibling(*before));
EXPECT_EQ(nullptr, FlatTreeTraversal::Parent(*fallback_content));
@@ -728,40 +770,33 @@ TEST_F(FlatTreeTraversalTest, v1AllFallbackContent) {
AttachOpenShadowRoot(*d1, shadow_html);
ShadowRoot* shadow_root = d1->OpenShadowRoot();
+ Element* slot_a = shadow_root->QuerySelector("slot[name=a]");
+ Element* slot_b = shadow_root->QuerySelector("slot[name=b]");
+ Element* slot_c = shadow_root->QuerySelector("slot[name=c]");
Element* fallback_x = shadow_root->QuerySelector("#x");
Element* fallback_y = shadow_root->QuerySelector("#y");
Element* fallback_z = shadow_root->QuerySelector("#z");
- EXPECT_EQ(fallback_x, FlatTreeTraversal::FirstChild(*d1));
- EXPECT_EQ(fallback_z, FlatTreeTraversal::LastChild(*d1));
- EXPECT_EQ(d1, FlatTreeTraversal::Parent(*fallback_x));
- EXPECT_EQ(d1, FlatTreeTraversal::Parent(*fallback_y));
- EXPECT_EQ(d1, FlatTreeTraversal::Parent(*fallback_z));
-
- EXPECT_EQ(fallback_y, FlatTreeTraversal::NextSibling(*fallback_x));
- EXPECT_EQ(fallback_z, FlatTreeTraversal::NextSibling(*fallback_y));
- EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*fallback_z));
-
- EXPECT_EQ(fallback_y, FlatTreeTraversal::PreviousSibling(*fallback_z));
- EXPECT_EQ(fallback_x, FlatTreeTraversal::PreviousSibling(*fallback_y));
- EXPECT_EQ(nullptr, FlatTreeTraversal::PreviousSibling(*fallback_x));
-}
+ EXPECT_EQ(slot_a, FlatTreeTraversal::FirstChild(*d1));
+ EXPECT_EQ(slot_c, FlatTreeTraversal::LastChild(*d1));
-TEST_F(FlatTreeTraversalTest, v0ParentDetailsInsertionPoint) {
- const char* main_html = "<div><span></span></div>";
- const char* shadow_html = "<content></content>";
+ EXPECT_EQ(fallback_x, FlatTreeTraversal::FirstChild(*slot_a));
+ EXPECT_EQ(fallback_y, FlatTreeTraversal::FirstChild(*slot_b));
+ EXPECT_EQ(fallback_z, FlatTreeTraversal::FirstChild(*slot_c));
- SetupSampleHTML(main_html, shadow_html, 0);
+ EXPECT_EQ(slot_a, FlatTreeTraversal::Parent(*fallback_x));
+ EXPECT_EQ(slot_b, FlatTreeTraversal::Parent(*fallback_y));
+ EXPECT_EQ(slot_c, FlatTreeTraversal::Parent(*fallback_z));
+ EXPECT_EQ(d1, FlatTreeTraversal::Parent(*slot_a));
- Element* span = GetDocument().body()->QuerySelector("span");
- ASSERT_TRUE(span);
-
- FlatTreeTraversal::ParentTraversalDetails details;
- EXPECT_FALSE(details.GetInsertionPoint());
+ EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*fallback_x));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*fallback_y));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::NextSibling(*fallback_z));
- ContainerNode* parent = FlatTreeTraversal::Parent(*span, &details);
- ASSERT_TRUE(parent);
- EXPECT_TRUE(details.GetInsertionPoint());
+ EXPECT_EQ(nullptr, FlatTreeTraversal::PreviousSibling(*fallback_z));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::PreviousSibling(*fallback_y));
+ EXPECT_EQ(nullptr, FlatTreeTraversal::PreviousSibling(*fallback_x));
}
+} // namespace flat_tree_traversal_test
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
index eebf55d1b01..8dce1e2a79c 100644
--- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
+++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
@@ -40,6 +40,7 @@ class GlobalEventHandlers {
public:
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(abort);
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(activateinvisible);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(auxclick);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(blur);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(cancel);
@@ -93,6 +94,7 @@ class GlobalEventHandlers {
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(pointermove);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(pointerout);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(pointerover);
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(pointerrawmove);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(pointerup);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(progress);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(ratechange);
diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
index dfed8b89785..5490b6033e4 100644
--- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
+++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
@@ -34,6 +34,7 @@
NoInterfaceObject // Always used on target of 'implements'
] interface GlobalEventHandlers {
attribute EventHandler onabort;
+ [RuntimeEnabled=InvisibleDOM] attribute EventHandler onactivateinvisible;
attribute EventHandler onblur;
attribute EventHandler oncancel;
attribute EventHandler oncanplay;
@@ -107,6 +108,7 @@
attribute EventHandler onlostpointercapture;
attribute EventHandler onpointerdown;
attribute EventHandler onpointermove;
+ [RuntimeEnabled=PointerRawMove] attribute EventHandler onpointerrawmove;
attribute EventHandler onpointerup;
attribute EventHandler onpointercancel;
attribute EventHandler onpointerover;
diff --git a/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc
index 1759da148c5..dee6adfab2e 100644
--- a/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -8,7 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h"
#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
@@ -51,8 +51,7 @@ class MockIdleDeadlineScheduler final : public ThreadScheduler {
void RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) override {}
- void AddRAILModeObserver(
- scheduler::WebThreadScheduler::RAILModeObserver*) override {}
+ void AddRAILModeObserver(scheduler::WebRAILModeObserver*) override {}
scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
return nullptr;
@@ -62,29 +61,6 @@ class MockIdleDeadlineScheduler final : public ThreadScheduler {
DISALLOW_COPY_AND_ASSIGN(MockIdleDeadlineScheduler);
};
-class MockIdleDeadlineThread final : public WebThread {
- public:
- MockIdleDeadlineThread() = default;
- ~MockIdleDeadlineThread() override = default;
- bool IsCurrentThread() const override { return true; }
- ThreadScheduler* Scheduler() const override { return &scheduler_; }
-
- private:
- mutable MockIdleDeadlineScheduler scheduler_;
- DISALLOW_COPY_AND_ASSIGN(MockIdleDeadlineThread);
-};
-
-class MockIdleDeadlinePlatform : public TestingPlatformSupport {
- public:
- MockIdleDeadlinePlatform() = default;
- ~MockIdleDeadlinePlatform() override = default;
- WebThread* CurrentThread() override { return &thread_; }
-
- private:
- MockIdleDeadlineThread thread_;
- DISALLOW_COPY_AND_ASSIGN(MockIdleDeadlinePlatform);
-};
-
} // namespace
class IdleDeadlineTest : public testing::Test {
@@ -111,7 +87,10 @@ TEST_F(IdleDeadlineTest, deadlineInPast) {
}
TEST_F(IdleDeadlineTest, yieldForHighPriorityWork) {
- ScopedTestingPlatformSupport<MockIdleDeadlinePlatform> platform;
+ MockIdleDeadlineScheduler scheduler;
+ ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler,
+ ThreadScheduler*>
+ platform(&scheduler);
IdleDeadline* deadline =
IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25),
diff --git a/chromium/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h b/chromium/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h
new file mode 100644
index 00000000000..0863a139a31
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_IGNORE_OPENS_DURING_UNLOAD_COUNT_INCREMENTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_IGNORE_OPENS_DURING_UNLOAD_COUNT_INCREMENTER_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class IgnoreOpensDuringUnloadCountIncrementer {
+ STACK_ALLOCATED();
+
+ public:
+ explicit IgnoreOpensDuringUnloadCountIncrementer(Document* document)
+ : count_(document ? &document->ignore_opens_during_unload_count_
+ : nullptr) {
+ if (!count_)
+ return;
+ ++(*count_);
+ }
+
+ ~IgnoreOpensDuringUnloadCountIncrementer() {
+ if (!count_)
+ return;
+ --(*count_);
+ }
+
+ private:
+ unsigned* count_;
+ DISALLOW_COPY_AND_ASSIGN(IgnoreOpensDuringUnloadCountIncrementer);
+};
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc
index e7ac71fa579..cc566ecbd7c 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc
@@ -132,8 +132,10 @@ bool LayoutTreeBuilderForElement::ShouldCreateLayoutObject() const {
ComputedStyle& LayoutTreeBuilderForElement::Style() const {
if (!style_) {
- DCHECK(!node_->GetNonAttachedStyle());
- DCHECK(node_->IsFirstLetterPseudoElement());
+ // TODO(futhark@chromium.org): this should never happen, but we currently
+ // have crashes in the wild because of this (https://crbug.com/875796).
+ // Please report if you ever end up here.
+ NOTREACHED();
style_ = node_->StyleForLayoutObject();
}
return *style_;
@@ -282,7 +284,7 @@ void ReattachLegacyLayoutObjectList::AddForceLegacyAtBFCAncestor(
}
bool ReattachLegacyLayoutObjectList::IsCollecting() const {
- return state_ == State::kCollecting || state_ == State::kRecalcStyle;
+ return state_ == State::kCollecting;
}
void ReattachLegacyLayoutObjectList::ForceLegacyLayoutIfNeeded() {
@@ -303,26 +305,6 @@ void ReattachLegacyLayoutObjectList::ForceLegacyLayoutIfNeeded() {
state_ = State::kClosed;
}
-void ReattachLegacyLayoutObjectList::DidRecalcStyle() {
- const State state = state_;
- state_ = State::kClosed;
- if (state == State::kBuildingLegacyLayoutTree)
- return;
- DCHECK_EQ(state, State::kRecalcStyle);
- for (const LayoutObject* block : blocks_)
- ToElement(*block->GetNode()).LazyReattachIfAttached();
-}
-
-void ReattachLegacyLayoutObjectList::WillRecalcStyle() {
- // TODO(layout-dev): Once make |RecalcStyle()| not to create layout object,
- // we don't need to have |WillRecalcStyle()| and |DidRecalcStyle()|.
- // Note: "first-letter-removed-added.html" creates layout object during
- // style recalc. See http://crbug.com/847218
- if (state_ == State::kBuildingLegacyLayoutTree)
- return;
- state_ = State::kRecalcStyle;
-}
-
void ReattachLegacyLayoutObjectList::Trace(blink::Visitor* visitor) {
visitor->Trace(document_);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h
index a3e30b2cd03..0f53a0781a8 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h
@@ -158,9 +158,6 @@ class CORE_EXPORT ReattachLegacyLayoutObjectList final {
}
void ForceLegacyLayoutIfNeeded();
- void DidRecalcStyle();
- void WillRecalcStyle();
-
void Trace(blink::Visitor*);
private:
@@ -180,8 +177,6 @@ class CORE_EXPORT ReattachLegacyLayoutObjectList final {
kCollecting,
// Replaces LayoutNG objects to legacy layout objects.
kForcingLegacyLayout,
- // Doing style re-calculation.
- kRecalcStyle,
} state_ = State::kInvalid;
DISALLOW_COPY_AND_ASSIGN(ReattachLegacyLayoutObjectList);
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
index f0b42f60ae6..8e00d68b145 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
@@ -123,39 +123,18 @@ Node* LayoutTreeBuilderTraversal::PreviousSibling(const Node& node) {
return nullptr;
}
-static Node* LastChild(const Node& node) {
- return FlatTreeTraversal::LastChild(node);
-}
-
-static Node* PseudoAwarePreviousSibling(const Node& node) {
- Node* previous_node = LayoutTreeBuilderTraversal::PreviousSibling(node);
- Node* parent_node = LayoutTreeBuilderTraversal::Parent(node);
-
- if (parent_node && parent_node->IsElementNode() && !previous_node) {
- if (node.IsAfterPseudoElement()) {
- if (Node* child = LastChild(*parent_node))
- return child;
- }
- if (!node.IsBeforePseudoElement())
- return ToElement(parent_node)->GetPseudoElement(kPseudoIdBefore);
- }
- return previous_node;
-}
+Node* LayoutTreeBuilderTraversal::LastChild(const Node& node) {
+ if (!node.IsElementNode())
+ return FlatTreeTraversal::LastChild(node);
-static Node* PseudoAwareLastChild(const Node& node) {
- if (node.IsElementNode()) {
- const Element& current_element = ToElement(node);
- Node* last = current_element.GetPseudoElement(kPseudoIdAfter);
- if (last)
- return last;
-
- last = LastChild(current_element);
- if (!last)
- last = current_element.GetPseudoElement(kPseudoIdBefore);
+ const Element& current_element = ToElement(node);
+ Node* last = current_element.GetPseudoElement(kPseudoIdAfter);
+ if (last)
return last;
- }
-
- return LastChild(node);
+ last = FlatTreeTraversal::LastChild(current_element);
+ if (!last)
+ last = current_element.GetPseudoElement(kPseudoIdBefore);
+ return last;
}
Node* LayoutTreeBuilderTraversal::Previous(const Node& node,
@@ -163,8 +142,8 @@ Node* LayoutTreeBuilderTraversal::Previous(const Node& node,
if (node == stay_within)
return nullptr;
- if (Node* previous_node = PseudoAwarePreviousSibling(node)) {
- while (Node* previous_last_child = PseudoAwareLastChild(*previous_node))
+ if (Node* previous_node = PreviousSibling(node)) {
+ while (Node* previous_last_child = LastChild(*previous_node))
previous_node = previous_last_child;
return previous_node;
}
@@ -172,48 +151,28 @@ Node* LayoutTreeBuilderTraversal::Previous(const Node& node,
}
Node* LayoutTreeBuilderTraversal::FirstChild(const Node& node) {
- return FlatTreeTraversal::FirstChild(node);
-}
-
-static Node* PseudoAwareNextSibling(const Node& node) {
- Node* parent_node = LayoutTreeBuilderTraversal::Parent(node);
- Node* next_node = LayoutTreeBuilderTraversal::NextSibling(node);
-
- if (parent_node && parent_node->IsElementNode() && !next_node) {
- if (node.IsBeforePseudoElement()) {
- if (Node* child = LayoutTreeBuilderTraversal::FirstChild(*parent_node))
- return child;
- }
- if (!node.IsAfterPseudoElement())
- return ToElement(parent_node)->GetPseudoElement(kPseudoIdAfter);
- }
- return next_node;
-}
+ if (!node.IsElementNode())
+ return FlatTreeTraversal::FirstChild(node);
-static Node* PseudoAwareFirstChild(const Node& node) {
- if (node.IsElementNode()) {
- const Element& current_element = ToElement(node);
- Node* first = current_element.GetPseudoElement(kPseudoIdBefore);
- if (first)
- return first;
- first = LayoutTreeBuilderTraversal::FirstChild(current_element);
- if (!first)
- first = current_element.GetPseudoElement(kPseudoIdAfter);
+ const Element& current_element = ToElement(node);
+ Node* first = current_element.GetPseudoElement(kPseudoIdBefore);
+ if (first)
return first;
- }
-
- return LayoutTreeBuilderTraversal::FirstChild(node);
+ first = FlatTreeTraversal::FirstChild(node);
+ if (!first)
+ first = current_element.GetPseudoElement(kPseudoIdAfter);
+ return first;
}
static Node* NextAncestorSibling(const Node& node, const Node* stay_within) {
- DCHECK(!PseudoAwareNextSibling(node));
+ DCHECK(!LayoutTreeBuilderTraversal::NextSibling(node));
DCHECK_NE(node, stay_within);
for (Node* parent_node = LayoutTreeBuilderTraversal::Parent(node);
parent_node;
parent_node = LayoutTreeBuilderTraversal::Parent(*parent_node)) {
if (parent_node == stay_within)
return nullptr;
- if (Node* next_node = PseudoAwareNextSibling(*parent_node))
+ if (Node* next_node = LayoutTreeBuilderTraversal::NextSibling(*parent_node))
return next_node;
}
return nullptr;
@@ -224,14 +183,14 @@ Node* LayoutTreeBuilderTraversal::NextSkippingChildren(
const Node* stay_within) {
if (node == stay_within)
return nullptr;
- if (Node* next_node = PseudoAwareNextSibling(node))
+ if (Node* next_node = NextSibling(node))
return next_node;
return NextAncestorSibling(node, stay_within);
}
Node* LayoutTreeBuilderTraversal::Next(const Node& node,
const Node* stay_within) {
- if (Node* child = PseudoAwareFirstChild(node))
+ if (Node* child = FirstChild(node))
return child;
return NextSkippingChildren(node, stay_within);
}
@@ -242,8 +201,8 @@ static Node* NextLayoutSiblingInternal(Node* node, int32_t& limit) {
if (!HasDisplayContentsStyle(*sibling))
return sibling;
- if (Node* inner =
- NextLayoutSiblingInternal(PseudoAwareFirstChild(*sibling), limit))
+ if (Node* inner = NextLayoutSiblingInternal(
+ LayoutTreeBuilderTraversal::FirstChild(*sibling), limit))
return inner;
if (limit == -1)
@@ -276,7 +235,7 @@ static Node* PreviousLayoutSiblingInternal(Node* node, int32_t& limit) {
return sibling;
if (Node* inner = PreviousLayoutSiblingInternal(
- PseudoAwareLastChild(*sibling), limit))
+ LayoutTreeBuilderTraversal::LastChild(*sibling), limit))
return inner;
if (limit == -1)
@@ -306,7 +265,7 @@ Node* LayoutTreeBuilderTraversal::PreviousLayoutSibling(const Node& node,
Node* LayoutTreeBuilderTraversal::FirstLayoutChild(const Node& node) {
int32_t limit = kTraverseAllSiblings;
- return NextLayoutSiblingInternal(PseudoAwareFirstChild(node), limit);
+ return NextLayoutSiblingInternal(FirstChild(node), limit);
}
LayoutObject* LayoutTreeBuilderTraversal::NextSiblingLayoutObject(
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h
index b73c21c00ee..be37bb84c45 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h
@@ -62,6 +62,7 @@ class CORE_EXPORT LayoutTreeBuilderTraversal {
static ContainerNode* Parent(const Node&, ParentDetails* = nullptr);
static ContainerNode* LayoutParent(const Node&, ParentDetails* = nullptr);
static Node* FirstChild(const Node&);
+ static Node* LastChild(const Node&);
static Node* NextSibling(const Node&);
static Node* NextLayoutSibling(const Node& node) {
int32_t limit = kTraverseAllSiblings;
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc
index 19d58178472..ad34ed77ff8 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal_test.cc
@@ -40,7 +40,7 @@ TEST_F(LayoutTreeBuilderTraversalTest, pseudos) {
const char* const kHtml =
"<style>"
"#top::before { content: \"foo\"; }"
- "#top::before { content: \"bar\"; }"
+ "#top::after { content: \"bar\"; }"
"</style>"
"<div id='top'></div>";
SetupSampleHTML(kHtml);
@@ -51,6 +51,10 @@ TEST_F(LayoutTreeBuilderTraversalTest, pseudos) {
EXPECT_EQ(before, LayoutTreeBuilderTraversal::Next(*top, nullptr));
EXPECT_EQ(after, LayoutTreeBuilderTraversal::NextSibling(*before));
EXPECT_EQ(nullptr, LayoutTreeBuilderTraversal::PreviousSibling(*before));
+ EXPECT_EQ(nullptr, LayoutTreeBuilderTraversal::NextSibling(*after));
+ EXPECT_EQ(before, LayoutTreeBuilderTraversal::PreviousSibling(*after));
+ EXPECT_EQ(before, LayoutTreeBuilderTraversal::FirstChild(*top));
+ EXPECT_EQ(after, LayoutTreeBuilderTraversal::LastChild(*top));
}
TEST_F(LayoutTreeBuilderTraversalTest, emptyDisplayContents) {
diff --git a/chromium/third_party/blink/renderer/core/dom/named_node_map.cc b/chromium/third_party/blink/renderer/core/dom/named_node_map.cc
index 5ba3f05cdf9..c6110494b41 100644
--- a/chromium/third_party/blink/renderer/core/dom/named_node_map.cc
+++ b/chromium/third_party/blink/renderer/core/dom/named_node_map.cc
@@ -82,14 +82,14 @@ Attr* NamedNodeMap::setNamedItemNS(Attr* attr,
return element_->setAttributeNodeNS(attr, exception_state);
}
-Attr* NamedNodeMap::item(unsigned index) const {
+Attr* NamedNodeMap::item(uint32_t index) const {
AttributeCollection attributes = element_->Attributes();
if (index >= attributes.size())
return nullptr;
return element_->EnsureAttr(attributes[index].GetName());
}
-size_t NamedNodeMap::length() const {
+uint32_t NamedNodeMap::length() const {
return element_->Attributes().size();
}
diff --git a/chromium/third_party/blink/renderer/core/dom/named_node_map.h b/chromium/third_party/blink/renderer/core/dom/named_node_map.h
index 7feaa384a17..905c349b782 100644
--- a/chromium/third_party/blink/renderer/core/dom/named_node_map.h
+++ b/chromium/third_party/blink/renderer/core/dom/named_node_map.h
@@ -58,8 +58,8 @@ class NamedNodeMap final : public ScriptWrappable {
Attr* setNamedItem(Attr*, ExceptionState&);
Attr* setNamedItemNS(Attr*, ExceptionState&);
- Attr* item(unsigned index) const;
- size_t length() const;
+ Attr* item(uint32_t index) const;
+ uint32_t length() const;
void NamedPropertyEnumerator(Vector<String>& names, ExceptionState&) const;
bool NamedPropertyQuery(const AtomicString&, ExceptionState&) const;
diff --git a/chromium/third_party/blink/renderer/core/dom/node.cc b/chromium/third_party/blink/renderer/core/dom/node.cc
index 5629f817085..32f58a1577b 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node.cc
@@ -876,10 +876,7 @@ static ContainerNode* GetReattachParent(Node& node) {
if (node.IsPseudoElement())
return node.ParentOrShadowHostNode();
if (node.IsChildOfV1ShadowHost()) {
- HTMLSlotElement* slot = RuntimeEnabledFeatures::SlotInFlatTreeEnabled()
- ? node.AssignedSlot()
- : node.FinalDestinationSlot();
- if (slot)
+ if (HTMLSlotElement* slot = node.AssignedSlot())
return slot;
}
if (node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost()) {
@@ -911,6 +908,8 @@ void Node::SetNeedsStyleRecalc(StyleChangeType change_type,
DCHECK(change_type != kNoStyleChange);
if (!InActiveDocument())
return;
+ if (!IsContainerNode() && !IsTextNode())
+ return;
TRACE_EVENT_INSTANT1(
TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
@@ -1120,7 +1119,7 @@ void Node::AttachLayoutTree(AttachContext& context) {
ClearNeedsStyleRecalc();
ClearNeedsReattachLayoutTree();
- if (AXObjectCache* cache = GetDocument().GetOrCreateAXObjectCache())
+ if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
cache->UpdateCacheAfterNodeIsAttached(this);
}
@@ -1181,10 +1180,7 @@ bool Node::IsStyledElement() const {
bool Node::CanParticipateInFlatTree() const {
// TODO(hayato): Return false for pseudo elements.
- if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled()) {
return !IsShadowRoot() && !IsActiveV0InsertionPoint(*this);
- }
- return !IsShadowRoot() && !IsActiveSlotOrActiveV0InsertionPoint();
}
bool Node::IsActiveSlotOrActiveV0InsertionPoint() const {
@@ -2261,15 +2257,15 @@ void Node::HandleLocalEvents(Event& event) {
return;
}
- FireEventListeners(&event);
+ FireEventListeners(event);
}
-void Node::DispatchScopedEvent(Event* event) {
- event->SetTrusted(true);
+void Node::DispatchScopedEvent(Event& event) {
+ event.SetTrusted(true);
EventDispatcher::DispatchScopedEvent(*this, event);
}
-DispatchEventResult Node::DispatchEventInternal(Event* event) {
+DispatchEventResult Node::DispatchEventInternal(Event& event) {
return EventDispatcher::DispatchEvent(*this, event);
}
@@ -2284,8 +2280,8 @@ void Node::DispatchSubtreeModifiedEvent() {
if (!GetDocument().HasListenerType(Document::kDOMSubtreeModifiedListener))
return;
- DispatchScopedEvent(MutationEvent::Create(EventTypeNames::DOMSubtreeModified,
- Event::Bubbles::kYes));
+ DispatchScopedEvent(*MutationEvent::Create(EventTypeNames::DOMSubtreeModified,
+ Event::Bubbles::kYes));
}
DispatchEventResult Node::DispatchDOMActivateEvent(int detail,
@@ -2293,16 +2289,16 @@ DispatchEventResult Node::DispatchDOMActivateEvent(int detail,
#if DCHECK_IS_ON()
DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
#endif
- UIEvent* event = UIEvent::Create();
- event->initUIEvent(EventTypeNames::DOMActivate, true, true,
- GetDocument().domWindow(), detail);
- event->SetUnderlyingEvent(&underlying_event);
- event->SetComposed(underlying_event.composed());
+ UIEvent& event = *UIEvent::Create();
+ event.initUIEvent(EventTypeNames::DOMActivate, true, true,
+ GetDocument().domWindow(), detail);
+ event.SetUnderlyingEvent(&underlying_event);
+ event.SetComposed(underlying_event.composed());
DispatchScopedEvent(event);
// TODO(dtapuska): Dispatching scoped events shouldn't check the return
// type because the scoped event could get put off in the delayed queue.
- return EventTarget::GetDispatchEventResult(*event);
+ return EventTarget::GetDispatchEventResult(event);
}
void Node::CreateAndDispatchPointerEvent(const AtomicString& mouse_event_name,
@@ -2347,7 +2343,7 @@ void Node::CreateAndDispatchPointerEvent(const AtomicString& mouse_event_name,
static_cast<WebInputEvent::Modifiers>(mouse_event.GetModifiers()));
pointer_event_init.setView(view);
- DispatchEvent(PointerEvent::Create(pointer_event_name, pointer_event_init));
+ DispatchEvent(*PointerEvent::Create(pointer_event_name, pointer_event_init));
}
// TODO(crbug.com/665924): This function bypasses all Blink event path.
@@ -2385,7 +2381,7 @@ void Node::DispatchMouseEvent(const WebMouseEvent& event,
->FiresTouchEvents(event.FromTouch())
: nullptr);
- DispatchEvent(MouseEvent::Create(
+ DispatchEvent(*MouseEvent::Create(
mouse_event_type, initializer, event.TimeStamp(),
event.FromTouch() ? MouseEvent::kFromTouch
: MouseEvent::kRealOrIndistinguishable,
@@ -2401,42 +2397,43 @@ void Node::DispatchSimulatedClick(Event* underlying_event,
void Node::DispatchInputEvent() {
// Legacy 'input' event for forms set value and checked.
- DispatchScopedEvent(Event::CreateBubble(EventTypeNames::input));
+ DispatchScopedEvent(*Event::CreateBubble(EventTypeNames::input));
}
-void Node::DefaultEventHandler(Event* event) {
- if (event->target() != this)
+void Node::DefaultEventHandler(Event& event) {
+ if (event.target() != this)
return;
- const AtomicString& event_type = event->type();
+ const AtomicString& event_type = event.type();
if (event_type == EventTypeNames::keydown ||
event_type == EventTypeNames::keypress) {
- if (event->IsKeyboardEvent()) {
- if (LocalFrame* frame = GetDocument().GetFrame())
+ if (event.IsKeyboardEvent()) {
+ if (LocalFrame* frame = GetDocument().GetFrame()) {
frame->GetEventHandler().DefaultKeyboardEventHandler(
- ToKeyboardEvent(event));
+ ToKeyboardEvent(&event));
+ }
}
} else if (event_type == EventTypeNames::click) {
- int detail =
- event->IsUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
- if (DispatchDOMActivateEvent(detail, *event) !=
+ int detail = event.IsUIEvent() ? ToUIEvent(event).detail() : 0;
+ if (DispatchDOMActivateEvent(detail, event) !=
DispatchEventResult::kNotCanceled)
- event->SetDefaultHandled();
+ event.SetDefaultHandled();
} else if (event_type == EventTypeNames::contextmenu &&
- event->IsMouseEvent()) {
+ event.IsMouseEvent()) {
if (Page* page = GetDocument().GetPage()) {
page->GetContextMenuController().HandleContextMenuEvent(
- ToMouseEvent(event));
+ ToMouseEvent(&event));
}
} else if (event_type == EventTypeNames::textInput) {
- if (event->HasInterface(EventNames::TextEvent)) {
- if (LocalFrame* frame = GetDocument().GetFrame())
+ if (event.HasInterface(EventNames::TextEvent)) {
+ if (LocalFrame* frame = GetDocument().GetFrame()) {
frame->GetEventHandler().DefaultTextInputEventHandler(
- ToTextEvent(event));
+ ToTextEvent(&event));
+ }
}
} else if (RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled() &&
- event_type == EventTypeNames::mousedown && event->IsMouseEvent()) {
- MouseEvent* mouse_event = ToMouseEvent(event);
- if (mouse_event->button() ==
+ event_type == EventTypeNames::mousedown && event.IsMouseEvent()) {
+ auto& mouse_event = ToMouseEvent(event);
+ if (mouse_event.button() ==
static_cast<short>(WebPointerProperties::Button::kMiddle)) {
if (EnclosingLinkEventParentOrSelf())
return;
@@ -2465,19 +2462,19 @@ void Node::DefaultEventHandler(Event* event) {
frame->GetEventHandler().StartMiddleClickAutoscroll(layout_object);
}
}
- } else if (event_type == EventTypeNames::mouseup && event->IsMouseEvent()) {
- MouseEvent* mouse_event = ToMouseEvent(event);
- if (mouse_event->button() ==
+ } else if (event_type == EventTypeNames::mouseup && event.IsMouseEvent()) {
+ auto& mouse_event = ToMouseEvent(event);
+ if (mouse_event.button() ==
static_cast<short>(WebPointerProperties::Button::kBack)) {
if (LocalFrame* frame = GetDocument().GetFrame()) {
if (frame->Client()->NavigateBackForward(-1))
- event->SetDefaultHandled();
+ event.SetDefaultHandled();
}
- } else if (mouse_event->button() ==
+ } else if (mouse_event.button() ==
static_cast<short>(WebPointerProperties::Button::kForward)) {
if (LocalFrame* frame = GetDocument().GetFrame()) {
if (frame->Client()->NavigateBackForward(1))
- event->SetDefaultHandled();
+ event.SetDefaultHandled();
}
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/node.h b/chromium/third_party/blink/renderer/core/dom/node.h
index 302eb60891c..0df2b7f1200 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.h
+++ b/chromium/third_party/blink/renderer/core/dom/node.h
@@ -634,6 +634,8 @@ class CORE_EXPORT Node : public EventTarget {
struct AttachContext {
STACK_ALLOCATED();
+
+ public:
// Keep track of previously attached in-flow box during attachment so that
// we don't need to backtrack past display:none/contents and out of flow
// objects when we need to do whitespace re-attachment.
@@ -710,7 +712,7 @@ class CORE_EXPORT Node : public EventTarget {
};
virtual InsertionNotificationRequest InsertedInto(
- ContainerNode* insertion_point);
+ ContainerNode& insertion_point);
virtual void DidNotifySubtreeInsertionsToDocument() {}
// Notifies the node that it is no longer part of the tree.
@@ -719,7 +721,7 @@ class CORE_EXPORT Node : public EventTarget {
// DOMNodeRemovedFromDocument DOM event, but does not require the overhead of
// event dispatching, and is called _after_ the node is removed from the tree.
//
- virtual void RemovedFrom(ContainerNode* insertion_point);
+ virtual void RemovedFrom(ContainerNode& insertion_point);
// FIXME(dominicc): This method is not debug-only--it is used by
// Tracing--rename it to something indicative.
@@ -769,12 +771,12 @@ class CORE_EXPORT Node : public EventTarget {
// Handlers to do/undo actions on the target node before an event is
// dispatched to it and after the event has been dispatched. The data pointer
// is handed back by the preDispatch and passed to postDispatch.
- virtual EventDispatchHandlingState* PreDispatchEventHandler(Event*) {
+ virtual EventDispatchHandlingState* PreDispatchEventHandler(Event&) {
return nullptr;
}
- virtual void PostDispatchEventHandler(Event*, EventDispatchHandlingState*) {}
+ virtual void PostDispatchEventHandler(Event&, EventDispatchHandlingState*) {}
- void DispatchScopedEvent(Event*);
+ void DispatchScopedEvent(Event&);
virtual void HandleLocalEvents(Event&);
@@ -796,7 +798,7 @@ class CORE_EXPORT Node : public EventTarget {
void DispatchInputEvent();
// Perform the default action for an event.
- virtual void DefaultEventHandler(Event*);
+ virtual void DefaultEventHandler(Event&);
virtual void WillCallDefaultEventHandler(const Event&);
// Should return true if this Node has activation behavior.
// https://dom.spec.whatwg.org/#eventtarget-activation-behavior
@@ -930,7 +932,7 @@ class CORE_EXPORT Node : public EventTarget {
protected:
enum ConstructionType {
- kCreateOther = kDefaultNodeFlags,
+ kCreateOther = kIsFinishedParsingChildrenFlag,
kCreateText = kDefaultNodeFlags | kIsTextFlag,
kCreateContainer =
kDefaultNodeFlags | kChildNeedsStyleRecalcFlag | kIsContainerFlag,
@@ -957,7 +959,7 @@ class CORE_EXPORT Node : public EventTarget {
RegisteredEventListener&) override;
void RemovedEventListener(const AtomicString& event_type,
const RegisteredEventListener&) override;
- DispatchEventResult DispatchEventInternal(Event*) override;
+ DispatchEventResult DispatchEventInternal(Event&) override;
bool HasRareData() const { return GetFlag(kHasRareDataFlag); }
diff --git a/chromium/third_party/blink/renderer/core/dom/node_test.cc b/chromium/third_party/blink/renderer/core/dom/node_test.cc
index 4e2a57ef638..2adc78d9813 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_test.cc
@@ -6,9 +6,11 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
+#include "third_party/blink/renderer/core/dom/comment.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder.h"
+#include "third_party/blink/renderer/core/dom/processing_instruction.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/shadow_root_init.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
@@ -315,4 +317,21 @@ TEST_F(NodeTest, HasMediaControlAncestor_MediaControls) {
EXPECT_TRUE(InitializeUserAgentShadowTree(node)->HasMediaControlAncestor());
}
+TEST_F(NodeTest, appendChildProcessingInstructionNoStyleRecalc) {
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
+ ProcessingInstruction* pi =
+ ProcessingInstruction::Create(GetDocument(), "A", "B");
+ GetDocument().body()->appendChild(pi, ASSERT_NO_EXCEPTION);
+ EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
+}
+
+TEST_F(NodeTest, appendChildCommentNoStyleRecalc) {
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
+ Comment* comment = Comment::Create(GetDocument(), "comment");
+ GetDocument().body()->appendChild(comment, ASSERT_NO_EXCEPTION);
+ EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/node_traversal.h b/chromium/third_party/blink/renderer/core/dom/node_traversal.h
index abeec1b5e6a..b3f22e655cf 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_traversal.h
+++ b/chromium/third_party/blink/renderer/core/dom/node_traversal.h
@@ -75,8 +75,9 @@ class NodeTraversal {
}
// Like next, but skips children and starts with the next sibling.
- static Node* NextSkippingChildren(const Node&);
- static Node* NextSkippingChildren(const Node&, const Node* stay_within);
+ CORE_EXPORT static Node* NextSkippingChildren(const Node&);
+ CORE_EXPORT static Node* NextSkippingChildren(const Node&,
+ const Node* stay_within);
static Node* FirstWithin(const Node& current) { return current.firstChild(); }
@@ -88,8 +89,9 @@ class NodeTraversal {
static Node* Previous(const Node&, const Node* stay_within = nullptr);
// Like previous, but skips children and starts with the next sibling.
- static Node* PreviousSkippingChildren(const Node&,
- const Node* stay_within = nullptr);
+ CORE_EXPORT static Node* PreviousSkippingChildren(
+ const Node&,
+ const Node* stay_within = nullptr);
// Like next, but visits parents after their children.
static Node* NextPostOrder(const Node&, const Node* stay_within = nullptr);
diff --git a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
index de81f256520..c20295e6608 100644
--- a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
+++ b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc
@@ -157,6 +157,8 @@ void ProcessingInstruction::Process(const String& href, const String& charset) {
loading_ = true;
if (is_xsl_) {
DCHECK(RuntimeEnabledFeatures::XSLTEnabled());
+ params.MutableResourceRequest().SetFetchRequestMode(
+ network::mojom::FetchRequestMode::kSameOrigin);
XSLStyleSheetResource::Fetch(params, GetDocument().Fetcher(), this);
} else {
params.SetCharset(charset.IsEmpty() ? GetDocument().Encoding()
@@ -234,9 +236,9 @@ void ProcessingInstruction::NotifyFinished(Resource* resource) {
}
Node::InsertionNotificationRequest ProcessingInstruction::InsertedInto(
- ContainerNode* insertion_point) {
+ ContainerNode& insertion_point) {
CharacterData::InsertedInto(insertion_point);
- if (!insertion_point->isConnected())
+ if (!insertion_point.isConnected())
return kInsertionDone;
String href;
@@ -250,16 +252,16 @@ Node::InsertionNotificationRequest ProcessingInstruction::InsertedInto(
return kInsertionDone;
}
-void ProcessingInstruction::RemovedFrom(ContainerNode* insertion_point) {
+void ProcessingInstruction::RemovedFrom(ContainerNode& insertion_point) {
CharacterData::RemovedFrom(insertion_point);
- if (!insertion_point->isConnected())
+ if (!insertion_point.isConnected())
return;
// No need to remove XSLStyleSheet from StyleEngine.
if (!DocumentXSLT::ProcessingInstructionRemovedFromDocument(GetDocument(),
this)) {
GetDocument().GetStyleEngine().RemoveStyleSheetCandidateNode(
- *this, *insertion_point);
+ *this, insertion_point);
}
if (sheet_) {
diff --git a/chromium/third_party/blink/renderer/core/dom/processing_instruction.h b/chromium/third_party/blink/renderer/core/dom/processing_instruction.h
index 04f6a6376c8..66e8683eb92 100644
--- a/chromium/third_party/blink/renderer/core/dom/processing_instruction.h
+++ b/chromium/third_party/blink/renderer/core/dom/processing_instruction.h
@@ -32,8 +32,8 @@ namespace blink {
class StyleSheet;
class EventListener;
-class ProcessingInstruction final : public CharacterData,
- private ResourceClient {
+class CORE_EXPORT ProcessingInstruction final : public CharacterData,
+ private ResourceClient {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(ProcessingInstruction);
@@ -78,8 +78,9 @@ class ProcessingInstruction final : public CharacterData,
NodeType getNodeType() const override;
Node* Clone(Document&, CloneChildrenFlag) const override;
- InsertionNotificationRequest InsertedInto(ContainerNode*) override;
- void RemovedFrom(ContainerNode*) override;
+ InsertionNotificationRequest InsertedInto(ContainerNode&) override;
+ void RemovedFrom(ContainerNode&) override;
+ void DetachLayoutTree(const AttachContext&) final {}
bool CheckStyleSheet(String& href, String& charset);
void Process(const String& href, const String& charset);
diff --git a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
index ac5aae97a88..c4b5eae5654 100644
--- a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -142,7 +142,7 @@ void PseudoElement::Dispose() {
Element* parent = ParentOrShadowHostElement();
GetDocument().AdoptIfNeeded(*this);
SetParentOrShadowHostNode(nullptr);
- RemovedFrom(parent);
+ RemovedFrom(*parent);
}
void PseudoElement::AttachLayoutTree(AttachContext& context) {
diff --git a/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h b/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h
index 335a846af5b..2ab87d442b5 100644
--- a/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h
@@ -85,7 +85,7 @@ inline PseudoElement* PseudoElementData::GetPseudoElement(
if (kPseudoIdAfter == pseudo_id)
return generated_after_;
// Workaround for CPU bug. This avoids compiler optimizing
-// this group of if conditions into switch. See crbug.com/855390.
+// this group of if conditions into switch. See http://crbug.com/855390.
#if defined(ARCH_CPU_ARMEL)
__asm__ volatile("");
#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/range.cc b/chromium/third_party/blink/renderer/core/dom/range.cc
index 332ba077493..f9cad1341ac 100644
--- a/chromium/third_party/blink/renderer/core/dom/range.cc
+++ b/chromium/third_party/blink/renderer/core/dom/range.cc
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/editing/set_selection_options.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/geometry/dom_rect_list.h"
@@ -823,7 +824,16 @@ DocumentFragment* Range::extractContents(ExceptionState& exception_state) {
return nullptr;
EventQueueScope scope;
- return ProcessContents(EXTRACT_CONTENTS, exception_state);
+ DocumentFragment* fragment = ProcessContents(EXTRACT_CONTENTS,
+ exception_state);
+ // |extractContents| has extended attributes [NewObject, DoNotTestNewObject],
+ // so it's better to have a test that exercises the following condition:
+ //
+ // !fragment || DOMDataStore::GetWrapper(fragment, isolate).IsEmpty()
+ //
+ // however, there is no access to |isolate| so far. So, we simply omit the
+ // test so far.
+ return fragment;
}
DocumentFragment* Range::cloneContents(ExceptionState& exception_state) {
@@ -975,23 +985,16 @@ DocumentFragment* Range::createContextualFragment(
// Algorithm:
// http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface
- DCHECK(string_or_html.IsString() ||
- RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
DCHECK(!string_or_html.IsNull());
Document& document = start_.Container().GetDocument();
- if (string_or_html.IsString() && document.RequireTrustedTypes()) {
- exception_state.ThrowTypeError(
- "This document requires `TrustedHTML` assignment.");
- return nullptr;
+ String markup =
+ TrustedHTML::GetString(string_or_html, &document, exception_state);
+ if (!exception_state.HadException()) {
+ return createContextualFragmentFromString(markup, exception_state);
}
-
- String markup = string_or_html.IsString()
- ? string_or_html.GetAsString()
- : string_or_html.GetAsTrustedHTML()->toString();
-
- return createContextualFragmentFromString(markup, exception_state);
+ return nullptr;
}
DocumentFragment* Range::createContextualFragmentFromString(
diff --git a/chromium/third_party/blink/renderer/core/dom/range.idl b/chromium/third_party/blink/renderer/core/dom/range.idl
index 86dc09b4a38..09fcdd407c1 100644
--- a/chromium/third_party/blink/renderer/core/dom/range.idl
+++ b/chromium/third_party/blink/renderer/core/dom/range.idl
@@ -50,7 +50,7 @@
[RaisesException] short compareBoundaryPoints(unsigned short how, Range sourceRange);
[RaisesException, CEReactions, CustomElementCallbacks] void deleteContents();
- [NewObject, RaisesException, CEReactions, CustomElementCallbacks] DocumentFragment extractContents();
+ [NewObject, RaisesException, CEReactions, CustomElementCallbacks, DoNotTestNewObject] DocumentFragment extractContents();
[NewObject, RaisesException, CEReactions, CustomElementCallbacks] DocumentFragment cloneContents();
[RaisesException, CEReactions, CustomElementCallbacks] void insertNode(Node node);
[RaisesException, CEReactions, CustomElementCallbacks] void surroundContents(Node newParent);
diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
index 7921474ad0b..5bdc1ac015a 100644
--- a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
+++ b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
@@ -120,9 +120,9 @@ void ScriptedAnimationController::DispatchEvents(
// tree.
probe::AsyncTask async_task(event_target->GetExecutionContext(), event);
if (LocalDOMWindow* window = event_target->ToLocalDOMWindow())
- window->DispatchEvent(event, nullptr);
+ window->DispatchEvent(*event, nullptr);
else
- event_target->DispatchEvent(event);
+ event_target->DispatchEvent(*event);
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
index 4e1d93ca401..fc562b24329 100644
--- a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
@@ -11,16 +11,18 @@
#include "third_party/blink/renderer/core/dom/idle_request_options.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_custom_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
namespace {
+enum class ShouldYield { YIELD, DONT_YIELD };
+
class MockScriptedIdleTaskControllerScheduler final : public ThreadScheduler {
public:
- MockScriptedIdleTaskControllerScheduler(bool should_yield)
- : should_yield_(should_yield) {}
+ explicit MockScriptedIdleTaskControllerScheduler(ShouldYield should_yield)
+ : should_yield_(should_yield == ShouldYield::YIELD) {}
~MockScriptedIdleTaskControllerScheduler() override = default;
// ThreadScheduler implementation:
@@ -57,8 +59,7 @@ class MockScriptedIdleTaskControllerScheduler final : public ThreadScheduler {
void RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) override {}
- void AddRAILModeObserver(
- scheduler::WebThreadScheduler::RAILModeObserver*) override {}
+ void AddRAILModeObserver(scheduler::WebRAILModeObserver*) override {}
scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
return nullptr;
@@ -74,37 +75,6 @@ class MockScriptedIdleTaskControllerScheduler final : public ThreadScheduler {
DISALLOW_COPY_AND_ASSIGN(MockScriptedIdleTaskControllerScheduler);
};
-class MockScriptedIdleTaskControllerThread final : public WebThread {
- public:
- MockScriptedIdleTaskControllerThread(bool should_yield)
- : scheduler_(should_yield) {}
- ~MockScriptedIdleTaskControllerThread() override = default;
- bool IsCurrentThread() const override { return true; }
- ThreadScheduler* Scheduler() const override { return &scheduler_; }
-
- void RunIdleTask() { scheduler_.RunIdleTask(); }
- bool HasIdleTask() const { return scheduler_.HasIdleTask(); }
-
- private:
- mutable MockScriptedIdleTaskControllerScheduler scheduler_;
- DISALLOW_COPY_AND_ASSIGN(MockScriptedIdleTaskControllerThread);
-};
-
-class MockScriptedIdleTaskControllerPlatform : public TestingPlatformSupport {
- public:
- MockScriptedIdleTaskControllerPlatform(bool should_yield)
- : thread_(should_yield) {}
- ~MockScriptedIdleTaskControllerPlatform() override = default;
- WebThread* CurrentThread() override { return &thread_; }
-
- void RunIdleTask() { thread_.RunIdleTask(); }
- bool HasIdleTask() const { return thread_.HasIdleTask(); }
-
- private:
- MockScriptedIdleTaskControllerThread thread_;
- DISALLOW_COPY_AND_ASSIGN(MockScriptedIdleTaskControllerPlatform);
-};
-
class MockIdleTask : public ScriptedIdleTaskController::IdleTask {
public:
MOCK_METHOD1(invoke, void(IdleDeadline*));
@@ -120,28 +90,34 @@ class ScriptedIdleTaskControllerTest : public testing::Test {
};
TEST_F(ScriptedIdleTaskControllerTest, RunCallback) {
- ScopedTestingPlatformSupport<MockScriptedIdleTaskControllerPlatform, bool>
- platform(false);
+ MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::DONT_YIELD);
+ ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler,
+ ThreadScheduler*>
+ platform(&scheduler);
+
NullExecutionContext execution_context;
ScriptedIdleTaskController* controller =
ScriptedIdleTaskController::Create(execution_context_);
Persistent<MockIdleTask> idle_task(new MockIdleTask());
IdleRequestOptions options;
- EXPECT_FALSE(platform->HasIdleTask());
+ EXPECT_FALSE(scheduler.HasIdleTask());
int id = controller->RegisterCallback(idle_task, options);
- EXPECT_TRUE(platform->HasIdleTask());
+ EXPECT_TRUE(scheduler.HasIdleTask());
EXPECT_NE(0, id);
EXPECT_CALL(*idle_task, invoke(testing::_));
- platform->RunIdleTask();
+ scheduler.RunIdleTask();
testing::Mock::VerifyAndClearExpectations(idle_task);
- EXPECT_FALSE(platform->HasIdleTask());
+ EXPECT_FALSE(scheduler.HasIdleTask());
}
TEST_F(ScriptedIdleTaskControllerTest, DontRunCallbackWhenAskedToYield) {
- ScopedTestingPlatformSupport<MockScriptedIdleTaskControllerPlatform, bool>
- platform(true);
+ MockScriptedIdleTaskControllerScheduler scheduler(ShouldYield::YIELD);
+ ScopedTestingPlatformSupport<TestingPlatformSupportWithCustomScheduler,
+ ThreadScheduler*>
+ platform(&scheduler);
+
NullExecutionContext execution_context;
ScriptedIdleTaskController* controller =
ScriptedIdleTaskController::Create(execution_context_);
@@ -152,11 +128,11 @@ TEST_F(ScriptedIdleTaskControllerTest, DontRunCallbackWhenAskedToYield) {
EXPECT_NE(0, id);
EXPECT_CALL(*idle_task, invoke(testing::_)).Times(0);
- platform->RunIdleTask();
+ scheduler.RunIdleTask();
testing::Mock::VerifyAndClearExpectations(idle_task);
// The idle task should have been reposted.
- EXPECT_TRUE(platform->HasIdleTask());
+ EXPECT_TRUE(scheduler.HasIdleTask());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
index dfc0422362e..d2e04506991 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -74,6 +74,7 @@ ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
type_(static_cast<unsigned short>(type)),
registered_with_parent_shadow_root_(false),
delegates_focus_(false),
+ slotting_(static_cast<unsigned short>(ShadowRootSlotting::kAuto)),
needs_distribution_recalc_(false),
unused_(0) {
if (IsV0())
@@ -111,6 +112,10 @@ Node* ShadowRoot::Clone(Document&, CloneChildrenFlag) const {
return nullptr;
}
+void ShadowRoot::SetSlotting(ShadowRootSlotting slotting) {
+ slotting_ = static_cast<unsigned short>(slotting);
+}
+
String ShadowRoot::InnerHTMLAsString() const {
return CreateMarkup(this, kChildrenOnly);
}
@@ -129,20 +134,11 @@ void ShadowRoot::SetInnerHTMLFromString(const String& markup,
void ShadowRoot::setInnerHTML(const StringOrTrustedHTML& stringOrHtml,
ExceptionState& exception_state) {
- DCHECK(stringOrHtml.IsString() ||
- RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
-
- if (stringOrHtml.IsString() && GetDocument().RequireTrustedTypes()) {
- exception_state.ThrowTypeError(
- "This document requires `TrustedHTML` assignment.");
- return;
+ String html =
+ TrustedHTML::GetString(stringOrHtml, &GetDocument(), exception_state);
+ if (!exception_state.HadException()) {
+ SetInnerHTMLFromString(html, exception_state);
}
-
- String html = stringOrHtml.IsString()
- ? stringOrHtml.GetAsString()
- : stringOrHtml.GetAsTrustedHTML()->toString();
-
- SetInnerHTMLFromString(html, exception_state);
}
void ShadowRoot::RecalcStyle(StyleRecalcChange change) {
@@ -186,10 +182,10 @@ void ShadowRoot::DetachLayoutTree(const AttachContext& context) {
}
Node::InsertionNotificationRequest ShadowRoot::InsertedInto(
- ContainerNode* insertion_point) {
+ ContainerNode& insertion_point) {
DocumentFragment::InsertedInto(insertion_point);
- if (!insertion_point->isConnected())
+ if (!insertion_point.isConnected())
return kInsertionDone;
if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled())
@@ -211,15 +207,15 @@ Node::InsertionNotificationRequest ShadowRoot::InsertedInto(
return kInsertionDone;
}
-void ShadowRoot::RemovedFrom(ContainerNode* insertion_point) {
- if (insertion_point->isConnected()) {
+void ShadowRoot::RemovedFrom(ContainerNode& insertion_point) {
+ if (insertion_point.isConnected()) {
if (NeedsSlotAssignmentRecalc())
GetDocument().GetSlotAssignmentEngine().Disconnected(*this);
GetDocument().GetStyleEngine().ShadowRootRemovedFromDocument(this);
if (registered_with_parent_shadow_root_) {
ShadowRoot* root = host().ContainingShadowRoot();
if (!root)
- root = insertion_point->ContainingShadowRoot();
+ root = insertion_point.ContainingShadowRoot();
if (root)
root->RemoveChildShadowRoot();
registered_with_parent_shadow_root_ = false;
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.h b/chromium/third_party/blink/renderer/core/dom/shadow_root.h
index fda132984ea..df9d2012820 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.h
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.h
@@ -48,6 +48,8 @@ class WhitespaceAttacher;
enum class ShadowRootType { V0, kOpen, kClosed, kUserAgent };
+enum class ShadowRootSlotting { kManual, kAuto };
+
class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(ShadowRoot);
@@ -106,8 +108,8 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
void AttachLayoutTree(AttachContext&) override;
void DetachLayoutTree(const AttachContext& = AttachContext()) override;
- InsertionNotificationRequest InsertedInto(ContainerNode*) override;
- void RemovedFrom(ContainerNode*) override;
+ InsertionNotificationRequest InsertedInto(ContainerNode&) override;
+ void RemovedFrom(ContainerNode&) override;
void SetNeedsAssignmentRecalc();
bool NeedsSlotAssignmentRecalc() const;
@@ -156,6 +158,12 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
void SetDelegatesFocus(bool flag) { delegates_focus_ = flag; }
bool delegatesFocus() const { return delegates_focus_; }
+ void SetSlotting(ShadowRootSlotting slotting);
+ bool IsManualSlotting() {
+ return slotting_ ==
+ static_cast<unsigned short>(ShadowRootSlotting::kManual);
+ }
+
bool ContainsShadowRoots() const { return child_shadow_root_count_; }
StyleSheetList& StyleSheets();
@@ -187,8 +195,9 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
unsigned short type_ : 2;
unsigned short registered_with_parent_shadow_root_ : 1;
unsigned short delegates_focus_ : 1;
+ unsigned short slotting_ : 1;
unsigned short needs_distribution_recalc_ : 1;
- unsigned short unused_ : 11;
+ unsigned short unused_ : 10;
DISALLOW_COPY_AND_ASSIGN(ShadowRoot);
};
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl b/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl
index 6bba7b9435c..0857f2ae500 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl
@@ -5,8 +5,10 @@
// Spec: https://w3c.github.io/webcomponents/spec/shadow/#shadowrootinit-dictionary
enum ShadowRootMode { "open", "closed" };
+enum ShadowRootSlottingMode { "manual", "auto" };
dictionary ShadowRootInit {
required ShadowRootMode mode;
boolean delegatesFocus;
+ [RuntimeEnabled=ManualSlotting] ShadowRootSlottingMode slotting;
};
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc b/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
index 4049af22401..8b3fe1c6e02 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
@@ -9,12 +9,10 @@
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
-#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
#include "third_party/blink/renderer/core/html/forms/html_opt_group_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/html_details_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
-#include "third_party/blink/renderer/core/html_names.h"
namespace blink {
@@ -39,6 +37,10 @@ void SlotAssignment::DidAddSlot(HTMLSlotElement& slot) {
++slot_count_;
needs_collect_slots_ = true;
+ if (owner_->IsManualSlotting()) {
+ DidAddSlotInternalInManualMode(slot);
+ return;
+ }
DCHECK(!slot_map_->Contains(slot.GetName()) ||
GetCachedFirstSlotWithoutAccessingNodeTree(slot.GetName()));
@@ -56,6 +58,15 @@ void SlotAssignment::DidRemoveSlot(HTMLSlotElement& slot) {
DCHECK_GT(slot_count_, 0u);
--slot_count_;
+ if (owner_->IsManualSlotting()) {
+ DCHECK(!needs_collect_slots_);
+ CallSlotChangeIfNeeded(slot);
+ needs_collect_slots_ = true;
+ // TODO(crbug.com/869308):Avoid calling Slots in order not to hit the
+ // DCHECK(!needs_collect_slots_)
+ Slots();
+ return;
+ }
needs_collect_slots_ = true;
DCHECK(GetCachedFirstSlotWithoutAccessingNodeTree(slot.GetName()));
@@ -85,7 +96,7 @@ void SlotAssignment::DidAddSlotInternal(HTMLSlotElement& slot) {
DCHECK(!old_active || old_active != slot);
// This might invalidate the slot_map's cache.
- slot_map_->Add(slot_name, &slot);
+ slot_map_->Add(slot_name, slot);
// This also ensures that TreeOrderedMap has a cache for the first element.
HTMLSlotElement* new_active = FindSlotByName(slot_name);
@@ -113,6 +124,17 @@ void SlotAssignment::DidAddSlotInternal(HTMLSlotElement& slot) {
}
}
+void SlotAssignment::DidAddSlotInternalInManualMode(HTMLSlotElement& slot) {
+ for (Node& child : NodeTraversal::ChildrenOf(owner_->host())) {
+ auto* change_slot = FindSlotChange(slot, child);
+ if (change_slot) {
+ slot.SignalSlotChange();
+ if (change_slot != slot)
+ change_slot->SignalSlotChange();
+ }
+ }
+}
+
void SlotAssignment::DidRemoveSlotInternal(
HTMLSlotElement& slot,
const AtomicString& slot_name,
@@ -132,7 +154,7 @@ void SlotAssignment::DidRemoveSlotInternal(
HTMLSlotElement* old_active =
GetCachedFirstSlotWithoutAccessingNodeTree(slot_name);
DCHECK(old_active);
- slot_map_->Remove(slot_name, &slot);
+ slot_map_->Remove(slot_name, slot);
// This also ensures that TreeOrderedMap has a cache for the first element.
HTMLSlotElement* new_active = FindSlotByName(slot_name);
DCHECK(!new_active || new_active != slot);
@@ -243,7 +265,16 @@ void SlotAssignment::RecalcAssignment() {
HTMLSlotElement* slot = nullptr;
if (!is_user_agent) {
- slot = FindSlotByName(child.SlotName());
+ if (owner_->IsManualSlotting()) {
+ for (auto a_slot : Slots()) {
+ if (a_slot->ContainsInAssignedNodesCandidates(child)) {
+ slot = a_slot;
+ break;
+ }
+ }
+ } else {
+ slot = FindSlotByName(child.SlotName());
+ }
} else {
if (user_agent_custom_assign_slot && ShouldAssignToCustomSlot(child)) {
slot = user_agent_custom_assign_slot;
@@ -332,12 +363,14 @@ const HeapVector<Member<HTMLSlotElement>>& SlotAssignment::Slots() {
return slots_;
}
-HTMLSlotElement* SlotAssignment::FindSlot(const Node& node) const {
+HTMLSlotElement* SlotAssignment::FindSlot(const Node& node) {
if (!node.IsSlotable())
return nullptr;
if (owner_->IsUserAgent())
return FindSlotInUserAgentShadow(node);
- return FindSlotByName(node.SlotName());
+ return owner_->IsManualSlotting()
+ ? FindFirstAssignedSlot(const_cast<Node&>(node))
+ : FindSlotByName(node.SlotName());
}
HTMLSlotElement* SlotAssignment::FindSlotByName(
@@ -356,6 +389,43 @@ HTMLSlotElement* SlotAssignment::FindSlotInUserAgentShadow(
return user_agent_default_slot;
}
+HTMLSlotElement* SlotAssignment::FindSlotChange(HTMLSlotElement& slot,
+ Node& child) {
+ HTMLSlotElement* found_this_slot = nullptr;
+ for (auto a_slot : Slots()) {
+ if (a_slot == slot) {
+ found_this_slot = &slot;
+ continue;
+ }
+ if (a_slot->ContainsInAssignedNodesCandidates(child)) {
+ if (found_this_slot) {
+ // case2 in DidRemoveSlotChange or DidAddSlotChange
+ return a_slot;
+ }
+ // case3 in DidRemoveSlotChange or DidAddSlotChange
+ return nullptr;
+ }
+ }
+ // case1 in DidRemoveSlotChange or DidAddSlotChange or no slot for the child
+ return found_this_slot;
+}
+
+void SlotAssignment::CallSlotChangeIfNeeded(HTMLSlotElement& slot) {
+ for (Node& child : NodeTraversal::ChildrenOf(owner_->host())) {
+ auto* change_slot = FindSlotChange(slot, child);
+ if (change_slot && change_slot != slot)
+ change_slot->SignalSlotChange();
+ }
+}
+
+HTMLSlotElement* SlotAssignment::FindFirstAssignedSlot(Node& node) {
+ for (auto slot : Slots()) {
+ if (slot->ContainsInAssignedNodesCandidates(node))
+ return slot;
+ }
+ return nullptr;
+}
+
void SlotAssignment::CollectSlots() {
DCHECK(needs_collect_slots_);
slots_.clear();
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment.h b/chromium/third_party/blink/renderer/core/dom/slot_assignment.h
index 579df6a18e3..9b27563fd86 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment.h
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment.h
@@ -7,10 +7,7 @@
#include "third_party/blink/renderer/core/dom/tree_ordered_map.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
namespace blink {
@@ -25,7 +22,7 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
}
// Relevant DOM Standard: https://dom.spec.whatwg.org/#find-a-slot
- HTMLSlotElement* FindSlot(const Node&) const;
+ HTMLSlotElement* FindSlot(const Node&);
HTMLSlotElement* FindSlotByName(const AtomicString& slot_name) const;
// DOM Standaard defines these two procedures:
@@ -46,6 +43,8 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
const AtomicString& new_value);
bool FindHostChildBySlotName(const AtomicString& slot_name) const;
+ void CallSlotChangeIfNeeded(HTMLSlotElement& slot);
+ HTMLSlotElement* FindSlotChange(HTMLSlotElement& slot, Node& child);
void Trace(blink::Visitor*);
@@ -67,11 +66,14 @@ class SlotAssignment final : public GarbageCollected<SlotAssignment> {
HTMLSlotElement* FindSlotInUserAgentShadow(const Node&) const;
+ HTMLSlotElement* FindFirstAssignedSlot(Node&);
+
void CollectSlots();
HTMLSlotElement* GetCachedFirstSlotWithoutAccessingNodeTree(
const AtomicString& slot_name);
void DidAddSlotInternal(HTMLSlotElement&);
+ void DidAddSlotInternalInManualMode(HTMLSlotElement&);
void DidRemoveSlotInternal(HTMLSlotElement&,
const AtomicString& slot_name,
SlotMutationType);
diff --git a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
index 53e1eb052f3..c2c719883ce 100644
--- a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
+++ b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
@@ -46,14 +46,7 @@ void SynchronousMutationNotifier::NotifyUpdateCharacterData(
unsigned offset,
unsigned old_length,
unsigned new_length) {
- // Using ForEachObserverWithoutChecks() instead of ForEachObserver() is
- // necessary because DocumentMarkerController::DidUpdateCharacterData ends up
- // calling SynchronousMutationNotifier::RemoveObserver, which is unsafe and
- // can result in memory corruption.
- //
- // TODO(crbug.com/862900): Fix DocumentMarkerController and switch to
- // ForEachObsever() here.
- ForEachObserverWithoutChecks([&](SynchronousMutationObserver* observer) {
+ ForEachObserver([&](SynchronousMutationObserver* observer) {
observer->DidUpdateCharacterData(character_data, offset, old_length,
new_length);
});
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc b/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc
index 00bf1d306d1..726880a1755 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc
+++ b/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc
@@ -76,9 +76,8 @@ inline bool KeyMatchesSlotName(const AtomicString& key,
ToHTMLSlotElement(element).GetName() == key;
}
-void TreeOrderedMap::Add(const AtomicString& key, Element* element) {
+void TreeOrderedMap::Add(const AtomicString& key, Element& element) {
DCHECK(key);
- DCHECK(element);
Map::AddResult add_result = map_.insert(key, new MapEntry(element));
if (add_result.is_new_entry)
@@ -91,9 +90,8 @@ void TreeOrderedMap::Add(const AtomicString& key, Element* element) {
entry->ordered_list.clear();
}
-void TreeOrderedMap::Remove(const AtomicString& key, Element* element) {
+void TreeOrderedMap::Remove(const AtomicString& key, Element& element) {
DCHECK(key);
- DCHECK(element);
Map::iterator it = map_.find(key);
if (it == map_.end())
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.h b/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.h
index 7598e47ea1a..8a5eba0d681 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.h
+++ b/chromium/third_party/blink/renderer/core/dom/tree_ordered_map.h
@@ -50,8 +50,8 @@ class TreeOrderedMap : public GarbageCollected<TreeOrderedMap> {
public:
static TreeOrderedMap* Create();
- void Add(const AtomicString&, Element*);
- void Remove(const AtomicString&, Element*);
+ void Add(const AtomicString&, Element&);
+ void Remove(const AtomicString&, Element&);
bool Contains(const AtomicString&) const;
bool ContainsMultiple(const AtomicString&) const;
@@ -98,7 +98,7 @@ class TreeOrderedMap : public GarbageCollected<TreeOrderedMap> {
class MapEntry : public GarbageCollected<MapEntry> {
public:
- explicit MapEntry(Element* first_element)
+ explicit MapEntry(Element& first_element)
: element(first_element), count(1) {}
void Trace(blink::Visitor*);
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
index 05b1cd910c2..ab7a51a9d28 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -137,7 +137,7 @@ const HeapVector<Member<Element>>& TreeScope::GetAllElementsById(
}
void TreeScope::AddElementById(const AtomicString& element_id,
- Element* element) {
+ Element& element) {
if (!elements_by_id_)
elements_by_id_ = TreeOrderedMap::Create();
elements_by_id_->Add(element_id, element);
@@ -145,7 +145,7 @@ void TreeScope::AddElementById(const AtomicString& element_id,
}
void TreeScope::RemoveElementById(const AtomicString& element_id,
- Element* element) {
+ Element& element) {
if (!elements_by_id_)
return;
elements_by_id_->Remove(element_id, element);
@@ -165,8 +165,8 @@ Node* TreeScope::AncestorInThisScope(Node* node) const {
return nullptr;
}
-void TreeScope::AddImageMap(HTMLMapElement* image_map) {
- const AtomicString& name = image_map->GetName();
+void TreeScope::AddImageMap(HTMLMapElement& image_map) {
+ const AtomicString& name = image_map.GetName();
if (!name)
return;
if (!image_maps_by_name_)
@@ -174,10 +174,10 @@ void TreeScope::AddImageMap(HTMLMapElement* image_map) {
image_maps_by_name_->Add(name, image_map);
}
-void TreeScope::RemoveImageMap(HTMLMapElement* image_map) {
+void TreeScope::RemoveImageMap(HTMLMapElement& image_map) {
if (!image_maps_by_name_)
return;
- const AtomicString& name = image_map->GetName();
+ const AtomicString& name = image_map.GetName();
if (!name)
return;
image_maps_by_name_->Remove(name, image_map);
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_scope.h b/chromium/third_party/blink/renderer/core/dom/tree_scope.h
index 63d0cb9206d..4542fc70052 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_scope.h
+++ b/chromium/third_party/blink/renderer/core/dom/tree_scope.h
@@ -76,8 +76,8 @@ class CORE_EXPORT TreeScope : public GarbageCollectedMixin {
const AtomicString&) const;
bool HasElementWithId(const AtomicString& id) const;
bool ContainsMultipleElementsWithId(const AtomicString& id) const;
- void AddElementById(const AtomicString& element_id, Element*);
- void RemoveElementById(const AtomicString& element_id, Element*);
+ void AddElementById(const AtomicString& element_id, Element&);
+ void RemoveElementById(const AtomicString& element_id, Element&);
Document& GetDocument() const {
DCHECK(document_);
@@ -86,8 +86,8 @@ class CORE_EXPORT TreeScope : public GarbageCollectedMixin {
Node* AncestorInThisScope(Node*) const;
- void AddImageMap(HTMLMapElement*);
- void RemoveImageMap(HTMLMapElement*);
+ void AddImageMap(HTMLMapElement&);
+ void RemoveImageMap(HTMLMapElement&);
HTMLMapElement* GetImageMap(const String& url) const;
Element* ElementFromPoint(double x, double y) const;
diff --git a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
index 59f1a048c3e..aef3967fea7 100644
--- a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
+++ b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
@@ -138,18 +138,25 @@ void V0InsertionPoint::RebuildDistributedChildrenLayoutTrees(
}
}
-void V0InsertionPoint::WillRecalcStyle(StyleRecalcChange change) {
- StyleChangeType style_change_type = kNoStyleChange;
-
- if (change > kInherit || GetStyleChangeType() > kLocalStyleChange)
- style_change_type = kSubtreeStyleChange;
- else if (change > kNoInherit)
- style_change_type = kLocalStyleChange;
- else
+void V0InsertionPoint::DidRecalcStyle(StyleRecalcChange change) {
+ if (!HasDistribution() || DistributedNodeAt(0)->parentNode() == this) {
+ // We either do not have distributed children or the distributed children
+ // are the fallback children. Fallback children have already been
+ // recalculated in ContainerNode::RecalcDescendantStyles().
return;
+ }
+
+ StyleChangeType style_change_type =
+ change == kForce ? kSubtreeStyleChange : kLocalStyleChange;
for (size_t i = 0; i < distributed_nodes_.size(); ++i) {
- distributed_nodes_.at(i)->SetNeedsStyleRecalc(
+ Node* node = distributed_nodes_.at(i);
+ if (change == kReattach && node->IsElementNode()) {
+ if (node->ShouldCallRecalcStyle(kReattach))
+ ToElement(node)->RecalcStyle(kReattach);
+ continue;
+ }
+ node->SetNeedsStyleRecalc(
style_change_type,
StyleChangeReasonForTracing::Create(
StyleChangeReason::kPropagateInheritChangeToDistributedNodes));
@@ -212,7 +219,7 @@ void V0InsertionPoint::ChildrenChanged(const ChildrenChange& change) {
}
Node::InsertionNotificationRequest V0InsertionPoint::InsertedInto(
- ContainerNode* insertion_point) {
+ ContainerNode& insertion_point) {
HTMLElement::InsertedInto(insertion_point);
if (ShadowRoot* root = ContainingShadowRoot()) {
if (!root->IsV1()) {
@@ -220,7 +227,7 @@ Node::InsertionNotificationRequest V0InsertionPoint::InsertedInto(
root->IsV1()))
root->SetNeedsDistributionRecalc();
if (CanBeActive() && !registered_with_shadow_root_ &&
- insertion_point->GetTreeScope().RootNode() == root) {
+ insertion_point.GetTreeScope().RootNode() == root) {
registered_with_shadow_root_ = true;
root->V0().DidAddInsertionPoint(this);
if (CanAffectSelector())
@@ -236,10 +243,10 @@ Node::InsertionNotificationRequest V0InsertionPoint::InsertedInto(
return kInsertionDone;
}
-void V0InsertionPoint::RemovedFrom(ContainerNode* insertion_point) {
+void V0InsertionPoint::RemovedFrom(ContainerNode& insertion_point) {
ShadowRoot* root = ContainingShadowRoot();
if (!root)
- root = insertion_point->ContainingShadowRoot();
+ root = insertion_point.ContainingShadowRoot();
if (root &&
!(RuntimeEnabledFeatures::IncrementalShadowDOMEnabled() && root->IsV1()))
@@ -250,7 +257,7 @@ void V0InsertionPoint::RemovedFrom(ContainerNode* insertion_point) {
ClearDistribution();
if (registered_with_shadow_root_ &&
- insertion_point->GetTreeScope().RootNode() == root) {
+ insertion_point.GetTreeScope().RootNode() == root) {
DCHECK(root);
registered_with_shadow_root_ = false;
root->V0().DidRemoveInsertionPoint(this);
diff --git a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
index 811fd7c0383..fde33dc516c 100644
--- a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
+++ b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
@@ -81,9 +81,9 @@ class CORE_EXPORT V0InsertionPoint : public HTMLElement {
V0InsertionPoint(const QualifiedName&, Document&);
bool LayoutObjectIsNeeded(const ComputedStyle&) const override;
void ChildrenChanged(const ChildrenChange&) override;
- InsertionNotificationRequest InsertedInto(ContainerNode*) override;
- void RemovedFrom(ContainerNode*) override;
- void WillRecalcStyle(StyleRecalcChange) override;
+ InsertionNotificationRequest InsertedInto(ContainerNode&) override;
+ void RemovedFrom(ContainerNode&) override;
+ void DidRecalcStyle(StyleRecalcChange) override;
private:
bool IsV0InsertionPoint() const =
diff --git a/chromium/third_party/blink/renderer/core/dom/visited_link_state.cc b/chromium/third_party/blink/renderer/core/dom/visited_link_state.cc
index 8045907b16d..5cedf79b315 100644
--- a/chromium/third_party/blink/renderer/core/dom/visited_link_state.cc
+++ b/chromium/third_party/blink/renderer/core/dom/visited_link_state.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/html_anchor_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
namespace blink {