Skip to content

Commit

Permalink
Reland "Add declarative AttributePart syntax parsing and functionality"
Browse files Browse the repository at this point in the history
This is a reland of commit 5a66ab6

The original was missing an initializer for the vector.

Original change's description:
> Add declarative AttributePart syntax parsing and functionality
>
> This adds the ability to parse declarative AttributePart syntax:
>
>   <div id={{}} class={{}}>
>
> The above snippet will now produce two "automatic" AttributeParts,
> which do not show up in getParts() output, but which can be updated
> while cloning via:
>
>   root.clone({attributeValues: ['id_value', 'class_value']});
>
> See [1] for more details.
>
> [1] https://docs.google.com/document/d/1z0YCj06-LFTWJlR_ayhtCOV2O4cJ5W1fHZbfckFsOdU/edit
>
> Bug: 1453291
> Change-Id: Icda4adbd3ce415999ff62e5a758124bd124188cb
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4930249
> Reviewed-by: Joey Arhar <jarhar@chromium.org>
> Commit-Queue: Mason Freed <masonf@chromium.org>
> Auto-Submit: Mason Freed <masonf@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1209190}

Bug: 1453291
Change-Id: I5c6887ff81e7d1f61d3fc8e48df3b34482c45e9e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4942513
Commit-Queue: Mason Freed <masonf@chromium.org>
Auto-Submit: Mason Freed <masonf@chromium.org>
Commit-Queue: Joey Arhar <jarhar@chromium.org>
Reviewed-by: Joey Arhar <jarhar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1210536}
  • Loading branch information
Mason Freed authored and Chromium LUCI CQ committed Oct 17, 2023
1 parent a622c5f commit 7800786
Show file tree
Hide file tree
Showing 19 changed files with 222 additions and 81 deletions.
2 changes: 2 additions & 0 deletions third_party/blink/renderer/bindings/generated_in_core.gni
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ generated_dictionary_sources_in_core = [
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_parse_from_string_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_part_init.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_part_init.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_part_root_clone_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_part_root_clone_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_pending_beacon_options.cc",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_pending_beacon_options.h",
"$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_performance_entry_filter_options.cc",
Expand Down
33 changes: 24 additions & 9 deletions third_party/blink/renderer/core/dom/attribute_part.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,42 @@ namespace blink {
// static
AttributePart* AttributePart::Create(PartRootUnion* root_union,
Node* node,
String local_name,
AtomicString local_name,
bool automatic,
const PartInit* init) {
const PartInit* init,
ExceptionState& exception_state) {
Element* element = DynamicTo<Element>(node);
if (!element) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"An AttributePart must be constructed on an Element.");
return nullptr;
}
return MakeGarbageCollected<AttributePart>(
*PartRoot::GetPartRootFromUnion(root_union), *node, local_name, automatic,
init);
*PartRoot::GetPartRootFromUnion(root_union), *element, local_name,
automatic, init);
}

AttributePart::AttributePart(PartRoot& root,
Node& node,
String local_name,
Element& element,
AtomicString local_name,
bool automatic,
const Vector<String> metadata)
: NodePart(root, node, !automatic, metadata),
: NodePart(root, element, !automatic, metadata),
local_name_(local_name),
automatic_(automatic) {}

Part* AttributePart::ClonePart(NodeCloningData& data, Node& node_clone) const {
DCHECK(IsValid());
return MakeGarbageCollected<AttributePart>(
data.CurrentPartRoot(), node_clone, local_name_, automatic_, metadata());
Element& element_clone = To<Element>(node_clone);
Part* new_part =
MakeGarbageCollected<AttributePart>(data.CurrentPartRoot(), element_clone,
local_name_, automatic_, metadata());
absl::optional<AtomicString> attribute_value = data.NextAttributeValue();
if (attribute_value) {
element_clone.setAttribute(local_name_, *attribute_value);
}
return new_part;
}

} // namespace blink
21 changes: 12 additions & 9 deletions third_party/blink/renderer/core/dom/attribute_part.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

namespace blink {

class ExceptionState;

// Implementation of the AttributePart class, which is part of the DOM Parts
// API. A AttributePart stores a reference to a single |Node| in the DOM tree.
class CORE_EXPORT AttributePart : public NodePart {
Expand All @@ -22,23 +24,24 @@ class CORE_EXPORT AttributePart : public NodePart {
public:
static AttributePart* Create(PartRootUnion* root_union,
Node* node,
String local_name,
AtomicString local_name,
bool automatic,
const PartInit* init);
const PartInit* init,
ExceptionState& exception_state);
AttributePart(PartRoot& root,
Node& node,
String local_name,
Element& element,
AtomicString local_name,
bool automatic,
const PartInit* init)
: AttributePart(root,
node,
element,
local_name,
automatic,
init && init->hasMetadata() ? init->metadata()
: Vector<String>()) {}
AttributePart(PartRoot& root,
Node& node,
String local_name,
Element& element,
AtomicString local_name,
bool automatic,
const Vector<String> metadata);
AttributePart(const AttributePart&) = delete;
Expand All @@ -48,11 +51,11 @@ class CORE_EXPORT AttributePart : public NodePart {
bool IncludeInPartsList() const override { return !automatic_; }

// AttributePart API
String localName() const { return local_name_; }
AtomicString localName() const { return local_name_; }
bool automatic() const { return automatic_; }

private:
String local_name_;
AtomicString local_name_;
bool automatic_;
};

Expand Down
2 changes: 1 addition & 1 deletion third_party/blink/renderer/core/dom/attribute_part.idl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

[RuntimeEnabled=DOMPartsAPI,Exposed=Window]
interface AttributePart : NodePart {
constructor(PartRoot root, Element element, DOMString localName, boolean automatic, optional PartInit init = {});
[RaisesException] constructor(PartRoot root, Element element, DOMString localName, boolean automatic, optional PartInit init = {});
// For now, HTML only, don't deal with prefix or namespaceURI.
readonly attribute DOMString localName;
readonly attribute boolean automatic;
Expand Down
4 changes: 3 additions & 1 deletion third_party/blink/renderer/core/dom/child_node_part.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ void ChildNodePart::disconnect() {
Part::disconnect();
}

PartRootUnion* ChildNodePart::clone(ExceptionState& exception_state) {
PartRootUnion* ChildNodePart::clone(PartRootCloneOptions* options,
ExceptionState& exception_state) {
// Since we're only cloning a part of the tree, not including this
// ChildNodePart's `root`, we use a temporary DocumentFragment and its
// PartRoot during the clone.
Expand All @@ -68,6 +69,7 @@ PartRootUnion* ChildNodePart::clone(ExceptionState& exception_state) {
auto& document = GetDocument();
auto* fragment = To<DocumentFragment>(DocumentFragment::Create(document));
NodeCloningData data{CloneOption::kPreserveDOMParts};
data.SetPartRootCloneOptions(options);
auto& fragment_part_root = fragment->getPartRoot();
data.PushPartRoot(fragment_part_root);
ContainerNode* new_parent = To<ContainerNode>(
Expand Down
9 changes: 7 additions & 2 deletions third_party/blink/renderer/core/dom/child_node_part.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CHILD_NODE_PART_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CHILD_NODE_PART_H_

#include "third_party/blink/renderer/bindings/core/v8/v8_part_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_node_string_trustedscript.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
Expand All @@ -19,6 +18,9 @@

namespace blink {

class PartInit;
class PartRootCloneOptions;

// Implementation of the ChildNodePart class, which is part of the DOM Parts
// API. A ChildNodePart stores a reference to a range of nodes within the
// children of a single parent |Node| in the DOM tree.
Expand Down Expand Up @@ -64,7 +66,10 @@ class CORE_EXPORT ChildNodePart : public Part, public PartRoot {

// ChildNodePart API
void disconnect() override;
PartRootUnion* clone(ExceptionState& exception_state);
PartRootUnion* clone(ExceptionState& exception_state) {
return clone(nullptr, exception_state);
}
PartRootUnion* clone(PartRootCloneOptions*, ExceptionState&);
ContainerNode* rootContainer() const override;
ContainerNode* parentNode() const { return previous_sibling_->parentNode(); }
Node* previousSibling() const { return previous_sibling_.Get(); }
Expand Down
4 changes: 3 additions & 1 deletion third_party/blink/renderer/core/dom/document_part_root.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ void DocumentPartRoot::Trace(Visitor* visitor) const {
PartRoot::Trace(visitor);
}

PartRootUnion* DocumentPartRoot::clone(ExceptionState&) {
PartRootUnion* DocumentPartRoot::clone(PartRootCloneOptions* options,
ExceptionState&) {
NodeCloningData data{CloneOption::kIncludeDescendants,
CloneOption::kPreserveDOMParts};
data.SetPartRootCloneOptions(options);
Node* clone = rootContainer()->Clone(rootContainer()->GetDocument(), data,
/*append_to*/ nullptr);
// http://crbug.com/1467847: clone may be null and can be hit by clusterfuzz.
Expand Down
7 changes: 6 additions & 1 deletion third_party/blink/renderer/core/dom/document_part_root.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace blink {

class PartRootCloneOptions;

// Implementation of the DocumentPartRoot class, which is part of the DOM Parts
// API. A DocumentPartRoot holds the parts for a Document or DocumentFragment.
// A Document always owns one DocumentPartRoot.
Expand All @@ -39,7 +41,10 @@ class CORE_EXPORT DocumentPartRoot : public ScriptWrappable, public PartRoot {
void Trace(Visitor*) const override;

// PartRoot API
PartRootUnion* clone(ExceptionState&);
PartRootUnion* clone(ExceptionState& exception_state) {
return clone(nullptr, exception_state);
}
PartRootUnion* clone(PartRootCloneOptions*, ExceptionState&);
ContainerNode* rootContainer() const override {
return root_container_.Get();
}
Expand Down
22 changes: 22 additions & 0 deletions third_party/blink/renderer/core/dom/node_cloning_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_CLONING_DATA_H_

#include "base/containers/enum_set.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_part_root_clone_options.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/child_node_part.h"
#include "third_party/blink/renderer/core/dom/node.h"
Expand All @@ -15,6 +16,8 @@
#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"

namespace blink {

Expand Down Expand Up @@ -67,9 +70,28 @@ class CORE_EXPORT NodeCloningData final {
return *cloned_part_root_stack_.back();
}

void SetPartRootCloneOptions(PartRootCloneOptions* options) {
if (options && options->hasAttributeValues()) {
attribute_values_.clear();
for (String value : options->attributeValues()) {
attribute_values_.push_back(AtomicString(value));
}
current_attribute_index_ = 0;
}
}

absl::optional<AtomicString> NextAttributeValue() {
if (current_attribute_index_ >= attribute_values_.size()) {
return absl::nullopt;
}
return attribute_values_[current_attribute_index_++];
}

private:
CloneOptionSet clone_options_;
HeapVector<Member<PartRoot>> cloned_part_root_stack_;
VectorOf<AtomicString> attribute_values_{};
wtf_size_t current_attribute_index_{0};
};

} // namespace blink
Expand Down
6 changes: 5 additions & 1 deletion third_party/blink/renderer/core/dom/part_root.idl
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ interface mixin PartRootMixin {
// document tree is cloned. In the case of a ChildPartRoot, only the children
// between `previous_node` and `next_node` are included, inclusive. The
// `clone()` method returns the cloned PartRoot.
[RaisesException] PartRoot clone();
[RaisesException] PartRoot clone(optional PartRootCloneOptions options);
// Return the root container for the PartRoot, which is the Document or
// DocumentFragment for a DocumentPartRoot, or the parent ContainerNode of
// a ChildNodePart.
readonly attribute Node rootContainer;
};

dictionary PartRootCloneOptions {
sequence<DOMString> attributeValues;
};

DocumentPartRoot includes PartRootMixin;
ChildNodePart includes PartRootMixin;

Expand Down
11 changes: 6 additions & 5 deletions third_party/blink/renderer/core/html/parser/atomic_html_token.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.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 {
Expand Down Expand Up @@ -205,9 +206,9 @@ class CORE_EXPORT AtomicHTMLToken {
return dom_part_data_->metadata_;
}

bool NeedsNodePart() const {
DCHECK(type_ == HTMLToken::kStartTag);
return needs_node_part_;
DOMPartsNeeded GetDOMPartsNeeded() {
DCHECK_EQ(type_, HTMLToken::kStartTag);
return dom_parts_needed_;
}

explicit AtomicHTMLToken(HTMLToken& token)
Expand All @@ -226,7 +227,7 @@ class CORE_EXPORT AtomicHTMLToken {
case HTMLToken::kEndOfFile:
break;
case HTMLToken::kStartTag:
needs_node_part_ = token.NeedsNodePart();
dom_parts_needed_ = token.GetDOMPartsNeeded();
[[fallthrough]];
case HTMLToken::kEndTag: {
self_closing_ = token.SelfClosing();
Expand Down Expand Up @@ -328,7 +329,7 @@ class CORE_EXPORT AtomicHTMLToken {

// For DOM Parts
std::unique_ptr<DOMPartData> dom_part_data_;
bool needs_node_part_{false};
DOMPartsNeeded dom_parts_needed_;

// For StartTag and EndTag
bool self_closing_ = false;
Expand Down

0 comments on commit 7800786

Please sign in to comment.