Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Aug 30, 2025

This PR implements comprehensive CSS variable dependency tracking and resolves property processing order issues to ensure proper variable resolution.

Key Changes

VariableReferenceTracker Class: Created a dedicated class to manage CSS variable dependencies with better separation of concerns:

  • Tracks which CSS properties depend on which variables
  • Provides change listener functionality for recomputation triggers
  • Manages dependency cleanup and variable change notifications
  • Moves variable tracking logic out of ComputedStyle for cleaner architecture

Simplified Custom Property Processing: Streamlined the two-pass CSS property processing:

  1. First pass: Process custom properties using setCustomProperty() directly without premature computation
  2. Second pass: Process regular properties with full access to all custom properties

Enhanced Method Updates: Updated resetProperties() and inheritProperties() to use the same two-pass approach, ensuring custom properties are always available before regular properties are processed.

Context-Based Inheritance: Utilizes the computed::Context for proper variable inheritance through context.inheritedStyle() rather than maintaining separate parent style references.

Enhanced Variable Resolution: Built on the existing dedicated CSS variable parser to provide:

  • Proper nested var() function support: var(--undefined, var(--fallback))blue
  • Recursive variable resolution with dependency tracking
  • Fallback chain support: var(--missing1, var(--missing2, var(--fallback)))

Example Usage

/* Variables are now processed before properties that use them */
.element {
  color: var(--primary-color);     /* Resolved after --primary-color is processed */
  --primary-color: blue;           /* Processed first, regardless of declaration order */
  border: 1px solid var(--primary-color); /* Also gets the blue value */
}

/* Nested variables work correctly */
.fallback-example {
  --fallback: red;
  color: var(--undefined, var(--fallback)); /* Resolves to red */
}

The VariableReferenceTracker enables future optimizations where changing a variable can automatically trigger re-computation of only the properties that depend on it, rather than re-processing the entire style.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 2 commits August 30, 2025 11:02
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
…e updates

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title [WIP] Support CSS variables in client/cssom and DOM Implement CSS Variables (Custom Properties) Support in CSSOM and DOM Aug 30, 2025
Copilot AI requested a review from yorkie August 30, 2025 11:09
static ComputedStyle Make(const CSSStyleDeclaration &style, std::shared_ptr<dom::Node> target_node);

// Create a `ComputedStyle` with CSS variable inheritance from parent style.
static ComputedStyle Make(const CSSStyleDeclaration &style, std::shared_ptr<dom::Node> target_node, const ComputedStyle *parent_style);
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot Remove this static method, just keep using make_shared<ComputedStyle> with computed context which contains the inherited properties.

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 static Make method with parent_style parameter as requested. The code now uses make_shared with computed context containing inherited properties. Fixed in commit 5e31d06.

std::unordered_map<std::string, std::string> custom_properties_;

// Parent style for CSS variable inheritance during computation
mutable const ComputedStyle *parent_style_context_ = nullptr;
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 maintain a parent computed style 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.

Removed the parent_style_context_ member variable as requested. The code no longer maintains a separate parent computed style reference. Fixed in commit 5e31d06.

}

// Resolve variables in the value for regular properties
string resolvedValue = resolveVariables(value, parent_style_context_);
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot You can get the the parent's style from context's inherited style via context.inheritedStyle().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the resolveVariables method to use context.inheritedStyle() instead of maintaining a parent style reference. The variable resolution now properly accesses the parent's custom properties through the context's inherited style. Fixed in commit 5e31d06.

yorkie and others added 2 commits August 30, 2025 19:30
…ent style reference

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

Copilot AI commented Aug 30, 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 30, 2025 11:41
ComputedStyle computedStyle;
computedStyle.setCustomProperty("--main-color", "red");

std::string resolved = computedStyle.resolveVariables("var(--main-color)");
Copy link
Collaborator

Choose a reason for hiding this comment

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

resolveVariables requires a 2nd argument computed::Context which stores the variables.

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 in commit a93f62e. Added the required computed::Context parameter to all resolveVariables calls in the test file. Created a createTestContext() helper function to provide the necessary context for test scenarios.

std::string resolved = computedStyle.resolveVariables("var(--main-color)");
REQUIRE(resolved == "red");

std::string complexResolved = computedStyle.resolveVariables("1px solid var(--main-color)");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto.

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 in commit a93f62e. Updated this resolveVariables call to include the computed::Context parameter.

