Skip to content

Conversation

@CGQAQ
Copy link
Contributor

@CGQAQ CGQAQ commented Jan 16, 2026

Motivation

This branch focuses on CSS correctness and performance in the bridge style engine, especially around stylesheet ordering/base URL, media-query evaluation, and style invalidation.

What changed

CSS correctness

  • Preserve author stylesheet DOM order and base URL handling so cascade order matches document order and relative URLs resolve consistently.
  • Fix style invalidation when elements transition from display:none to visible by forcing subtree style recalculation (prevents descendants from keeping stale styles).

Performance

  • Avoid per-element MediaQueryEvaluator construction during rule matching; reuse evaluator via match request context.
  • Speed up resize-triggered media-query style recalculation.

Refactors / cleanup

  • Remove legacy UA stylesheet handling in the bridge (drop embedded resources + associated plumbing).
  • Clarify cascade-origin bit manipulation (readability/maintainability).
  • Remove per-category logging system and build options.
  • Theme: sync system color scheme and overrides.
  • Fix build regressions introduced by the above changes.

Commits (in order)

  • fix(css): preserve author sheet DOM order and base URL
  • refactor(bridge): remove UA stylesheet handling
  • perf(bridge): avoid per-element MediaQueryEvaluator in rule matching
  • perf(bridge): speed up resize media-query style recalc
  • refactor(css): clarify cascade origin bit manipulation and improve comments
  • refactor(logging): remove per-category logging system and related build options
  • fix(theme): sync system color scheme and overrides
  • fix: build
  • fix(css): recompute subtree styles after display:none -> visible changes

Risk / compatibility notes

  • Large churn in bridge/core/css/style_engine.cc; please pay extra attention to regressions in selector matching, invalidation, and stylesheet ordering.
  • Removing UA stylesheet handling may change default rendering expectations if any callers relied on the old embedded UA sheets.

Testing

  • Not run locally in this PR draft (recommended: node scripts/run_bridge_unit_test.js).

@vercel
Copy link

vercel bot commented Jan 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
use-case Ready Ready Preview, Comment Jan 17, 2026 4:15am
vue_usecase Ready Ready Preview, Comment Jan 17, 2026 4:15am

Request Review

CGQAQ added 12 commits January 16, 2026 20:13
- Cache author stylesheets in DOM order via StyleEngine and match against that list to preserve cascade semantics and avoid matching inline/link sheets twice.
- Reuse cached UA default HTML stylesheet RuleSet instead of rebuilding per match.
- Track pseudo-element matches during normal collection; only resolve ::before/::after when `content` is present, prefilter pseudo selector buckets, and clear stale pseudo styles via a per-element sent mask.
- Initialize Document URL from script/module sourceURL (and Dart-provided URL for parseHTML/bytecode eval) so @import/url() never leak about:* bases across the bridge.
- Add gtests for pseudo style gating.
UA (user-agent) default styles are now provided by the Dart engine only.

This removes the native UA stylesheet pipeline from the C++ bridge:

- Drop CSSDefaultStyleSheets and bundled html.css/quirks.css resources

- Remove UA rule matching from StyleResolver / ElementRuleCollector

- Remove CMake CSS header generation and source list entry

- Update tests to stop resetting UA stylesheets
Blink-style declared-value recalc was rebuilding MediaQueryEvaluator for every element during MatchAuthorRules, which is expensive because it constructs dynamic MediaValues.

Changes:
- Reuse cached author-sheet RuleSets via StyleSheetContents::GetRuleSetShared() and only call EnsureRuleSet() (and thus create a MediaQueryEvaluator) on cache miss.
- Lazily construct a single MediaQueryEvaluator per MatchAuthorRules call instead of per element.
- Make MatchRequest store the common single RuleSet inline and iterate via ForEachRuleSet() to avoid per-match vector allocations.

Tests:
- node scripts/run_bridge_unit_test.js (fails: StyleEngineTest.SiblingInvalidationDirectAdjacentOnInsertion)
- Cache viewport width/height + DPR in ExecutingContext and feed via Page resize/DPR callbacks.
  MediaValues reads cached values first to avoid synchronous GetBindingProperty during MQ eval.
- Optimize cascade construction by avoiding per-property stable_sort in StyleCascade::AnalyzeMatchResult.
- Speed up selector rule collection: use std::sort (cascade_order is unique) and avoid allocating typed-only ID buckets.
- Minor: assign MatchResult directly into StyleCascade in StyleEngine.

Also remove noisy style update timing log previously used for profiling.

Tests:
- cmake --build bridge/cmake-build-macos-arm64 -j 8
- bridge/build/macos/lib/arm64/webf_css_unittests '--gtest_filter=StyleCascadeTest.*'

# Conflicts:
#	webf/example/macos/Runner.xcodeproj/project.pbxproj
…mments

- Update cascade origin documentation to provide clearer implementation details.
- Adjust bit manipulation logic for important origins to simplify flipping behavior while preserving transition bit.
- Refactor constants and inline methods for improved readability and consistency.
…ld options

- Eliminated WEBF_LOG_* macros and conditional logging logic.
- Simplified CMakeLists.txt by removing log category definitions and build-time switches.
- Streamlined logging implementation for maintenance and readability.
- Bridge: cache preferred color scheme in ExecutingContext and reuse it in MediaValuesDynamic::PreferredColorScheme

- Bridge: update cached scheme on nativeOnColorSchemeChanged to keep prefers-color-scheme media queries consistent

- Dart: on attach/brightness change, dispatch ColorSchemeChangeEvent and notify native Blink when not overridden

- Dart: make WebFController.isDarkMode fall back to PlatformDispatcher for consistent system brightness

- Example: keep DayNightSwitcherIcon in sync (app toggle sets override; system toggle clears override to null)

- macOS example: embed objective_c.framework for plugin linkage
…anges

- Ensure descendants of elements transitioning from `display:none` to visible recalculate styles to pick up inline styles and render correctly.
- Add handling for `IsDisplayNoneForStyleInvalidation` to trigger subtree recalculation and clear subtree flags.
- Dropped redundant `nativeOnColorSchemeChanged` call, as platform brightness changes no longer notify native Blink.
…equirement

- Ensure sibling invalidations occur even when restyle flags are not set by WebF.
- Adjust logic to skip unnecessary checks for indirect/direct adjacent rules before scheduling invalidations.
- Add safe handling for inserting/removing sibling elements when selector matching is incomplete.
And run generate_ios_mirror_ccs.js --fix

- Added logic to detect and remove orphan wrappers no longer matching source files or configuration.
- Extended wrapper support to include `.mm` files.
- Updated `--fix` flag to remove orphans and prune empty directories.
- Improved dry-run mode to clarify removal actions without modifying files.
@andycall andycall merged commit 09adfed into main Jan 17, 2026
34 of 37 checks passed
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.

3 participants