Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Aug 27, 2025

This PR completely replaces the Rust-based CSS selector parsing and matching system with a native C++ implementation in JSAR Runtime, while adding comprehensive support for structural pseudo-classes.

Implementation Details

Complete Rust Removal: The existing CSSStyleRule class now uses native C++ SelectorList directly instead of crates::css2::selectors::SelectorList, eliminating all Rust selector dependencies.

Document Query Integration: Both querySelector and querySelectorAll methods in document.cpp now use the C++ CSS selector parser (client_cssom::selectors::CSSelectorParser::parseSelectors) instead of the Rust implementation (crates::css2::parsing::parseSelectors), completing the migration.

Simplified Architecture:

  • Removed separate CSSStyleRuleNative class - modified existing CSSStyleRule directly
  • Eliminated adapter classes that were bridging C++ and Rust implementations
  • Streamlined matching system to use only C++ selector logic

Fixed CSS Selector Matching: Implemented proper right-to-left CSS selector matching algorithm to fix child and descendant combinators:

  • Child combinator (a > b) now correctly matches direct parent-child relationships
  • Descendant combinator (a b) now correctly matches ancestor-descendant relationships
  • Added matchesSelectorFromEnd() function that processes components from right to left as per CSS specification

Fixed CSS Selector Parsing: Resolved critical parsing issues where descendant selectors like "div p" were incorrectly parsed into only 2 components instead of the expected 3 components (div, descendant combinator, p):

  • Enhanced combinator detection to properly handle whitespace around explicit combinators (>, +, ~)
  • Fixed descendant combinator recognition for space-separated selectors
  • All combinators now parse correctly regardless of whitespace formatting

Comprehensive Pseudo-class Support: Added complete support for structural pseudo-classes:

  • :first-child - matches elements that are the first child of their parent
  • :last-child - matches elements that are the last child of their parent
  • :first-of-type - matches elements that are the first of their type among siblings
  • :last-of-type - matches elements that are the last of their type among siblings

CSS Selector Support: The native C++ parser handles all standard CSS selectors:

  • Basic selectors: div, .class, #id
  • Pseudo-classes: :hover, :focus, :active, :first-child, :last-child, :first-of-type, :last-of-type, :root
  • Pseudo-elements: ::before, ::after
  • Combinators: child (>), descendant (space), sibling (+, ~)
  • Complex combinations: div.class > p:hover, body, .foo > div#bar

Benefits

  • Reduced Complexity: Removed 630 lines of adapter/fallback code
  • Better Performance: Direct C++ implementation without Rust interop overhead
  • Cleaner API: Single implementation path with consistent interface
  • Maintainability: Eliminates dual parser maintenance burden
  • Correct CSS Behavior: Child and descendant selectors now work properly with accurate parsing
  • Enhanced Selector Coverage: Comprehensive structural pseudo-class support

Example Usage

// Document query methods now use C++ selectors directly and work correctly
auto element = document->querySelector("div.class > p:hover");     // Child selector now works
auto elements = document->querySelectorAll("body div");            // Descendant selector now works
auto firstChild = document->querySelector("p:first-child");        // Structural pseudo-classes work
auto lastOfType = document->querySelector("h1:last-of-type");      // Type-based pseudo-classes work

// CSS parsing now correctly identifies all components
auto result = CSSelectorParser::parseSelectors("div p");
// Returns 3 components: [LocalName(div), Combinator(Descendant), LocalName(p)]

// CSSStyleRule uses native C++ implementation
CSSStyleRule rule(rustStyleRule);
const auto& selectors = rule.selectors(); // Returns native C++ SelectorList
bool matches = rule.matches(htmlElement);

The implementation maintains full API compatibility while providing a cleaner, more efficient CSS selector system throughout the entire codebase with correctly functioning combinators, accurate component parsing, and comprehensive pseudo-class support.

Fixes #240.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits August 27, 2025 06:39
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement C/C++ CSS Selectors Parser and Integrate with StyleRule SelectorList Implement native C++ CSS selectors parser to replace Rust-based parsing Aug 27, 2025
Copilot AI requested a review from yorkie August 27, 2025 06:54
* Alternative implementation of CSSStyleRule that uses native C++ CSS selector parsing
* instead of the Rust-based parser. This addresses the TODO in the original CSSStyleRule.
*/
class CSSStyleRuleNative final : public CSSGroupingRule
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Just use this to replace, not creating another class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced CSSStyleRuleNative with direct modification to existing CSSStyleRule class. The separate native class has been removed and CSSStyleRule now uses C++ selectors directly instead of Rust selectors. Changes committed in 0c47774.

* Adapter class to make our native C++ SelectorList compatible
* with the existing crates::css2::selectors::SelectorList interface
*/
class SelectorListAdapter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot No need to introduce an adapter, you should use the new C++ SelectorList to replace the code that uses the old crates::css2::selectors::SelectorList.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the adapter classes completely. CSSStyleRule now uses the native C++ SelectorList directly instead of crates::css2::selectors::SelectorList. All adapter files (css_selector_adapter.hpp/cpp) have been deleted and matching system simplified to only use C++ implementation. Changes committed in 0c47774.

…nd separate classes

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title Implement native C++ CSS selectors parser to replace Rust-based parsing Replace Rust CSS selectors with native C++ implementation Aug 27, 2025
Copilot AI requested a review from yorkie August 27, 2025 11:20

