-
Notifications
You must be signed in to change notification settings - Fork 641
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] Serialize numbers using scientific notation? #8538
Comments
I think we should just do what JS does. Edit: If I'm understanding the algo correctly, the So JS prints without scinot if the number either has 21 or less digits of integer part, or has less than 6 leading zeros in the decimal part. If it's larger or smaller than that, it uses scinot. Testing in the console confirms this. JS produces large string representations by default, while we intentionally capped the decimal precision of our string representations, but the thresholds match. So I suggest we use scinot when either:
In either of these conditions, we format the number with a single non-zero digit in the integer part and up to 6 digits in the decimal part (less than 6 if they are trailing zeros), followed by the exponent part. (Omitting the decimal part entirely if it's all zeros, obvs.) |
While at it, we should serialize Infinity and NaN: https://drafts.csswg.org/css-values/#calc-error-constants The precision loss to 6 digits helps with hiding implementation details of the precision, but OTOH it might cause roundtrip degradation for e.g. Since the keywords are only allowed in |
|
The |
For the Agenda+, here's a first draft of the text to replace the
|
I am not sure that the plan is to check later if this change can be applied to |
For what it's worth, one principle of serialization that I think we documented somewhere (but I can't find it anywhere that's general, although it's documented in a more specific case for serializing CSS values) is that serializing should generally prefer serializing to the more backwards-compatible / older form when there are different serialization possibilities that have been part of CSS for different amounts of time. This preference is both (a) because older web content might expect that and (b) because serialized content might be sent to a different user agent with different capabilities. (Though (b) is probably less of an issue these days because of faster browser release cycles and faster uptake of those releases.) Following this principle here would mean not using scientific notation, or at least mean limiting its use to cases where non-use is problematic (for example, because it breaks other serialization principles such as lack of dataloss during a round-trip through parsing and serialization... though I'm not sure that's the case here). That said, if we agree that (b) is less important these days, then I think this principle just degrades to the caution that we have whenever making non-backwards-compatible changes. |
The CSS Working Group just discussed
The full IRC log of that discussion<fantasai> TabAtkins: our rules for serializing numbers are reasonably well-defined<fantasai> TabAtkins: But we have scientific notation now, which is widely implemented <fantasai> TabAtkins: Browsers use it for serialization *sometimes*, inconsistent, depends on the property... <fantasai> TabAtkins: So the proposal here is to formalize when we serialize as scinot <fantasai> TabAtkins: My proposal is to match JS exactly, which means that you use scinot whenever either the number has 22 or more digits of integer value, or has 6 or more leading zeroes in its decimal portion and is zero integer <fantasai> TabAtkins: only change from JS is that we continue to truncate to only 6 digits after decimal point, maximum <fantasai> TabAtkins: this is required for compat <fantasai> TabAtkins: and also it hides some differences between browsers/properties <fantasai> TabAtkins: and it also hides some floating-point variances <fantasai> TabAtkins: so there's spec text in the issue <fantasai> TabAtkins: and that's it <bkardell_> do we have numbers that big? <fantasai> TabAtkins: Wrt interop, we're all over the place <fantasai> TabAtkins: every property and every browser does an effectively random thing <fantasai> TabAtkins: partially due to different levels of precision, e.g. width supports subpixel, but scale property supports ... <fantasai> TabAtkins: e.g. Chrome start scinot at 0.0001 <fantasai> TabAtkins: So no interop, so match JS with wrinkle about 6 digits seems reasonable to do with minimal impact on authors <fantasai> Rossen_: Any additional comments? <fantasai> TabAtkins: dbaron's point was to bias towards older formats during serialization <fantasai> ... that's part of why the bounds are so wide <fantasai> ... Most numbers you will ever encounter in a stylesheet do not trigger scinot <fantasai> TabAtkins: but outside those bounds, e.g. when serializing a transform matrix, need to serialize somehow <fantasai> Rossen_: Pretty clear proposal, not seeing anyone rushing to the queue ... <fantasai> ... any objections to the proposal? <fantasai> RESOLVED: Accept proposal to match JS scinot serialization triggers, other than 6-digit decimal truncation rule |
While it is good to see that small numbers will be serialized with great precision (7 digits) there is a noticeable 'jump' in precision between "e-6" and "e-7". Allowing "6 significant digits" instead of "truncating to 6 digits", for numbers between 0 and 1, would eliminate that 'jump'. (A similar 'jump' happens when large numbers switch to scinot and limiting significant digits would also solve that. Again this is already the behavior of Firefox and PDFreactor. However this isn't really a significant issue.) |
Just to redocument the behavior between browsers currently, here's a testcase: code<!DOCTYPE html>
<div id=test></div>
<table id=results>
<thead><tr><th>JS Value<th>Specified<th>Computed</thead>
</table>
<script>
var test = document.querySelector("#test");
function addRow(...cells) {
var tr = document.createElement("tr");
for(var cell of cells) {
var td = document.createElement("td");
td.textContent = cell;
tr.appendChild(td);
}
document.querySelector("#results").appendChild(tr);
}
for(var i = 0; i < 10; i++) {
var value = .123456789 / Math.pow(10, i);
test.style.opacity = value;
addRow(value, test.style.opacity, getComputedStyle(test).opacity);
}
</script>
<style>
table {
border-collapse: collapse;
}
td {
border: thin solid silver;
padding: 1px 5px;
}
</style> The results are different between all three major engines:
|
Conclusion: yeah, we should indeed mandate six significant figures (matching Firefox, and mostly matching Blink), rather than six figures (kinda matching WebKit, but it never actually switches to scinot so it doesn't count). |
Created from 1796eb4#r102754719.
The spec currently says that scientific notation is not used, but relevant people seem to think that we should in fact use that notation now (see link).
If so, we need to specify when sci-not is and isn't used, and how.
@zcorpan @tabatkins @emilio
The text was updated successfully, but these errors were encountered: