Skip to content

LibWeb: Make ComputedValues the durable computed style#10712

Merged
awesomekling merged 6 commits into
LadybirdBrowser:masterfrom
awesomekling:big-css
Jul 16, 2026
Merged

LibWeb: Make ComputedValues the durable computed style#10712
awesomekling merged 6 commits into
LadybirdBrowser:masterfrom
awesomekling:big-css

Conversation

@awesomekling

@awesomekling awesomekling commented Jul 16, 2026

Copy link
Copy Markdown
Member

Style computation currently produces a generic ComputedProperties array of StyleValue objects and stores it on elements. Layout then projects that array into the typed ComputedValues used by layout and painting. This represents the same computed style twice, places CSS value conversion in layout, and makes typed style information depend on layout-node creation.

This is also the wrong boundary for the planned Rust migration. Porting StyleComputer in the current architecture would require migrating or bridging the durable generic property array and much of its downstream machinery. The intended boundary is simpler: style computation should return one immutable, typed result that existing C++ consumers can use directly.

Invert the relationship between these types. Keep ComputedProperties as a transient workspace used internally while applying the cascade, resolving inheritance, and calculating one style. At the end of computation, construct and return an immutable ComputedValues. Store that object on elements and pseudo-elements, and share it directly with ordinary layout nodes.

Keep StyleValue for declarations, custom properties, animation interpolation, and other cases where preserving generic CSS syntax is useful. Reconstruct temporary StyleValue objects from ComputedValues when CSSOM, inheritance, or animation code specifically requires them.

This change also:

  • Moves typed-value construction from layout into CSS, including font, color, currentcolor, and calculation resolution.
  • Makes computed values available for disconnected elements, display: none, display: contents, and pseudo-elements without layout boxes.
  • Uses ComputedValues::Builder for anonymous and layout-adjusted styles while publishing only immutable results.
  • Preserves base and animation-effective typed values without duplicating styles for elements that are not animated.
  • Carries importance, inheritance, dependency, pseudo-element, and inherited recomputation metadata in the typed style.
  • Migrates layout, painting, CSSOM, invalidation, inheritance, animations, HTML, and SVG consumers to typed access.
  • Preserves incremental inherited-style recomputation and animation invalidation instead of replacing them with full recascades.
  • Leaves custom properties on their existing token/value path.

Add characterization coverage for no-box computed styles, logical and shorthand serialization, inherited values, colors, line height, images, SVG geometry, animation interpolation, and semantic distinctions that must survive typed storage.

This does not port style computation to Rust. It establishes the boundary needed for that work: a future Rust StyleComputer can produce ComputedValues directly, while the existing C++ engine consumes a compact typed result instead of depending on the transient generic computation workspace. This substantially reduces the amount of machinery that must be ported or exposed across the language boundary.

Summary by CodeRabbit

  • New Features
    • Improved computed-style handling across properties, pseudo-elements, animations, counters, generated content, colors, masks, and SVG geometry.
    • Added support for scroll-behavior: auto and smooth.
  • Bug Fixes
    • More accurate style updates and repaint scheduling, including better handling for elements without layout boxes and display:none scenarios.
    • Refined transitions/animations, inheritance, and style querying for getComputedStyle(), computedStyleMap(), and inspection tools.
  • Tests
    • Added/updated fixtures for computed styles, counters, SVG geometry, inherited values, and animation interpolation.

Cover computed style access for display: contents, display: none, and
pseudo-elements that do not generate layout boxes. Exercise logical and
shorthand properties, colors, line height, and image serialization.
Introduce a final, reference-counted ComputedValues with a builder for
derived styles. Preserve semantic line-height and color values while
separating layout resource attachment from typed value construction.
Construct typed values during style computation and retain them on
elements beside the transitional generic workspace. Carry importance,
inheritance, dependency, pseudo-element, display-none, and animation
metadata in the durable object.
@coderabbitai

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Services/WebContent/ConnectionFromClient.cpp (1)

854-861: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Refresh computed_values after updating layout.

