chore: cherry-pick 3 changes from chromium (#50461)

* chore: cherry-pick 45c5a70d984d from chromium

Describe a vector of segments as "segments", not "tokens"

Bug: 487117772
Change-Id: I2dc132c4e618e398e1f8bdabc03a8d2ab6c118e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7606599
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1590040}

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

* chore: cherry-pick 05e4b544803c from chromium

Stringify CSSUnparsedValues via toString, as normal

Bug: 484751092
Change-Id: I5db45ad85f780c67a2ea3ba8482c390ebab10068
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7600415
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1590041}

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

* chore: cherry-pick 5efc7a0127a6 from chromium

Validate CSSUnparsedValues upon assignment

Fixed: 484751092
Change-Id: Id7f888a6df8c02ade24910900f5d01909cb2dfad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7595347
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1590110}

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

* chore: update patches

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

---------

Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
This commit is contained in:
Keeley Hammond
2026-03-24 18:42:34 -07:00
committed by GitHub
parent 2c8b6ee0c0
commit 17e4863d8e
4 changed files with 607 additions and 0 deletions

View File

@@ -155,3 +155,6 @@ cherry-pick-50b057660b4d.patch
cherry-pick-074d472db745.patch
validate_uniform_block_count_limits_at_compile_time_on_img.patch
feat_plumb_node_integration_in_worker_through_workersettings.patch
cherry-pick-45c5a70d984d.patch
cherry-pick-05e4b544803c.patch
cherry-pick-5efc7a0127a6.patch

View File

