Visitar URL original
[cssom] Serialization of large numbers should use scientific notation · Issue #6471 · w3c/csswg-drafts · GitHub
Skip to content

[cssom] Serialization of large numbers should use scientific notation #6471

Open

Description

@achristensen07

https://drafts.csswg.org/cssom/#serialize-a-css-component-value in the section has a note that says "scientific notation is not used." While this makes sense for small values so we serialize "0" instead of "6.123233995736766e-17" and this matches the behavior of Chrome and Firefox and I'm looking into implementing this in WebKit, for large numbers all browsers do use scientific notation, as illustrated by this simple example:

<body onload='checkLargeValues()'>
<script>
function checkLargeValues() {
    let target = document.getElementById('p');
    target.style['line-height'] = 1e+26;
    alert(window.getComputedStyle(target)['line-height'])
}
</script>
<p id="p"></p>
</body>

The phrase "in the shortest form possible" is already in the text, which suggests to me that multiple forms are possible. I suggest the note be clarified to say something like "scientific notation is not used with negative exponents."

Activity

  1. achristensen07 commented on Jul 23, 2021

    @achristensen07
    Author

    BTW I found this while trying to implement it at https://bugs.webkit.org/show_bug.cgi?id=228190 based on some earlier work by Tyler Wilcock.

  2. tabatkins commented on Jul 23, 2021

    @tabatkins
    Member

    Agreed, the spec should reflect reality there.

    A small wrinkle is that, per the current Syntax spec, using scinot automatically makes it a <number>, not an <integer>. I did this for simplicity, but if we're serializing large numbers, either properties like z-index need to not use scinot even for large numbers, or I need to amend Syntax to allow scinot to produce integers at least some of time.

    (Happy to go with either "only when there's no decimal point", so 23e8 is an integer but 23.4e8 isn't, or the more forgiving "as long as the exponent exceeds the number of digits after the decimal point", so 23.4e8 would be an integer but 2.34e1 isn't.)

  3. dlibby- commented on Sep 20, 2021

    @dlibby-
    Contributor

    In terms of expected behaviors for developers, I think the current behavior for large numbers is somewhat unintuitive, as values don't roundtrip and script cannot disambiguate between two large numbers that are close to each other.

    let value = 1000000;
    document.body.style.lineHeight = value + "px";
    document.documentElement.style.lineHeight = (++value) + "px";
    
    // both '1e+06px', evals to true
    document.documentElement.style.lineHeight === document.body.style.lineHeight 
    

    Maybe we should specify that for numbers < X, use a set number of precision digits (in Blink I believe this is 6 currently), but numbers larger should use N precision digits where N is the number of digits (maybe +2?). Or perhaps inertia is enough that specifying the current behavior is the right call for web compat.

  4. css-meeting-bot commented on Oct 6, 2021

    @css-meeting-bot
    Member

    The CSS Working Group just discussed [cssom] Serialization of large numbers should use scientific notation, and agreed to the following:

    • RESOLVED: Take scientific notation and match serialization of JS
    The full IRC log of that discussion <dael> Topic: [cssom] Serialization of large numbers should use scientific notation
    <dael> github: https://github.com//issues/6471
    <dael> Rossen_: Added to TPAC agenda but we didn't get to it
    <dael> smfr: The issue is how large numbeer serialize.
    <dael> smfr: Agreed in past to allow scientific notation when we pass. Difference in serialization. FF and Blink use scientific notation. Webkit writes them out
    <dael> smfr: One question is if should be different for numbeer vs int. z-index how much precision do we maintain so they round trip, for example
    <dael> smfr: And then there are differences like blink adds leading 0s.
    <TabAtkins> q+
    <dael> smfr: This impacts wpt so would be good to resolve
    <florian> q-
    <Rossen_> ack florian
    <Rossen_> ack TabAtkins
    <TabAtkins> https://drafts.csswg.org/cssom/#serializing-css-values
    <dael> TabAtkins: Well defined in CSSOM. Will grab a link
    <dael> TabAtkins: Per this int serialize fully and floats with no more than 6 digits. If needed scientific with 6 digits.
    <dael> TabAtkins: it is defined. If question is should define something else we can talk about it
    <dael> smfr: Fine with as spec. Q is if impl will impl as spec
    <dael> florian: Does this no more than 6 cover the leading 0s?
    <dael> TabAtkins: 6 significant digits. And need to use shortest form. Leading 0s are dropped
    <TabAtkins> "A base-ten number using digits 0-9 (U+0030 to U+0039) in the shortest form possible, using "." to separate decimals (if any), rounding the value if necessary to not produce more than 6 decimals, preceded by "-" (U+002D) if it is negative."
    <Rossen_> q?
    <dael> Rossen_: Sounds like we don't need to change a definition. Back to smfr question about are impl willing to use this definition?
    <dael> Rossen_: Survey question to implementors
    <dael> iank_: All of our folks are in EU so I'm not sure
    <dael> Rossen_: Perhaps we don't have right folks.
    <dael> Rossen_: We can resolve on the issue as no change to spec and encourage implementors to engage
    <dael> Rossen_: Reasonable?
    <dael> smfr: I'm reading the link from TabAtkins it says scientific notation is not used. Is it out of date?
    <dael> TabAtkins: Yes, must be. Thought it was required. Integer question is answered. Hmm.
    <dael> TabAtkins: No way to satisfy this without scientific notation. If you do a large number you need more than 6
    <dael> Rossen_: And why is it a note?
    <dael> TabAtkins: It's a clarification. It should fall out from definition.
    <dael> Rossen_: Perhaps we can try and ammend the spec to require scientific notation?
    <dael> TabAtkins: Yes
    <dael> smfr: Serialization we can reference? Perhaps from JS?
    <dael> TabAtkins: JS does have well spec one
    <dael> smfr: Chrome JS doesn't match number serialization which is a bit surprising
    <dael> Rossen_: We can call for resolution here to add scientific notation to be used for number
    <dael> Rossen_: Then wait for TabAtkins or someone to define the serialization. Unles syou have one right now
    <dael> TabAtkins: Happy to take that
    <dael> Rossen_: Prop: Take scientific notation and match serialization of JS
    <dael> Rossen_: Obj?
    <dael> RESOLVED: Take scientific notation and match serialization of JS
    <dael> Rossen_: Call to impl and getting feedback still stays
  5. cdoublev commented on May 24, 2022

    @cdoublev
    Collaborator

    I need to amend Syntax to allow scinot to produce integers at least some of time.

    Copy-paste of what I was suggesting in #7289 :

    Otherwise, step 5.3 of consume a number could be replaced after step 6 by evaluating if repr is an integer. I do not know how this evaluation can be translated into spec/WebIDL terms.

    Perhaps it can not be fixed because it would break parsing eg. <signless-integer> and <signed-integer>.

  6. cdoublev commented on Jun 3, 2022

    @cdoublev
    Collaborator

    I'm not sure I totally understand the intent of the resolution for the new definition. The current definition to serialize <number> is:

    A base-ten number using digits 0-9 (U+0030 to U+0039) in the shortest form possible, using "." to separate decimals (if any), rounding the value if necessary to not produce more than 6 decimals, preceded by "-" (U+002D) if it is negative.

    Reading the IRC log and observing values produced in Chrome and Firefox, I think the intent is to limit to 6 significant digits, not to 6 decimals. Is it correct?

    Does it refer to Number.toPrecision() as the serialization of JS to match? Number.toPrecision() does not always produce the shortest form possible, eg. (100).toPrecision(2) is 1.0e+2 instead of 1e2, and I also read: Leading 0s are dropped. Leading 0s are not dropped by Number.toPrecision().

    What is the purpose of serialization in the shortest possible form? Is it to optimize the internal storage of values?

    Lastly, this resolution only applies to <number> and not to <integer>, isn't it? Then this issue does not justify modifying Syntax to produce a <number-token> with a type equal to integer in some cases where scientific notification is used, isn't it?

  7. tabatkins commented on Jun 5, 2022

    @tabatkins
    Member

    I think the intent is to limit to 6 significant digits, not to 6 decimals. Is it correct?

    No, it means six digits after the decimal point. An integer in the millions shouldn't start rounding off its lower integer digits.

    Does it refer to Number.toPrecision() as the serialization of JS to match?

    No, we were referring to the normal JS serialization of numbers, aka what happens when you stringify, as in num + "".

    What is the purpose of serialization in the shortest possible form? Is it to optimize the internal storage of values?

    No, serialization has nothing to do with internal storage, it's just what people expect out of serialization by default. When they write 1 they don't expect it to come back out as 1.000e0.

    Lastly, this resolution only applies to and not to , isn't it? Then this issue does not justify modifying Syntax to produce a with a type equal to integer in some cases where scientific notification is used, isn't it?

    The resolution doesn't pertain to that question at all; it's a separate topic. If the serialization I end up defining does use scinot for large integers, tho, then it still requires me to make some scinot strings parse to integers.

  8. cdoublev commented on Jun 6, 2022

    @cdoublev
    Collaborator

    I guess limiting to 6 significant digits is ok as long no more than 6 decimal places are produced.

    line-height style Chrome style Firefox +n.toFixed(6) +n.toPrecision(6)
    1.5e-6 1.5e-06 0.0000015 0.000002 0.0000015
    1e-6 1e-06 0.000001 0.000001 0.000001
    1e-7 1e-07 1e-7 0 1e-7
    0.123456 0.123456 0.123456 0.123456 0.123456
    0.1234567 0.123457 0.123457 0.123457 0.123457
    123456.7 123457 123457 123456.7 123457
    999999 999999 999999 999999 999999
    1e6 1e+06 1000000 1000000 1000000
    1234567 1.23457e+06 1234570 1234567 1234570

    First case: bug in Firefox, because more than 6 decimals are produced.

    Last case: bug in Chrome and Firefox, because an integer in the millions shouldn't start rounding off its lower integer digits.

  9. domenic commented on Oct 21, 2026

    @domenic
    Collaborator

    Cross-referencing #8538 (comment) which seems to have concluded in 6 significant digits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions