Bug 247810 - border shorthand serialization doesn't round-trip
Summary: border shorthand serialization doesn't round-trip
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: Other
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2022-11-11 08:50 PST by Emilio Cobos Álvarez (:emilio)
Modified: 2022-11-18 08:51 PST (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Emilio Cobos Álvarez (:emilio) 2022-11-11 08:50:47 PST
document.body.style.border = "1px solid";
document.body.style.borderImageSlice = "99%"; // Something non-initial
document.body.style.border // Should be "", on WebKit is "1px solid"

Per spec it should be the empty string.

https://drafts.csswg.org/cssom/#serialize-a-css-value:

> If there is no such shorthand or shorthand cannot exactly represent the values of all the properties in list, return the empty string.

The list comes from https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-getpropertyvalue which has:

> For each longhand property longhand that property maps to, in canonical order [...]

And border maps to the border-image properties.
Comment 1 Oriol Brufau 2022-11-11 11:35:04 PST
This also affects other properties, as can be easily shown by the fact that WebKit doesn't even ensure that all longhands are present.

var allCSSProps = new Set();
for (let obj = document.createElement("div").style; obj; obj = Reflect.getPrototypeOf(obj)) {
  for (let name of Object.getOwnPropertyNames(obj)) {
    let prop = name.replace(/[A-Z]/g, c => "-" + c.toLowerCase());
    if (CSS.supports(prop, "initial")) {
      allCSSProps.add(prop);
    }
  }
}
var style = document.createElement("div").style;
document.documentElement.style.cssText = "all: initial; direction: initial; unicode-bidi: initial";
var cs = getComputedStyle(document.documentElement);
var bad = {};
for (let prop of allCSSProps) {
  const value = cs.getPropertyValue(prop);
  style.cssText = "";
  style.setProperty(prop, value);
  if (style.length > 1) {
    let longhands = [...style];
    for (let longhand of longhands) {
      style.cssText = "";
      style.setProperty(prop, value);
      style.removeProperty(longhand);
      if (style.getPropertyValue(prop) !== "") {
        bad[prop] ||= [];
        bad[prop].push(longhand);
      }
    }
  }
}
bad;


{
  border: ["border-image-source", "border-image-slice", "border-image-width", "border-image-outset", "border-image-repeat"],
  font: ["font-style", "font-variant-caps", "font-weight", "font-stretch", "line-height", "font-size-adjust", "font-kerning", "font-variant-alternates", "font-variant-ligatures", "font-variant-numeric", "font-variant-east-asian", "font-variant-position", "font-feature-settings", "font-optical-sizing", "font-variation-settings", "font-palette"],
  font-synthesis: ["font-synthesis-weight", "font-synthesis-style", "font-synthesis-small-caps"],
  font-variant: ["font-variant-numeric", "font-variant-caps", "font-variant-alternates", "font-variant-east-asian", "font-variant-position"],
  offset: ["offset-path", "offset-distance", "offset-position", "offset-anchor", "offset-rotate"],
}
Comment 2 Tim Nguyen (:ntim) 2022-11-12 10:18:05 PST
Are there any WPT for this? It would be nice to add some if not.
Comment 3 Darin Adler 2022-11-12 10:50:03 PST
Tests should cover both specified properties and computed properties. For specified values of shorthands it’s important to cover cases when the longhands are set to CSS-wide keywords like "inherit" and "initial".

Aside from this, I think we also might want tests for what longhands get set to when the specification says "reset to the initial value" because you could imagine that could serialize as "initial" or as "normal", for example.
Comment 4 Oriol Brufau 2022-11-12 12:58:56 PST
It should not be literally "initial", see e.g. bug 82078 and bug 244657
Using "initial" causes bugs like bug 242775.
Comment 5 Darin Adler 2022-11-13 20:35:56 PST
I don’t mean how it will serialize in the shorthand. I meant how it should serialize in the longhand.
Comment 6 Darin Adler 2022-11-13 20:36:49 PST
But I assume that most shorthands never say "reset to the initial value".
Comment 7 Darin Adler 2022-11-13 20:37:00 PST
The font shorthand does, but maybe that’s the only one.
Comment 8 Darin Adler 2022-11-13 20:37:53 PST
Without existing WPT, the main task here is writing the tests. It will be very quick to fix the code once we have the tests.
Comment 9 Tim Nguyen (:ntim) 2022-11-14 01:14:15 PST
The border/border-image case is tested by LayoutTests/imported/w3c/web-platform-tests/css/cssom/border-shorthand-serialization.html
Comment 10 Oriol Brufau 2022-11-14 08:06:33 PST
(In reply to Darin Adler from comment #6)
> But I assume that most shorthands never say "reset to the initial value".

I think it's quite common.

https://drafts.csswg.org/css-backgrounds/#border-shorthands
> Omitted values are set to their initial values. 
> The border shorthand also resets border-image to its initial value.

https://drafts.csswg.org/css-backgrounds/#background
> 'background-color' is set to the specified color, if any, else set to its initial value. 

https://drafts.fxtf.org/motion/#offset-shorthand
> Omitted values are set to their initial values.

https://drafts.csswg.org/css-grid/#valdef-grid-template-none
> Sets all three properties to their initial values ('none'). 

https://drafts.csswg.org/css-grid/#grid-shorthand
> the 'grid-auto-*' longhands to their initial values.
> All other grid sub-properties are reset to their initial values.
Comment 11 Radar WebKit Bug Importer 2022-11-18 08:51:15 PST
<rdar://problem/102516427>