{
ComputedStyle computedStyle;

std::string resolved = computedStyle.resolveVariables("var(--undefined, blue)");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ditto.

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 in commit a93f62e. Updated this resolveVariables call to include the computed::Context parameter.

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

Copilot AI commented Aug 30, 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 changed the title Implement CSS Variables (Custom Properties) Support in CSSOM and DOM Fix CSS Variables Tests to Use New Computed Context API Aug 30, 2025
Copilot AI requested a review from yorkie August 30, 2025 12:06

string ComputedStyle::resolveVariables(const string &value, const values::computed::Context &context) const
{
string result = value;
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot Create a tokenizer and parser at client/cssom/parsers instead of writing the logic at ComputedStyle

Copy link
Collaborator

Choose a reason for hiding this comment

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

And please make sure that the nested var() calls work well: var(--undefined, var(--fallback)) with --fallback: blue would produce var(--undefined, blue).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created a dedicated CSS variable tokenizer and parser at client/cssom/parsers/css_variable_parser.{hpp,cpp} instead of having the logic embedded in ComputedStyle. The new parser also properly handles nested var() calls with recursive resolution, so var(--undefined, var(--fallback)) with --fallback: blue correctly produces blue. Fixed in commit 86b0974.

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 in commit 86b0974. The new CSS variable parser now correctly handles nested var() calls with full recursive resolution. The example var(--undefined, var(--fallback)) with --fallback: blue properly produces blue instead of leaving partial unresolved variables.

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title Fix CSS Variables Tests to Use New Computed Context API Refactor CSS variables to use dedicated parser with proper nested var() support Aug 30, 2025
Copilot AI requested a review from yorkie August 30, 2025 13:27
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot Updating new custom properties from CSSStyleDeclaration (inserting --foo: a into custom_properties_) should be completed before computing properties or inherited properties, please update related code in this source.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented two-pass processing in the update() method. Custom properties (CSS variables) are now processed in the first pass before regular properties in the second pass. This ensures custom properties are available when resolving variables in regular properties. Fixed in commit 6c44cdd.


setCustomProperty(name, value);

// TODO: Re-resolve all properties that depend on this variable
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 introduce a variable reference tracker to complete this TODO.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Introduced variable reference tracker with dependency mapping. Added variable_dependencies_ member to track which properties use which variables, plus methods trackVariableDependency(), clearVariableDependencies(), and reResolveVariableDependents(). The computeProperty method now tracks variable dependencies before resolving variables. Fixed in commit 6c44cdd.

…essing

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title Refactor CSS variables to use dedicated parser with proper nested var() support Implement CSS variable dependency tracking and two-pass property processing Aug 30, 2025
Copilot AI requested a review from yorkie August 30, 2025 14:27
auto it = find(propertyName);
if (it != end())
// Only process custom properties in the first pass
if (propertyName.length() >= 2 && propertyName.substr(0, 2) == "--")
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot Simplify the following code that updates custom properties, just setting the custom property via setCustomProperty().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Simplified the custom property updates in the first pass to use setCustomProperty() directly instead of manual property management. Fixed in commit dc3cf57.

}

if (context.has_value())
computeProperty(propertyName, value, context.value());
Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to call computeProperty() at first pass that updates the custom properties only.

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 computeProperty() call from the first pass. The first pass now only sets custom properties without computing them. Fixed in commit dc3cf57.

return false;

// Two-pass approach: first process custom properties, then regular properties
// This ensures custom properties are available when resolving variables in regular properties
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot we need first-updating custom properties at resetProperties() and inheritProperties(), too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated both resetProperties() and inheritProperties() methods to use two-pass processing: custom properties are set first, then regular properties are processed. This ensures custom properties are available before they're referenced. Fixed in commit dc3cf57.

std::unordered_map<std::string, std::string> custom_properties_;

// Variable dependency tracking: maps variable names to properties that use them
std::unordered_map<std::string, std::unordered_set<std::string>> variable_dependencies_;
Copy link
Collaborator

Choose a reason for hiding this comment

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

@copilot Create a new class VariableReferenceTracker to manage the variable references, it provide a way to listen a variable changed (or removed) and recompute the related values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created a new VariableReferenceTracker class that manages variable dependencies and provides change listener functionality. The class handles dependency tracking, cleanup, and recomputation trigger mechanisms. The ComputedStyle class now uses this tracker instead of managing dependencies directly. Fixed in commit dc3cf57.

- Simplify custom property updates in first pass to use setCustomProperty() only
- Remove computeProperty() calls from first pass to avoid premature computation
- Update resetProperties() and inheritProperties() to handle custom properties first
- Create dedicated VariableReferenceTracker class to manage variable dependencies
- Move variable dependency tracking out of ComputedStyle for better separation of concerns

Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Copilot AI changed the title Implement CSS variable dependency tracking and two-pass property processing Implement CSS variable dependency tracking with VariableReferenceTracker and improved property processing Aug 30, 2025
Copilot AI requested a review from yorkie August 30, 2025 14:58
@yorkie yorkie marked this pull request as ready for review August 30, 2025 20:14
@yorkie yorkie merged commit 204c761 into main Aug 30, 2025
2 checks passed
@yorkie yorkie deleted the copilot/fix-262 branch August 30, 2025 20:22
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.

2 participants