shared_ptr<Element> Document::querySelector(const string &selectors)
{
// TODO(yorkie): use C++ selectors?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Complete this TODO, use the C/C++ css selector parser instead of crates::css2::parsing::parseSelectors here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completed the TODO by replacing crates::css2::parsing::parseSelectors with client_cssom::selectors::CSSelectorParser::parseSelectors in both querySelector and querySelectorAll methods. The C++ CSS selector parser now handles all document query operations. Changes committed in ae92b07.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Revert the changes in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted the package.json changes by restoring eslint from ^9.34.0 to ^9.27.0 and typescript from ^5.9.2 to ^5.1.6. Changes committed in ae92b07.

…ementation

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Aug 29, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • registry.npmmirror.com
    • Triggering command: npm ci (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from yorkie August 29, 2025 14:31
Copy link
Collaborator

@yorkie yorkie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot The following selectors doesn't work, please fix:

a > b { .. }
a b { ... }

…matching

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Aug 29, 2025

@copilot The following selectors doesn't work, please fix:

...

Fixed the child (a > b) and descendant (a b) selectors by implementing proper right-to-left CSS selector matching. The issue was that the matching algorithm was processing components left-to-right instead of following the CSS specification's right-to-left matching pattern. Added matchesSelectorFromEnd() function that correctly processes selector components from the rightmost element backwards. Changes committed in f05d365.

Copilot AI changed the title Replace Rust CSS selectors with native C++ implementation Replace Rust CSS selectors with native C++ implementation and fix child/descendant selectors Aug 29, 2025
Copilot AI requested a review from yorkie August 29, 2025 14:50
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Please make sure the descendant parsing work correctly, such as "div p" would be parsed into 3 components: div, descendant combinator and p, but the current implementation only returns 2 components.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the descendant parsing issue. The CSS selector parser now correctly parses "div p" into 3 components: div, descendant combinator, and p. Also fixed parsing of other combinators with whitespace like "div > p", "div + p", and "div ~ p". The issue was in the whitespace handling logic in both parseSingleSelector and parseCombinator functions. Changes committed in 2d7a881.

…binators with whitespace

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title Replace Rust CSS selectors with native C++ implementation and fix child/descendant selectors Replace Rust CSS selectors with native C++ implementation and fix CSS selector parsing Aug 29, 2025
Copilot AI requested a review from yorkie August 29, 2025 15:44
Copy link
Collaborator

@yorkie yorkie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support the following:

  • :first-child
  • :first-of-type
  • :last-child
  • :last-of-type

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Move to docs/internals/CSS_SELECTOR_PARSER_IMPL.md

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the documentation from docs/css-selector-parser.md to docs/internals/CSS_SELECTOR_PARSER_IMPL.md as requested. Changes committed in 55c2aab.

…ype pseudo-classes and move documentation

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Aug 29, 2025

Support the following:

  • :first-child
    ...

Added support for all four requested pseudo-classes. The CSS selector parser now correctly handles :first-child, :last-child, :first-of-type, and :last-of-type with proper matching logic that checks parent-child and sibling relationships. Changes committed in 55c2aab.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • registry.npmmirror.com
    • Triggering command: npm ci (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Replace Rust CSS selectors with native C++ implementation and fix CSS selector parsing Replace Rust CSS selectors with native C++ implementation and add comprehensive pseudo-class support Aug 29, 2025
Copilot AI requested a review from yorkie August 29, 2025 16:23
@yorkie yorkie requested a review from Copilot August 29, 2025 17:23
@yorkie yorkie marked this pull request as ready for review August 29, 2025 17:23
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR completely replaces the Rust-based CSS selector parsing and matching system with a native C++ implementation, while adding comprehensive support for structural pseudo-classes. The implementation includes fixes for CSS selector parsing issues (especially combinator handling) and introduces proper right-to-left CSS selector matching.

Key changes:

  • Native C++ CSS parser: Replaced Rust crates::css2::selectors with client_cssom::selectors::CSSelectorParser
  • Enhanced pseudo-class support: Added :first-child, :last-child, :first-of-type, :last-of-type support
  • Fixed selector parsing: Corrected combinator detection and parsing for descendant selectors like "div p"

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/client/css_selector_parser_tests.cpp Comprehensive test suite for the new C++ CSS selector parser covering all selector types and combinations
src/client/dom/document.cpp Updated querySelector and querySelectorAll to use C++ parser instead of Rust implementation
src/client/cssom/selectors/matching.hpp Modified function signatures to use C++ selector types and added new matching functions
src/client/cssom/selectors/matching.cpp Implemented structural pseudo-class helpers and right-to-left selector matching algorithm
src/client/cssom/selectors/css_selector_parser.hpp Complete C++ selector parser class definitions with comprehensive enum types and data structures
src/client/cssom/selectors/css_selector_parser.cpp Full implementation of CSS selector parsing logic with proper combinator handling
src/client/cssom/rules/css_style_rule.hpp Updated to use native C++ selectors and added element matching capability
fixtures/html/simple.html Test file updates to demonstrate structural pseudo-class functionality
docs/internals/CSS_SELECTOR_PARSER_IMPL.md Comprehensive documentation for the new CSS parser implementation

yorkie and others added 3 commits August 30, 2025 01:26
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@yorkie yorkie merged commit 19dafc6 into main Aug 29, 2025
2 checks passed
@yorkie yorkie deleted the copilot/fix-240 branch August 29, 2025 18:03
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.

Implement C/C++ CSS Selectors Parser and Integrate with StyleRule SelectorList

2 participants