Skip to content

Harvest inline <style> CSS from the live DOM for Baseline feature detection - #330

Open
smsnedden wants to merge 3 commits into
cloudflare:mainfrom
smsnedden:baseline-css-inline-live
Open

Harvest inline <style> CSS from the live DOM for Baseline feature detection#330
smsnedden wants to merge 3 commits into
cloudflare:mainfrom
smsnedden:baseline-css-inline-live

Conversation

@smsnedden

Copy link
Copy Markdown
Contributor

Second slice of the --baseline CSS analysis feature. This PR adds extraction of inline <style> blocks by reading them from a page's live DOM; CSS feature detection (css-tree) and Baseline lookup (web-features) over the collected sources follow in later PRs. (External stylesheets landed in #317.)

Like the external extractor, harvestInlineStyles is intentionally not wired into the CLI or launchTest yet. It is designed to be driven by the Baseline detection pass — a live second-pass browser navigation (the same pass that performs JS API detection) — which is productionized in a follow-up PR. Reading inline CSS there keeps all live-DOM detection in one place and one navigation, and runs it once: Baseline analyzes browser-agnostic source CSS, so there is no need to repeat it across the browser matrix. Keeping this slice separate keeps each PR small and reviewable.

Why read the live DOM instead of parsing the HTML? So that <style> blocks a page injects at runtime (e.g. via JavaScript) are captured — static HTML parsing would miss them. The browser is already running in the detection pass, so it is the ground truth for what the page actually applied.

Changes

harvestInlineStyles(page): Promise<CSSSource[]> (src/baselineCssExtract.ts)

Reads inline CSS from a loaded page's live DOM:

  • Collects the text of every <style> element in document order, returning one CSSSource per non-empty block (the same { css, file } shape as extractCSSFromHar).
  • Skips empty / whitespace-only blocks.
  • The read is strictly read-only — a single page.evaluate that reads <style> text with no DOM mutation and no layout-triggering reads — so it can run inside the shared detection pass without interfering with co-located instrumentation or page state.

Out of scope (documented in the JSDoc; may be revisited later): only <style> element text is read, so CSS with no <style> text — rules added via CSSStyleSheet.insertRule() or constructable adoptedStyleSheets — is not captured, nor are <style> elements inside shadow roots (querySelectorAll does not pierce shadow DOM) or <template> content.

Types (src/types.ts)

  • Document CSSSource: css is the field that gets parsed; file is a provenance label for reporting — a URL for external stylesheets, a page-derived label (e.g. https://example.com/ (inline style #1)) for inline blocks. It is a display string, not a URL to parse.

Tests

Extends packages/telescope/__tests__/baselineCssExtract.test.ts with 6 tests parameterized per rendering engine (chromium/firefox/webkit; Firefox-only in CI), driving a real page via setContent:

  • Single <style> block extracted as one source
  • Multiple blocks preserved in document order
  • <style> injected by JavaScript after load is captured (the case static parsing misses)
  • No <style> blocks → empty array
  • Empty / whitespace-only blocks skipped
  • Read-only guarantee: harvesting leaves the document markup unchanged

…ection

Add harvestInlineStyles() which reads inline <style> blocks from a page's
live DOM and returns them as CSSSource[], the same shape produced by
extractCSSFromHar(). Reading the rendered document rather than parsing the
HTML captures <style> blocks injected at runtime by JavaScript, which static
parsing would miss.

The read is strictly read-only (no DOM mutation, no layout), so a later change
can run it after metrics collection without perturbing performance
measurements.

This is the second slice of the Baseline (--baseline) CSS analysis feature;
wiring it into the test run and CSS feature detection over the collected
sources follow in later changes.

- Add harvestInlineStyles() in baselineCssExtract.ts and update the
  extractCSSFromHar() doc to reference it
- Document CSSSource.file as a provenance label (URL for external stylesheets,
  page-derived label for inline blocks) and css as the parsed field
- Add engine-parameterized tests (chromium/firefox/webkit) covering static and
  JS-injected <style> blocks, document order, empty-block skipping, and a
  read-only (no DOM mutation) guarantee
The harvest will run inside the Baseline detection pass (alongside JS API
detection), not the performance run, so tie the read-only guarantee to not
interfering with co-located instrumentation rather than to metrics safety.
The 'does not modify the DOM' test still described the read-only guarantee in
terms of metrics collection; match the reframed harvestInlineStyles JSDoc so the
rationale is consistent across source and tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant