Skip to content

Conversation

@asamuzaK
Copy link
Contributor

@asamuzaK asamuzaK commented Dec 13, 2025

Summary

This PR serves as a preparation step to resolve long-standing issues with shorthand properties.
It introduces a mechanism to auto-generate CSS property definitions and refactors the codebase to utilize them.

Key Changes and Reasons

1. Introducing propertyDefinitions.js

  • Change: Added a script to generate lib/generated/propertyDefinitions.js based on property metadata.
  • Reason: To implement shorthand properties correctly, we need a reliable source of truth for every longhand property (initial values, syntax, inheritance, etc.). Hardcoding these manually is error-prone.
  • Future Integration with jsdom: The newly introduced lib/generated/propertyDefinitions.js is designed to be the single source of truth for CSS properties. In the future, this is intended to replace propertiesWithResolvedValueImplemented in jsdom's lib/jsdom/living/helpers/style-rules.js, allowing jsdom to delegate property metadata management entirely to cssstyle.

2. Splitting Functions and Clarifying Roles

  • Change: Decomposed the monolithic normalization logic into smaller, discrete functions.
  • Reason: To explicitly define the role of each function (separation of concerns). By isolating the logic for different value types and validation steps, the code becomes more readable and easier to maintain. This modularity is essential for handling the complexity of shorthand property expansion in the next steps.

3. Refactoring with Constants

  • Change: Replaced string literals (e.g., property names, values like 'initial', 'inherit') with constants.
  • Reason: To prevent bugs caused by typos and to improve code maintainability across the parser and normalizer.

Effect

While the direct effects of this PR are limited regarding the overall shorthand behavior, it explicitly resolves the following test case:

  • web-platform-tests/to-upstream/css/cssom/style-border-shorthand-var.html

Once merged, this PR establishes the necessary data structures and infrastructure, allowing us to implement the complex logic for expanding shorthands into longhands in a follow-up PR with high reliability and low maintenance cost.

@asamuzaK asamuzaK marked this pull request as draft December 13, 2025 14:37
@asamuzaK asamuzaK force-pushed the defs branch 2 times, most recently from 05d1ddb to 38299f6 Compare December 14, 2025 06:26
@asamuzaK asamuzaK changed the title Address shorthand property issues Preparation for resolving shortcut property issues Dec 14, 2025
@asamuzaK asamuzaK marked this pull request as ready for review December 14, 2025 12:20
@domenic
Copy link
Member

domenic commented Dec 15, 2025

Can you add a more detailed description of this PR? What changes, why are those changes good, does this fix any bugs currently or is it only for use in a follow-up, etc.? Why do we need a new generated properties list and how does it differ from the other generated lists? What specs does this implement? That sort of thing.

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

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

My biggest worry here is the module-level mutable state.

Otherwise, there are likely improvements that could be made to reduce complexity and code duplication, etc., but they are not blockers, and I am happy to continue with you being the expert on these parts of the code.

lib/normalize.js Outdated
for (const position of borderPositions) {
const longhandProperty = `${namePart}-${position}-${linePart}`;
const longhandItem = createPropertyItem(longhandProperty, lineValue, priority);
if (longhandProperties.has(longhandProperty)) {
Copy link
Member

Choose a reason for hiding this comment

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

This pattern (lines 1346-1354) appears multiple times. Can we extract it into a helper?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

6507ee3

Please take a look.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

a35b915

Please take a look.

Copy link
Member

Choose a reason for hiding this comment

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

Now we have these three duplicated:

  • cssstyle/lib/normalize.js

    Lines 1306 to 1314 in a35b915

    if (properties.has(longhandProperty)) {
    const { priority: existingPriority } = properties.get(longhandProperty);
    if (!existingPriority) {
    properties.delete(longhandProperty);
    properties.set(longhandProperty, longhandItem);
    }
    } else {
    properties.set(longhandProperty, longhandItem);
    }
  • cssstyle/lib/normalize.js

    Lines 1330 to 1338 in a35b915

    if (safe && properties.has(property)) {
    const { priority: existingPriority } = properties.get(property);
    if (!existingPriority) {
    properties.delete(property);
    properties.set(property, item);
    }
    } else {
    properties.set(property, item);
    }
  • cssstyle/lib/normalize.js

    Lines 1401 to 1409 in a35b915

    } else if (longhandProperties.has(property)) {
    const { priority } = longhandProperties.get(property);
    if (!priority) {
    longhandProperties.delete(property);
    longhandProperties.set(property, item);
    }
    } else {
    longhandProperties.set(property, item);
    }

I think maybe you missed what I was referring to in the original comment, which was specifically the block from 1346-1354? Both of your attempted refactorings so far do not focus on that specific code pattern, but instead pull out larger chunks of code. And because they pull out larger chunks of code, they miss and duplicate the smaller pattern I am pointing to.

Updated generateBorderLineShorthand, generateBorderPositionShorthand, and generateBorderNameShorthand to use a default parameter for priority instead of reassigning within the function. This simplifies the function signatures and improves code clarity.
Replaces direct calls to createPropertyItem with getPropertyItem for border-related properties in prepareBorderProperties, streamlining property item retrieval and improving code consistency.
Replaces the borderCollections object with borderCollectionConfig and dynamically constructs borderCollections with items and priorityItems maps. Renames priorItems to priorityItems throughout for clarity and consistency, and updates related logic in prepareBorderShorthands.
Renamed 'namePriorItems' to 'namePriorityItems' in prepareBorderShorthands for consistency and clarity.
Extracted repeated logic for updating border longhand properties into a new helper function, updatePositionLonghands. This improves code readability and maintainability in the border property normalization process.
@asamuzaK asamuzaK requested a review from domenic December 18, 2025 00:04
Introduces the updateLonghandProperties helper to consolidate logic for updating longhand properties in multiple places. This reduces code duplication and improves maintainability in normalize.js.
Replaces all instances of the variable 'nameItem' with 'shorthandItem'. No functional changes were made; this is a variable renaming for better meaning and code readability.
Renamed generateBorderNameShorthand to generateBorderShorthand and updated related variable names for clarity. This improves code readability and better reflects the function's purpose.
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