-
Notifications
You must be signed in to change notification settings - Fork 642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[cssom] Serialization of a declaration block not idempotent in presence of logical properties. #3244
Comments
cc @Loirooriol too :) |
I think this is easy to fix, and we may want to just not compress shorthands if we'd need to jump over a declaration with the same logical group in order to do that. |
To avoid overlap with #1282 ( $0.style.cssText = "margin-block-start: 10px; margin-bottom: 20px; margin-block-end: 30px";
$0.style.cssText; It shouldn't serialize as I agree with your solution. |
I think the current use of the concept in $0.style.cssText = "border: 1px solid red; border-block-start-color: green; border-color: blue";
$0.style.cssText; should not be So either all border longhands should be in the same logical group (I would like some clarification in #3033), or instead of checking what I initially imagined, i.e.
it should be
where property and current longhands are the ones from the algorithm in https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block |
There's also the case of the property containing both the logical and the physical longhands (i.e., |
This has been fixed by dc37a3f, isn't it? |
Firefox handles Edit: the spec seems fine |
I have not implemented the step added by the commit I linked above. Could you please tell me why EDIT: hmm, I guess a round-trip would change the declaration order ( I would expect the second example to serialize to |
Don't forget
|
For the following case: style.borderTopWidth = '1px'
style.borderBlockStartWidth = '2px'
style.borderTopStyle = 'solid'
style.borderTopColor = 'green' I would expect If so, I think it could be modified with: - If there’s any declaration in `declaration block` in between the first and the last longhand in `current longhands` which belongs to the same logical property group, but has a different mapping logic as any of the longhands in `current longhands`, and is not in `current longhands`, continue with the steps labeled `shorthand loop`.
+ If there’s any declaration in `declaration block` in between some declarations in `current longhands` which belongs to the same logical property group, but has a different mapping logic as any of the longhands of these declarations, and is not in `current longhands`, continue with the steps labeled `shorthand loop`. |
I think the spec is saying the same as your wording, so it shouldn't be preventing the serialization with But I agree the spec is not particularly clear, I had to read it a few times to understand it. Your wording is not particularly clear to me either, what does "these declarations" refer to? This looks better to me:
Note that now it's clear that the "which" refers to "any declaration" and not to "first/last longhand in |
In my example, the declaration for To make it clear: style.borderTopWidth = '1px'
style.borderBlockStartWidth = '2px'
// Some border-*-width is missing here
// so that the above declaration is in between two declarations
// whose longhands are in the same logical property group
style.borderTopStyle = 'solid'
style.borderTopColor = 'green'
style.cssText; // border-top: 1px solid green; border-block-start-width: 2px; style.borderTopWidth = '1px'
style.borderBlockStartWidth = '2px'
style.borderRightWidth = '1px'
style.borderBottomWidth = '1px'
style.borderLeftWidth = '1px'
style.cssText; // border-top-width: 1px; border-block-start-width: 2px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; Note that Firefox serializes I agree with your rewording. I also considered splitting the sentence (step) by listing conditions but ended up only rewording it to make my point. I was also not comfortable with a declaration in between longhands in But I am sure someone can come up with the ideal and correct wording. |
Precisely, the spec says "belongs to the same logical property group, but has a different mapping logic as any of the longhands in |
OK, sorry, I'm contradicting myself, that's what happens when I try to post quickly. So yeah, I guess that the spec is preventing the serialization with But note that requiring it to be between 2 declaration in the same logical group would be wrong, see #3244 (comment) |
I guess it only applies to shorthands (there is only |
Exactly, we can't serialize
Not necessarily more than one logical property group. It suffices to have some longhands in one group (without covering the group completely), and some longhands not in the group (either another group or no group). But yeah I think The spec could say:
|
I wonder when a declaration that would not be in I guess it could be further improved by serializing the interleaved declaration, in order to serialize Another example for the observation I made in the previous paragraph is the output for |
I managed to implement the improvement mentioned in my previous comment. Basically it boils down to (if some condition is satisfied) resuming
Similarly as the obvervation I made in a previous comment, I think either are not in the same logical property group or have the same mapping logic is required. Test cases to recap: (Below, move declarations would be the result from a round trip) // Currently resolved: move declarations backward
style.cssText = 'border-top-width: 1px; border-block-start-width: 1px; border-top-style: solid; border-top-color: green'
expect(style.cssText).toBe('border-top: 1px solid green; border-block-start-width: 1px;') // Improvement: move declarations forward
style.cssText = 'border-top-width: 1px; border-block-start-style: none; border-top-style: solid; border-top-color: green'
expect(style.cssText).toBe('border-block-start-style: none; border-top: 1px solid green;')
// Guarded: skip shorthand when declarations cannot be moved backward/forward
let input = 'border-top-width: 1px; border-block-start-width: 1px; border-block-start-style: none; border-top-style: solid; border-top-color: green'
expect(style.cssText).toBe(input)
// More complex cases with moving declarations forward
style.cssText = 'border: 1px solid red; border-block-start-color: orange; border-color: green'
expect(style.cssText).toBe('border-block-start-color: orange; border: 1px solid green;')
style.cssText = 'border-top-width: 1px; border-block-start-width: 1px; border-block-end-width: 1px; border-top-style: solid; border-top-color: green'
expect(style.cssText).toBe('border-top: 1px solid green; border-block-width: 1px;')
style.cssText = 'border-block-width: 1px; border-top-width: 2px; border-top-style: none; border-block-style: solid; border-block-color: green;'
expect(style.cssText).toBe('border-top-style: none; border-block: 1px solid green; border-top-width: 2px;') Let me know what you think. |
Can't just jump from
Should not skip My concern with trying too hard to find the best serialization when there are logical properties is that it can make it much harder to also improve things like #2515. Optimizing for 2 different things is tricky. |
Sorry, I did not mean to copy/paste code, but I meant You also "jump" declarations when you look forward, no?
Yeah, I know about this issue but I have not given much thought to it. The problem with find the best serialization seems to draw the line where it becomes too much when crossed. |
Well then the iteration order needs to be precisely defined. Note that when handling |
Damn, you are right. It fails with the following entries (assuming the order is guaranteed). const input = {
'border-block-start-width': '1px',
'border-top-style': 'none',
'border-block-end-style': 'solid',
'border-right-style': 'none',
'border-bottom-style': 'none',
'border-left-style': 'none',
'border-block-start-style': 'solid',
'border-block-start-color': 'green',
}
const expected = {
'border-top-style': 'none',
'border-block-end-style': 'solid',
'border-right-style': 'none',
'border-bottom-style': 'none',
'border-left-style': 'none',
'border-block-start': '1px solid green',
} I revert to emilio's algorithm (which fixes this issue), ie. abort searching a shorthand when encoutering the first condition that might cause the serialization to not be idempotent, and I think this issue can be closed. Thanks for the follow up! |
Testcase is:
Which serializes to:
Which is not idempotent.
cc @FremyCompany
The text was updated successfully, but these errors were encountered: