perf(runtime): skip empty style mutation followups

Handle empty CSP input in a small inline entry and delegate nonempty
batches to a separate function. The mutation finisher only checks
whether the DOM changed before invoking CSP followups.

Skip processing empty stylesheet owner changes at the mutation finisher.
Continue applying pending stylesheet CSS projections and slotchange events.

A/B against the previous caller-side CSP guard on the resulting branch
(fixed local WeChat HTML; release; JS/CSS/subframes disabled; 200 balanced
randomized pairs) measured 142.39 -> 141.29 ms.
Paired saving: 0.34 ms; 95% bootstrap CI:
[-0.87, 1.57] ms. The confidence interval includes zero; no resolved performance gain.
All 400 measured Markdown outputs were identical.

Validation:
- cargo fmt --all
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo nextest run --no-fail-fast (19,490 passed, 16 skipped)
This commit is contained in:
ldm0
2026-10-07 03:28:07 +08:00
committed by Donough Liu
parent 62716f0997
commit d4a6234ca0
2 changed files with 25 additions and 1 deletions
@@ -1809,7 +1809,7 @@ pub(super) fn finish_runtime_mutation_effects(
);
}
runtime.apply_pending_stylesheet_source_css_projections(scope, host_ptr);
if changed {
if changed && !stylesheet_owner_changes.is_empty() {
let mut prime_result = ConnectedStyleLoadPrimeResult::default();
let prepared_owner_changes =
runtime.prepare_stylesheet_owner_runtime_changes(&stylesheet_owner_changes);
@@ -225,6 +225,7 @@ impl DocumentPolicyContainer {
}
impl DocumentRuntime {
#[inline]
pub(super) fn apply_style_csp_mutation_followups<'s>(
&mut self,
scope: &mut v8::PinScope<'s, '_>,
@@ -232,6 +233,29 @@ impl DocumentRuntime {
attribute_mutations: &[super::mutation_commands::InlineStyleAttributeCspMutation],
connected_roots: &[DomHandle],
stylesheet_owner_changes: &[crate::dom::native::DomStylesheetOwnerChange],
) {
if attribute_mutations.is_empty()
&& connected_roots.is_empty()
&& stylesheet_owner_changes.is_empty()
{
return;
}
self.apply_nonempty_style_csp_mutation_followups(
scope,
host_ptr,
attribute_mutations,
connected_roots,
stylesheet_owner_changes,
);
}
fn apply_nonempty_style_csp_mutation_followups<'s>(
&mut self,
scope: &mut v8::PinScope<'s, '_>,
host_ptr: *mut JsContextHost,
attribute_mutations: &[super::mutation_commands::InlineStyleAttributeCspMutation],
connected_roots: &[DomHandle],
stylesheet_owner_changes: &[crate::dom::native::DomStylesheetOwnerChange],
) {
let mut checked_attributes = HashSet::new();
for mutation in attribute_mutations {