Fix skipping CSP checks for styles when cloning nodes (#37465)

Cloned nodes were re-parsing already-parsed style attributes. As such,
they were also checking CSP, which shouldn't happen as the original node
already was checked for it.

Testing: The existing WPT test now mostly passes. It had two cases which
were passing in no browsers.
Fixes: Part of #4577

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
This commit is contained in:
Tim van der Lippe 2025-06-28 19:31:03 +02:00 committed by GitHub
parent 5311beb34a
commit e1c037815c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 32 additions and 32 deletions

View file

@ -44,6 +44,7 @@ use servo_arc::Arc;
use servo_config::pref;
use servo_url::ServoUrl;
use smallvec::SmallVec;
use style::attr::AttrValue;
use style::context::QuirksMode;
use style::dom::OpaqueNode;
use style::properties::ComputedValues;
@ -2713,6 +2714,27 @@ impl Node {
parent.owner_doc().remove_script_and_layout_blocker();
}
/// Ensure that for styles, we clone the already-parsed property declaration block.
/// This does two things:
/// 1. it uses the same fast-path as CSSStyleDeclaration
/// 2. it also avoids the CSP checks when cloning (it shouldn't run any when cloning
/// existing valid attributes)
fn compute_attribute_value_with_style_fast_path(attr: &Dom<Attr>, elem: &Element) -> AttrValue {
if *attr.local_name() == local_name!("style") {
if let Some(ref pdb) = *elem.style_attribute().borrow() {
let document = elem.owner_document();
let shared_lock = document.style_shared_lock();
let new_pdb = pdb.read_with(&shared_lock.read()).clone();
return AttrValue::Declaration(
(**attr.value()).to_owned(),
Arc::new(shared_lock.wrap(new_pdb)),
);
}
}
attr.value().clone()
}
/// <https://dom.spec.whatwg.org/#concept-node-clone>
pub(crate) fn clone(
node: &Node,
@ -2835,9 +2857,11 @@ impl Node {
let copy_elem = copy.downcast::<Element>().unwrap();
for attr in node_elem.attrs().iter() {
let new_value =
Node::compute_attribute_value_with_style_fast_path(attr, node_elem);
copy_elem.push_new_attribute(
attr.local_name().clone(),
attr.value().clone(),
new_value,
attr.name().clone(),
attr.namespace().clone(),
attr.prefix().cloned(),

View file

@ -577403,7 +577403,7 @@
]
],
"inline-style-allowed-while-cloning-objects.sub.html": [
"f702e6eb9d65fadfcb3ea9199146d835df036e04",
"32f711a9f15aa19a621c370e3abb26a425982ae9",
[
null,
{}

View file

@ -2,35 +2,8 @@
[non-HTML namespace]
expected: FAIL
[inline-style-allowed-while-cloning-objects 1]
expected: FAIL
[inline-style-allowed-while-cloning-objects 3]
expected: FAIL
[inline-style-allowed-while-cloning-objects 5]
expected: FAIL
[inline-style-allowed-while-cloning-objects 7]
expected: FAIL
[inline-style-allowed-while-cloning-objects 8]
expected: FAIL
[inline-style-allowed-while-cloning-objects 9]
expected: FAIL
[inline-style-allowed-while-cloning-objects 10]
expected: FAIL
[inline-style-allowed-while-cloning-objects 11]
expected: FAIL
[inline-style-allowed-while-cloning-objects 17]
expected: FAIL
[inline-style-allowed-while-cloning-objects 18]
expected: FAIL
[inline-style-allowed-while-cloning-objects 19]
expected: FAIL
[inline-style-allowed-while-cloning-objects 20]
expected: FAIL

View file

@ -80,6 +80,9 @@
test(function() {
assert_equals(clonedOps.style.background, "")
});
test(function() {
assert_equals(clonedOps.style.color, "red")
});
test(function() {
assert_equals(violetOps.style.background.match(/rgb\(238, 130, 238\)/)[0], "rgb(238, 130, 238)")
});