update_layout() can publish a new immutable style snapshot, but serialization retains the pointer obtained beforehand. This can expose stale container-query or other layout-dependent styles in DevTools.

Proposed fix
-    auto computed_values = element.computed_values(pseudo_element);
-
-    if (!computed_values) {
-        async_did_inspect_dom_node(page_id, { property_type, {} });
-        return;
-    }
-
     node->document().update_layout(Web::DOM::UpdateLayoutReason::Debugging);
+
+    auto computed_values = element.computed_values(pseudo_element);
+    if (!computed_values) {
+        async_did_inspect_dom_node(page_id, { property_type, {} });
+        return;
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Services/WebContent/ConnectionFromClient.cpp` around lines 854 - 861, Refresh
the computed style snapshot in the DOM inspection flow after
node->document().update_layout(...) completes. Update the computed_values
pointer used for serialization by calling
element.computed_values(pseudo_element) again, while preserving the existing
early return when no values are available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Libraries/LibWeb/CSS/ComputedProperties.cpp`:
- Around line 1502-1525: Update the TouchAction serialization branch to append
the pinch-zoom keyword whenever action.allow_pinch_zoom is true, including mixed
values such as pan-x pinch-zoom, while preserving the existing auto,
manipulation, none, and directional pan handling.

In `@Libraries/LibWeb/CSS/ComputedValues.cpp`:
- Around line 74-78: Move calculation and application of the element’s used
color scheme in the computed-values construction flow before the color
resolution at the affected color-handling code. Ensure system colors and
subsequent currentcolor values resolve using the element-specific scheme, while
retaining the existing color-scheme property setup and output assignment.
- Around line 503-506: Update the transition-property conversion in the loop
over CSS::PropertyID::TransitionProperty so the keyword all is represented
distinctly from none; do not use an empty Optional<Utf16FlyString> for both
cases. Preserve custom identifiers and ensure explicit all transitions remain
available to computed-style consumers.
- Around line 652-659: Update the extract_side lambda in ComputedValues.cpp to
resolve calculated overflow-clip-margin offsets, not just plain lengths. Use the
existing calculated-value resolution path for overflow_clip_margin.offset() so
valid calc(...) values produce their resolved CSSPixels amount instead of
defaulting to zero, while preserving the current behavior for unsupported or
non-length values.
- Around line 827-845: Update the `aspect_ratio` two-value list branch in
`ComputedValues` so an `auto <ratio>` value with a degenerate resolved ratio is
represented as auto, matching the bare-ratio branch. Preserve the existing
preferred-ratio assignment for non-degenerate ratios and the handling of
standalone `auto`.

In `@Libraries/LibWeb/CSS/Length.cpp`:
- Around line 269-281: Update the root_font_metrics initializer in the
Length::ResolutionContext construction to use
root_computed_values->line_height() instead of computed_values->line_height(),
while leaving the target element’s font_metrics unchanged.

In `@Libraries/LibWeb/CSS/StyleComputer.cpp`:
- Around line 1604-1610: Update the currentcolor handling in the style
comparison logic around originates_from_current_color so it suppresses the
difference only when the underlying non-animated color value is unchanged. Do
not mark before_change_style_is_different false solely because both declarations
use currentcolor; preserve transitions when the resolved color changes, such as
when color changes with border-color: currentcolor.

In `@Services/WebContent/ConnectionFromClient.cpp`:
- Around line 571-573: Change the property iteration loop in the computed-style
dump to use an inclusive upper bound so it also processes
Web::CSS::last_longhand_property_id, matching the inclusive iteration behavior
elsewhere in the inspection code.

---

Outside diff comments:
In `@Services/WebContent/ConnectionFromClient.cpp`:
- Around line 854-861: Refresh the computed style snapshot in the DOM inspection
flow after node->document().update_layout(...) completes. Update the
computed_values pointer used for serialization by calling
element.computed_values(pseudo_element) again, while preserving the existing
early return when no values are available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 111f42ad-3ed4-42eb-bdb3-397d59faca2b

📥 Commits

Reviewing files that changed from the base of the PR and between 483865b and f02a0ae.

📒 Files selected for processing (204)
  • Libraries/LibWeb/Animations/AnimationEffect.cpp
  • Libraries/LibWeb/Animations/KeyframeEffect.cpp
  • Libraries/LibWeb/Animations/KeyframeEffect.h
  • Libraries/LibWeb/CMakeLists.txt
  • Libraries/LibWeb/CSS/CSSStyleProperties.cpp
  • Libraries/LibWeb/CSS/ComputedProperties.cpp
  • Libraries/LibWeb/CSS/ComputedProperties.h
  • Libraries/LibWeb/CSS/ComputedValues.cpp
  • Libraries/LibWeb/CSS/ComputedValues.h
  • Libraries/LibWeb/CSS/ContainerQuery.cpp
  • Libraries/LibWeb/CSS/CountersSet.cpp
  • Libraries/LibWeb/CSS/EasingFunction.cpp
  • Libraries/LibWeb/CSS/EasingFunction.h
  • Libraries/LibWeb/CSS/Enums.json
  • Libraries/LibWeb/CSS/FontComputer.cpp
  • Libraries/LibWeb/CSS/Length.cpp
  • Libraries/LibWeb/CSS/StyleComputer.cpp
  • Libraries/LibWeb/CSS/StyleComputer.h
  • Libraries/LibWeb/CSS/StyleInvalidation.cpp
  • Libraries/LibWeb/CSS/StyleInvalidation.h
  • Libraries/LibWeb/CSS/StylePropertyMapReadOnly.cpp
  • Libraries/LibWeb/CSS/StyleSheetInvalidation.cpp
  • Libraries/LibWeb/CSS/StyleValues/ColorStyleValue.cpp
  • Libraries/LibWeb/CSS/StyleValues/CounterStyleStyleValue.h
  • Libraries/LibWeb/CSS/StyleValues/ShorthandStyleValue.cpp
  • Libraries/LibWeb/CSS/StyleValues/StyleValue.cpp
  • Libraries/LibWeb/CSS/StyleValues/StyleValue.h
  • Libraries/LibWeb/CSS/UpdateStyle.cpp
  • Libraries/LibWeb/CSS/UpdateStyle.h
  • Libraries/LibWeb/DOM/AbstractElement.cpp
  • Libraries/LibWeb/DOM/AbstractElement.h
  • Libraries/LibWeb/DOM/Document.cpp
  • Libraries/LibWeb/DOM/Document.h
  • Libraries/LibWeb/DOM/Element.cpp
  • Libraries/LibWeb/DOM/Element.h
  • Libraries/LibWeb/DOM/Node.cpp
  • Libraries/LibWeb/DOM/PseudoElement.cpp
  • Libraries/LibWeb/DOM/PseudoElement.h
  • Libraries/LibWeb/Dump.cpp
  • Libraries/LibWeb/Forward.h
  • Libraries/LibWeb/HTML/Canvas/AbstractCanvasMixin.cpp
  • Libraries/LibWeb/HTML/Canvas/CanvasTextDrawingStyles.cpp
  • Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp
  • Libraries/LibWeb/HTML/HTMLAudioElement.cpp
  • Libraries/LibWeb/HTML/HTMLAudioElement.h
  • Libraries/LibWeb/HTML/HTMLBRElement.cpp
  • Libraries/LibWeb/HTML/HTMLBRElement.h
  • Libraries/LibWeb/HTML/HTMLCanvasElement.cpp
  • Libraries/LibWeb/HTML/HTMLCanvasElement.h
  • Libraries/LibWeb/HTML/HTMLElement.cpp
  • Libraries/LibWeb/HTML/HTMLFieldSetElement.cpp
  • Libraries/LibWeb/HTML/HTMLFieldSetElement.h
  • Libraries/LibWeb/HTML/HTMLHtmlElement.cpp
  • Libraries/LibWeb/HTML/HTMLIFrameElement.cpp
  • Libraries/LibWeb/HTML/HTMLIFrameElement.h
  • Libraries/LibWeb/HTML/HTMLImageElement.cpp
  • Libraries/LibWeb/HTML/HTMLImageElement.h
  • Libraries/LibWeb/HTML/HTMLInputElement.cpp
  • Libraries/LibWeb/HTML/HTMLInputElement.h
  • Libraries/LibWeb/HTML/HTMLLegendElement.cpp
  • Libraries/LibWeb/HTML/HTMLLegendElement.h
  • Libraries/LibWeb/HTML/HTMLObjectElement.cpp
  • Libraries/LibWeb/HTML/HTMLObjectElement.h
  • Libraries/LibWeb/HTML/HTMLSelectElement.cpp
  • Libraries/LibWeb/HTML/HTMLTableCellElement.cpp
  • Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
  • Libraries/LibWeb/HTML/HTMLTextAreaElement.h
  • Libraries/LibWeb/HTML/HTMLVideoElement.cpp
  • Libraries/LibWeb/HTML/HTMLVideoElement.h
  • Libraries/LibWeb/HTML/LocalNavigable.cpp
  • Libraries/LibWeb/Layout/AudioBox.cpp
  • Libraries/LibWeb/Layout/AudioBox.h
  • Libraries/LibWeb/Layout/BlockContainer.cpp
  • Libraries/LibWeb/Layout/BlockContainer.h
  • Libraries/LibWeb/Layout/BlockFormattingContext.cpp
  • Libraries/LibWeb/Layout/Box.cpp
  • Libraries/LibWeb/Layout/Box.h
  • Libraries/LibWeb/Layout/BreakNode.cpp
  • Libraries/LibWeb/Layout/BreakNode.h
  • Libraries/LibWeb/Layout/CanvasBox.cpp
  • Libraries/LibWeb/Layout/CanvasBox.h
  • Libraries/LibWeb/Layout/CheckBox.cpp
  • Libraries/LibWeb/Layout/CheckBox.h
  • Libraries/LibWeb/Layout/FieldSetBox.cpp
  • Libraries/LibWeb/Layout/FieldSetBox.h
  • Libraries/LibWeb/Layout/FormattingContext.cpp
  • Libraries/LibWeb/Layout/ImageBox.cpp
  • Libraries/LibWeb/Layout/ImageBox.h
  • Libraries/LibWeb/Layout/InlineNode.cpp
  • Libraries/LibWeb/Layout/InlineNode.h
  • Libraries/LibWeb/Layout/LegendBox.cpp
  • Libraries/LibWeb/Layout/LegendBox.h
  • Libraries/LibWeb/Layout/ListItemBox.cpp
  • Libraries/LibWeb/Layout/ListItemBox.h
  • Libraries/LibWeb/Layout/ListItemMarkerBox.cpp
  • Libraries/LibWeb/Layout/ListItemMarkerBox.h
  • Libraries/LibWeb/Layout/NavigableContainerViewport.cpp
  • Libraries/LibWeb/Layout/NavigableContainerViewport.h
  • Libraries/LibWeb/Layout/Node.cpp
  • Libraries/LibWeb/Layout/Node.h
  • Libraries/LibWeb/Layout/RadioButton.cpp
  • Libraries/LibWeb/Layout/RadioButton.h
  • Libraries/LibWeb/Layout/RangeInputBox.cpp
  • Libraries/LibWeb/Layout/RangeInputBox.h
  • Libraries/LibWeb/Layout/ReplacedBox.cpp
  • Libraries/LibWeb/Layout/ReplacedBox.h
  • Libraries/LibWeb/Layout/SVGBox.cpp
  • Libraries/LibWeb/Layout/SVGBox.h
  • Libraries/LibWeb/Layout/SVGClipBox.cpp
  • Libraries/LibWeb/Layout/SVGClipBox.h
  • Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp
  • Libraries/LibWeb/Layout/SVGForeignObjectBox.h
  • Libraries/LibWeb/Layout/SVGGeometryBox.cpp
  • Libraries/LibWeb/Layout/SVGGeometryBox.h
  • Libraries/LibWeb/Layout/SVGGraphicsBox.cpp
  • Libraries/LibWeb/Layout/SVGGraphicsBox.h
  • Libraries/LibWeb/Layout/SVGImageBox.cpp
  • Libraries/LibWeb/Layout/SVGImageBox.h
  • Libraries/LibWeb/Layout/SVGMaskBox.cpp
  • Libraries/LibWeb/Layout/SVGMaskBox.h
  • Libraries/LibWeb/Layout/SVGPatternBox.cpp
  • Libraries/LibWeb/Layout/SVGPatternBox.h
  • Libraries/LibWeb/Layout/SVGSVGBox.cpp
  • Libraries/LibWeb/Layout/SVGSVGBox.h
  • Libraries/LibWeb/Layout/SVGTextBox.cpp
  • Libraries/LibWeb/Layout/SVGTextBox.h
  • Libraries/LibWeb/Layout/SVGTextPathBox.cpp
  • Libraries/LibWeb/Layout/SVGTextPathBox.h
  • Libraries/LibWeb/Layout/TableWrapper.cpp
  • Libraries/LibWeb/Layout/TableWrapper.h
  • Libraries/LibWeb/Layout/TextAreaBox.cpp
  • Libraries/LibWeb/Layout/TextAreaBox.h
  • Libraries/LibWeb/Layout/TextInputBox.cpp
  • Libraries/LibWeb/Layout/TextInputBox.h
  • Libraries/LibWeb/Layout/TreeBuilder.cpp
  • Libraries/LibWeb/Layout/TreeBuilder.h
  • Libraries/LibWeb/Layout/VideoBox.cpp
  • Libraries/LibWeb/Layout/VideoBox.h
  • Libraries/LibWeb/Layout/Viewport.cpp
  • Libraries/LibWeb/Layout/Viewport.h
  • Libraries/LibWeb/Painting/AccumulatedVisualContext.cpp
  • Libraries/LibWeb/Painting/BackgroundPainting.cpp
  • Libraries/LibWeb/Painting/Paintable.cpp
  • Libraries/LibWeb/Painting/Paintable.h
  • Libraries/LibWeb/Painting/StackingContext.cpp
  • Libraries/LibWeb/SVG/SVGAElement.cpp
  • Libraries/LibWeb/SVG/SVGAElement.h
  • Libraries/LibWeb/SVG/SVGClipPathElement.cpp
  • Libraries/LibWeb/SVG/SVGClipPathElement.h
  • Libraries/LibWeb/SVG/SVGDecodedImageData.cpp
  • Libraries/LibWeb/SVG/SVGDefsElement.h
  • Libraries/LibWeb/SVG/SVGDescElement.cpp
  • Libraries/LibWeb/SVG/SVGDescElement.h
  • Libraries/LibWeb/SVG/SVGElement.cpp
  • Libraries/LibWeb/SVG/SVGFEDropShadowElement.cpp
  • Libraries/LibWeb/SVG/SVGFEFloodElement.cpp
  • Libraries/LibWeb/SVG/SVGFEFloodElement.h
  • Libraries/LibWeb/SVG/SVGFilterElement.cpp
  • Libraries/LibWeb/SVG/SVGForeignObjectElement.cpp
  • Libraries/LibWeb/SVG/SVGForeignObjectElement.h
  • Libraries/LibWeb/SVG/SVGGElement.cpp
  • Libraries/LibWeb/SVG/SVGGElement.h
  • Libraries/LibWeb/SVG/SVGGeometryElement.cpp
  • Libraries/LibWeb/SVG/SVGGeometryElement.h
  • Libraries/LibWeb/SVG/SVGGradientElement.cpp
  • Libraries/LibWeb/SVG/SVGImageElement.cpp
  • Libraries/LibWeb/SVG/SVGImageElement.h
  • Libraries/LibWeb/SVG/SVGMaskElement.cpp
  • Libraries/LibWeb/SVG/SVGMaskElement.h
  • Libraries/LibWeb/SVG/SVGMetadataElement.cpp
  • Libraries/LibWeb/SVG/SVGMetadataElement.h
  • Libraries/LibWeb/SVG/SVGPatternElement.cpp
  • Libraries/LibWeb/SVG/SVGPatternElement.h
  • Libraries/LibWeb/SVG/SVGSVGElement.cpp
  • Libraries/LibWeb/SVG/SVGSVGElement.h
  • Libraries/LibWeb/SVG/SVGStopElement.cpp
  • Libraries/LibWeb/SVG/SVGSwitchElement.cpp
  • Libraries/LibWeb/SVG/SVGSwitchElement.h
  • Libraries/LibWeb/SVG/SVGSymbolElement.cpp
  • Libraries/LibWeb/SVG/SVGSymbolElement.h
  • Libraries/LibWeb/SVG/SVGTSpanElement.cpp
  • Libraries/LibWeb/SVG/SVGTSpanElement.h
  • Libraries/LibWeb/SVG/SVGTextElement.cpp
  • Libraries/LibWeb/SVG/SVGTextElement.h
  • Libraries/LibWeb/SVG/SVGTextPathElement.cpp
  • Libraries/LibWeb/SVG/SVGTextPathElement.h
  • Libraries/LibWeb/SVG/SVGTitleElement.cpp
  • Libraries/LibWeb/SVG/SVGTitleElement.h
  • Libraries/LibWeb/SVG/SVGUseElement.cpp
  • Libraries/LibWeb/SVG/SVGUseElement.h
  • Services/WebContent/ConnectionFromClient.cpp
  • Services/WebContent/WebDriverConnection.cpp
  • Tests/LibWeb/Text/expected/css/computed-style-map-counters.txt
  • Tests/LibWeb/Text/expected/css/computed-style-without-layout-box.txt
  • Tests/LibWeb/Text/expected/css/computed-values-svg-geometry.txt
  • Tests/LibWeb/Text/expected/css/list-style-symbols-inherit.txt
  • Tests/LibWeb/Text/expected/css/shape-image-threshold-inherit.txt
  • Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/animations/background-color-interpolation.txt
  • Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/animations/border-color-interpolation.txt
  • Tests/LibWeb/Text/input/css/computed-style-map-counters.html
  • Tests/LibWeb/Text/input/css/computed-style-without-layout-box.html
  • Tests/LibWeb/Text/input/css/computed-values-svg-geometry.html
  • Tests/LibWeb/Text/input/css/list-style-symbols-inherit.html
  • Tests/LibWeb/Text/input/css/shape-image-threshold-inherit.html

Comment thread Libraries/LibWeb/CSS/ComputedProperties.cpp
Comment thread Libraries/LibWeb/CSS/ComputedValues.cpp
Comment thread Libraries/LibWeb/CSS/ComputedValues.cpp
Comment thread Libraries/LibWeb/CSS/ComputedValues.cpp
Comment thread Libraries/LibWeb/CSS/ComputedValues.cpp
Comment thread Libraries/LibWeb/CSS/Length.cpp
Comment thread Libraries/LibWeb/CSS/StyleComputer.cpp
Comment thread Services/WebContent/ConnectionFromClient.cpp Outdated
Reconstruct core property families from ComputedValues and redirect
CSSOM, DOM, HTML, SVG, painting, container queries, and traversal state
to typed access. Preserve currentcolor-sensitive data, font details, and
remaining inherited state needed by the transitional algorithm.
Complete typed storage and reconstruction for layout, CSSOM, animation,
invalidation, generated content, and remaining engine clients. Preserve
exact syntax and computed semantics for inherited, color, shape, border,
list, image, anchor, timeline, and SVG values.
Reconstruct transient generic workspaces for animation and inherited
style updates, then remove durable ComputedProperties storage from
elements and pseudo-elements. Return immutable ComputedValues directly
from style computation and keep mutable access confined to consuming
builders. Handle CSS animations whose effects are temporarily detached
by script.
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
putComment timed out

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