@@ -0,0 +1,204 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anders Hartvoll Ruud <andruud@chromium.org>
Date: Wed, 25 Feb 2026 03:25:14 -0800
Subject: Stringify CSSUnparsedValues via toString, as normal
CSSUnparsedValue exposes a special stringification function
ToUnparsedString() in addition to the regular toString().
The documentation says it returns "tokens without substituting
variables", but it's not clear what this means; we don't substitute
any variables in CSSStyleValue::toString() either.
This CL makes ToUnparsedString() private (and renames it).
Clients needing to serialize a CSSUnparsedValue can do so via
the normal toString() function. (If ToUnparsedString() existed
for performance reasons, that should have been documented.)
Also, the /**/-"fixup" pass over the value has been folded into
ToStringInternal(). This is to make it easy to find the canonical string
representation of this value within CSSUnparsedValue (without going
through a CSSValue).
The main point of this CL is to prepare for validating
the "argument grammar" of the value during the StyleValue-to-CSSValue
conversion in StylePropertyMap (which requires item (2) above).
We now jump through additional hoops to ultimately get a string
from the outside of CSSUnparsedValue, but there should otherwise
be no behavior change.
Bug: 484751092
Change-Id: I5db45ad85f780c67a2ea3ba8482c390ebab10068
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7600415
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1590041}
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
index dcc2eccbc84e6cd5710ab51cee2dab49661467c1..86d42c87a6bd10838a3e059c9227868e5bfc0798 100644
--- a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
+++ b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
@@ -19,12 +19,12 @@
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
-#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_color.h"
#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
@@ -152,8 +152,7 @@ TEST_F(CrossThreadStyleValueTest, CrossThreadUnparsedValueToCSSStyleValue) {
CSSStyleValue* style_value = value->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(),
CSSStyleValue::StyleValueType::kUnparsedType);
- EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToUnparsedString(),
- "Unparsed");
+ EXPECT_EQ(style_value->toString(), "Unparsed");
}
TEST_F(CrossThreadStyleValueTest, PassKeywordValueCrossThread) {
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
index 67a4afde452f94ffb9ecbaeea104a3997c65b7b3..9c6bb62d044f804b0ce7bc8df398d77695cf950c 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
@@ -124,16 +124,26 @@ IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
}
const CSSValue* CSSUnparsedValue::ToCSSValue() const {
- String unparsed_string = ToUnparsedString();
- CSSParserTokenStream stream(unparsed_string);
+ String unparsed_string = ToStringInternal();
- if (stream.AtEnd()) {
+ if (unparsed_string.IsNull()) {
return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
MakeGarbageCollected<CSSVariableData>());
}
- // The string we just parsed has /**/ inserted between every token
- // to make sure we get back the correct sequence of tokens.
+ // TODO(crbug.com/985028): We should probably propagate the CSSParserContext
+ // to here.
+ return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
+ CSSVariableData::Create(unparsed_string, false /* is_animation_tainted */,
+ false /* is_attr_tainted */,
+ false /* needs_variable_resolution */));
+}
+
+String CSSUnparsedValue::ToStringInternal() const {
+ String serialized = SerializeSegments();
+
+ // The serialization above defensively inserted /**/ between segments
+ // to make sure that e.g. ['foo', 'bar'] does not collapse into 'foobar'.
// The spec mentions nothing of the sort:
// https://drafts.css-houdini.org/css-typed-om-1/#unparsedvalue-serialization
//
@@ -147,6 +157,10 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
// the original contents of any comments will be lost, but Typed OM does
// not have anywhere to store that kind of data, so it is expected.
StringBuilder builder;
+ CSSParserTokenStream stream(serialized);
+ if (stream.AtEnd()) {
+ return g_null_atom;
+ }
CSSParserToken token = stream.ConsumeRaw();
token.Serialize(builder);
while (!stream.Peek().IsEOF()) {
@@ -156,17 +170,10 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
token = stream.ConsumeRaw();
token.Serialize(builder);
}
- String original_text = builder.ReleaseString();
-
- // TODO(crbug.com/985028): We should probably propagate the CSSParserContext
- // to here.
- return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
- CSSVariableData::Create(original_text, false /* is_animation_tainted */,
- false /* is_attr_tainted */,
- false /* needs_variable_resolution */));
+ return builder.ReleaseString();
}
-String CSSUnparsedValue::ToUnparsedString() const {
+String CSSUnparsedValue::SerializeSegments() const {
StringBuilder builder;
HeapHashSet<Member<const CSSUnparsedValue>> values_on_stack;
if (AppendUnparsedString(builder, values_on_stack)) {
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
index 5d1961b170f14ae21ca8f69b3c3cd8af28f4478a..ec7e3ed708f406d7a61fdb370b2eed8a8297cffb 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
@@ -67,15 +67,9 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
CSSStyleValue::Trace(visitor);
}
- // Unlike CSSStyleValue::toString(), this returns tokens without
- // substituting variables. There are extra /**/ inserted between
- // every token to ensure there are no ambiguities, which is fine
- // because this value is never presented directly to the user
- // (ToCSSValue() will parse to a token range and then re-serialize
- // using extra /**/ only where needed).
- String ToUnparsedString() const;
-
private:
+ String ToStringInternal() const;
+ String SerializeSegments() const;
// Return 'false' if there is a cycle in the serialization.
bool AppendUnparsedString(
StringBuilder&,
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
index f81fa39423a9235bc58e1600ca7a250affd3d9bb..2ee4dd7e591095b8460ca559b29b78e37ab71729 100644
--- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
+++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h"
#include <memory>
+
#include "base/synchronization/waitable_event.h"
#include "base/task/single_thread_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -13,7 +14,6 @@
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
-#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_color.h"
#include "third_party/blink/renderer/core/css/properties/longhands/custom_property.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
@@ -66,8 +67,7 @@ class PaintWorkletStylePropertyMapTest : public PageTestBase {
CSSStyleValue* style_value = data.at("--x")->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(),
CSSStyleValue::StyleValueType::kUnparsedType);
- EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToUnparsedString(),
- "50");
+ EXPECT_EQ(style_value->toString(), "50");
waitable_event->Signal();
}
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
index 1db0fd72478d708008f1b95a6aff206b28f60a6a..b52d8065c770aba822e9977c251c540643972629 100644
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -4872,7 +4872,7 @@ ComputedStyleUtils::CrossThreadStyleValueFromCSSStyleValue(
To<CSSUnsupportedColor>(style_value)->Value());
case CSSStyleValue::StyleValueType::kUnparsedType:
return std::make_unique<CrossThreadUnparsedValue>(
- To<CSSUnparsedValue>(style_value)->ToUnparsedString());
+ To<CSSUnparsedValue>(style_value)->toString());
default:
return std::make_unique<CrossThreadUnsupportedValue>(
style_value->toString());

View File

@@ -0,0 +1,199 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anders Hartvoll Ruud <andruud@chromium.org>
Date: Wed, 25 Feb 2026 03:24:19 -0800
Subject: Describe a vector of segments as "segments", not "tokens"
The specification uses the term "tokens" to refer to a sequence
of V8CSSUnparsedSegment objects, and CSSUnparsedValue has adopted
this terminology. While it is usually a good idea for Blink
to mirror the language used in specifications, "tokens" is very
confusing here, since it always means CSSParserTokens in every other
place in the style code.
Bug: 487117772
Change-Id: I2dc132c4e618e398e1f8bdabc03a8d2ab6c118e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7606599
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1590040}
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
index 3d43306dd902b3071637e5d5d0af26e5ee47f141..67a4afde452f94ffb9ecbaeea104a3997c65b7b3 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
@@ -24,12 +24,12 @@ String FindVariableName(CSSParserTokenStream& stream) {
V8CSSUnparsedSegment* VariableReferenceValue(
const StringView& variable_name,
- const HeapVector<Member<V8CSSUnparsedSegment>>& tokens) {
+ const HeapVector<Member<V8CSSUnparsedSegment>>& segments) {
CSSUnparsedValue* unparsed_value;
- if (tokens.size() == 0) {
+ if (segments.size() == 0) {
unparsed_value = nullptr;
} else {
- unparsed_value = CSSUnparsedValue::Create(tokens);
+ unparsed_value = CSSUnparsedValue::Create(segments);
}
CSSStyleVariableReferenceValue* variable_reference =
@@ -41,13 +41,13 @@ V8CSSUnparsedSegment* VariableReferenceValue(
HeapVector<Member<V8CSSUnparsedSegment>> ParserTokenStreamToTokens(
CSSParserTokenStream& stream) {
int nesting_level = 0;
- HeapVector<Member<V8CSSUnparsedSegment>> tokens;
+ HeapVector<Member<V8CSSUnparsedSegment>> segments;
StringBuilder builder;
while (stream.Peek().GetType() != kEOFToken) {
if (stream.Peek().FunctionId() == CSSValueID::kVar ||
stream.Peek().FunctionId() == CSSValueID::kEnv) {
if (!builder.empty()) {
- tokens.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(
+ segments.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(
builder.ReleaseString()));
}
@@ -57,7 +57,7 @@ HeapVector<Member<V8CSSUnparsedSegment>> ParserTokenStreamToTokens(
if (stream.Peek().GetType() == CSSParserTokenType::kCommaToken) {
stream.Consume();
}
- tokens.push_back(VariableReferenceValue(
+ segments.push_back(VariableReferenceValue(
variable_name, ParserTokenStreamToTokens(stream)));
} else {
if (stream.Peek().GetBlockType() == CSSParserToken::kBlockStart) {
@@ -73,10 +73,10 @@ HeapVector<Member<V8CSSUnparsedSegment>> ParserTokenStreamToTokens(
}
}
if (!builder.empty()) {
- tokens.push_back(
+ segments.push_back(
MakeGarbageCollected<V8CSSUnparsedSegment>(builder.ReleaseString()));
}
- return tokens;
+ return segments;
}
} // namespace
@@ -96,8 +96,8 @@ CSSUnparsedValue* CSSUnparsedValue::FromCSSVariableData(
V8CSSUnparsedSegment* CSSUnparsedValue::AnonymousIndexedGetter(
uint32_t index,
ExceptionState& exception_state) const {
- if (index < tokens_.size()) {
- return tokens_[index].Get();
+ if (index < segments_.size()) {
+ return segments_[index].Get();
}
return nullptr;
}
@@ -106,20 +106,20 @@ IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
uint32_t index,
V8CSSUnparsedSegment* segment,
ExceptionState& exception_state) {
- if (index < tokens_.size()) {
- tokens_[index] = segment;
+ if (index < segments_.size()) {
+ segments_[index] = segment;
return IndexedPropertySetterResult::kIntercepted;
}
- if (index == tokens_.size()) {
- tokens_.push_back(segment);
+ if (index == segments_.size()) {
+ segments_.push_back(segment);
return IndexedPropertySetterResult::kIntercepted;
}
exception_state.ThrowRangeError(
ExceptionMessages::IndexOutsideRange<unsigned>(
- "index", index, 0, ExceptionMessages::kInclusiveBound, tokens_.size(),
- ExceptionMessages::kInclusiveBound));
+ "index", index, 0, ExceptionMessages::kInclusiveBound,
+ segments_.size(), ExceptionMessages::kInclusiveBound));
return IndexedPropertySetterResult::kIntercepted;
}
@@ -182,14 +182,14 @@ bool CSSUnparsedValue::AppendUnparsedString(
return false; // Cycle.
}
values_on_stack.insert(this);
- for (unsigned i = 0; i < tokens_.size(); i++) {
+ for (unsigned i = 0; i < segments_.size(); i++) {
if (i) {
builder.Append("/**/");
}
- switch (tokens_[i]->GetContentType()) {
+ switch (segments_[i]->GetContentType()) {
case V8CSSUnparsedSegment::ContentType::kCSSVariableReferenceValue: {
const auto* reference_value =
- tokens_[i]->GetAsCSSVariableReferenceValue();
+ segments_[i]->GetAsCSSVariableReferenceValue();
builder.Append("var(");
builder.Append(reference_value->variable());
if (reference_value->fallback()) {
@@ -203,7 +203,7 @@ bool CSSUnparsedValue::AppendUnparsedString(
break;
}
case V8CSSUnparsedSegment::ContentType::kString:
- builder.Append(tokens_[i]->GetAsString());
+ builder.Append(segments_[i]->GetAsString());
break;
}
}
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
index c9dab7a0b3ffeaeb6b5d2ab50d876d40c38a760e..5d1961b170f14ae21ca8f69b3c3cd8af28f4478a 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
@@ -26,8 +26,8 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
public:
static CSSUnparsedValue* Create(
- const HeapVector<Member<V8CSSUnparsedSegment>>& tokens) {
- return MakeGarbageCollected<CSSUnparsedValue>(tokens);
+ const HeapVector<Member<V8CSSUnparsedSegment>>& segments) {
+ return MakeGarbageCollected<CSSUnparsedValue>(segments);
}
// Blink-internal constructor
@@ -37,14 +37,14 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
static CSSUnparsedValue* FromCSSValue(const CSSUnparsedDeclarationValue&);
static CSSUnparsedValue* FromCSSVariableData(const CSSVariableData&);
static CSSUnparsedValue* FromString(const String& string) {
- HeapVector<Member<V8CSSUnparsedSegment>> tokens;
- tokens.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(string));
- return Create(tokens);
+ HeapVector<Member<V8CSSUnparsedSegment>> segments;
+ segments.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(string));
+ return Create(segments);
}
explicit CSSUnparsedValue(
- const HeapVector<Member<V8CSSUnparsedSegment>>& tokens)
- : tokens_(tokens) {}
+ const HeapVector<Member<V8CSSUnparsedSegment>>& segments)
+ : segments_(segments) {}
CSSUnparsedValue(const CSSUnparsedValue&) = delete;
CSSUnparsedValue& operator=(const CSSUnparsedValue&) = delete;
@@ -60,10 +60,10 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
V8CSSUnparsedSegment* segment,
ExceptionState& exception_state);
- wtf_size_t length() const { return tokens_.size(); }
+ wtf_size_t length() const { return segments_.size(); }
void Trace(Visitor* visitor) const override {
- visitor->Trace(tokens_);
+ visitor->Trace(segments_);
CSSStyleValue::Trace(visitor);
}
@@ -81,7 +81,7 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
StringBuilder&,
HeapHashSet<Member<const CSSUnparsedValue>>& values_on_stack) const;
- HeapVector<Member<V8CSSUnparsedSegment>> tokens_;
+ HeapVector<Member<V8CSSUnparsedSegment>> segments_;
FRIEND_TEST_ALL_PREFIXES(CSSUnparsedDeclarationValueTest, MixedList);
};

View File

@@ -0,0 +1,201 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Anders Hartvoll Ruud <andruud@chromium.org>
Date: Wed, 25 Feb 2026 12:17:00 -0800
Subject: Validate CSSUnparsedValues upon assignment
CSS Typed OM has a concept of a value "matching a grammar" (or not)
upon assignment to a property [1]. For CSSUnparsedValues, we currently
don't perform any significant validation, and as a consequence
we allow "invalid" CSSUnparsedDeclarationValues to be created
(causing DCHECKs later in the pipeline).
This CL makes sure values can be parsed using CSSVariableParser::
ConsumeUnparsedDeclaration before assignment.
We're still not handling the value in the context of the destination
property, which we probably should. This is also a problem with
current state of things, however, so for now the goal is primarily
to avoid the DCHECKs in Issue 484751092.
Finally, I opened an issue against the specification [2], which
currently doesn't define any of this.
[1] https://drafts.css-houdini.org/css-typed-om-1/#create-an-internal-representation
[2] https://github.com/w3c/csswg-drafts/issues/13547
Fixed: 484751092
Change-Id: Id7f888a6df8c02ade24910900f5d01909cb2dfad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7595347
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1590110}
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl
index edfa73a57d30ebd4f9a7147702df42b836f7d82b..4442ba0872ca4c739596b546e6d3b600c5a31598 100644
--- a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/cssom_keywords.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
@@ -105,8 +106,8 @@ bool CSSOMTypes::PropertyCanTake(CSSPropertyID id,
: CSSPropertyName(id);
return unsupported_style_value->IsValidFor(name);
}
- if (value.GetType() == CSSStyleValue::kUnparsedType) {
- return true;
+ if (auto* unparsed_value = DynamicTo<CSSUnparsedValue>(value)) {
+ return unparsed_value->IsValidDeclarationValue();
}
switch (id) {
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
index 9c6bb62d044f804b0ce7bc8df398d77695cf950c..17a86e1292d76ff0b0c74b701750c0e972b4d885 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
@@ -4,11 +4,13 @@
#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
+#include "css_style_value.h"
#include "third_party/blink/renderer/core/css/css_unparsed_declaration_value.h"
#include "third_party/blink/renderer/core/css/css_variable_data.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+#include "third_party/blink/renderer/core/css/parser/css_variable_parser.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -123,6 +125,10 @@ IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
return IndexedPropertySetterResult::kIntercepted;
}
+bool CSSUnparsedValue::IsValidDeclarationValue() const {
+ return IsValidDeclarationValue(ToStringInternal());
+}
+
const CSSValue* CSSUnparsedValue::ToCSSValue() const {
String unparsed_string = ToStringInternal();
@@ -131,12 +137,40 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
MakeGarbageCollected<CSSVariableData>());
}
+ CHECK(IsValidDeclarationValue(unparsed_string));
+ // The call to IsValidDeclarationValue() above also creates a CSSVariableData
+ // to carry out its check. It would be nice to use that here, but WPTs
+ // expect leading whitespace to be preserved, even though it's not possible
+ // to create such declaration values normally.
+ CSSVariableData* variable_data =
+ CSSVariableData::Create(unparsed_string,
+ /*is_animation_tainted=*/false,
+ /*is_attr_tainted=*/false,
+ /*needs_variable_resolution=*/false);
+
// TODO(crbug.com/985028): We should probably propagate the CSSParserContext
// to here.
- return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
- CSSVariableData::Create(unparsed_string, false /* is_animation_tainted */,
- false /* is_attr_tainted */,
- false /* needs_variable_resolution */));
+ return MakeGarbageCollected<CSSUnparsedDeclarationValue>(variable_data);
+}
+
+bool CSSUnparsedValue::IsValidDeclarationValue(const String& string) {
+ CSSParserTokenStream stream(string);
+ bool important_unused;
+ // This checks that the value does not violate the "argument grammar" [1]
+ // of any substitution functions, and that it is a valid <declaration-value>
+ // otherwise.
+ //
+ // [1] https://drafts.csswg.org/css-values-5/#argument-grammar
+ //
+ // TODO(andruud): 'restricted_value' depends on the destination property.
+ return CSSVariableParser::ConsumeUnparsedDeclaration(
+ stream,
+ /*allow_important_annotation=*/false,
+ /*is_animation_tainted=*/false,
+ /*must_contain_variable_reference=*/false,
+ /*restricted_value=*/false,
+ /*comma_ends_declaration=*/false, important_unused,
+ *StrictCSSParserContext(SecureContextMode::kInsecureContext));
}
String CSSUnparsedValue::ToStringInternal() const {
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
index ec7e3ed708f406d7a61fdb370b2eed8a8297cffb..7fd66aed677e31046a1bd206854b2cbeac07c25b 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
@@ -48,6 +48,14 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
CSSUnparsedValue(const CSSUnparsedValue&) = delete;
CSSUnparsedValue& operator=(const CSSUnparsedValue&) = delete;
+ // True if this CSSUnparsedValue can be converted into
+ // a CSSUnparsedDeclarationValue.
+ //
+ // We may want to ban some invalid values earlier, see:
+ // https://github.com/w3c/csswg-drafts/issues/13547
+ bool IsValidDeclarationValue() const;
+
+ // Requires IsValidDeclarationValue()==true.
const CSSValue* ToCSSValue() const override;
StyleValueType GetType() const override { return kUnparsedType; }
@@ -68,6 +76,7 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
}
private:
+ static bool IsValidDeclarationValue(const String&);
String ToStringInternal() const;
String SerializeSegments() const;
// Return 'false' if there is a cycle in the serialization.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-invalid-untyped-value-crash.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-invalid-untyped-value-crash.html
new file mode 100644
index 0000000000000000000000000000000000000000..ce618bf38fe651297b969ffdc16e212dee6a3688
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-invalid-untyped-value-crash.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>Crash when setting invalid CSSUnparsedValue</title>
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/13547">
+<div id=target></div>
+<script>
+ let examples = [
+ 'var()',
+ 'var(,)',
+ 'var(0)',
+ 'env()',
+ 'env(,)',
+ 'env(0)',
+ 'attr()',
+ 'attr(,)',
+ 'attr(0)',
+ 'if()',
+ 'if(,)',
+ 'if(0)',
+ '--f()',
+ '--f(,)',
+ '--f(0)',
+ 'thing!!!',
+ 'var(--x) !important',
+ ];
+ // Some of the above cases may be valid. That's fine; just don't crash.
+
+ for (let e of examples) {
+ try {
+ let value = new CSSUnparsedValue([e]);
+ target.attributeStyleMap.set('width', value);
+ // One of the two above statements should likely throw an exception.
+ // If they don't, then we should at least not crash on get():
+ target.attributeStyleMap.get('width');
+ } catch (e) {
+ // Intentionally empty.
+ }
+ target.offsetTop;
+ }
+</script>