You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add test for date/time separating literal for { dateStyle: "medium" } #3776
I have found an implementation inconsistency between Safari (WebKit) and Chrome (V8) where formatting a date with time in en-US locale, if dateStyle is medium, the literal separating the date and time is different.
For example:
newIntl.DateTimeFormat("en-US",{dateStyle: "medium",timeStyle: "short"}).format(newDate())// Google Chrome Version 109.0.5414.119 (Official Build) (arm64)>Jan30,2023,6:50PM// Safari Version 16.1 (18614.2.9.1.12)>Jan30,2023at6:50PM
I wonder which behavior is correct, but the spec is dense and I thought that there should be a test for this case. If you don't think this is the case, please let me know where I should open a bug report.
The standard disclaimer that I give when we get questions about the output of Intl formatter methods and toLocaleString() is that these formats are "implementation-defined" which technically puts this out of scope for test262 because an engine could pretty much have any value they like and still be compliant. In practice, of course, that's not what happens: engines either have no locale data and no Intl object at all, or sensible locale data.
That said, we do have some locale-specific tests for particular bugs, and this isn't the first report of unexpected localization results in Safari 16.1 that I've heard of, so I'll ask around to see if anyone knows more about why this might be the case.
Thanks for pointing me to the right direction, seems like the issue is with CLDR compliance, not DateTimeFormat, but it still affects the outcome. Sorry to hear that this happened before with Safari.
I wouldn’t mind too much since the output is acceptable to me, but to give more context about my issue is that when server-rendering a React application, there’s a hydration mismatch between Node.js and Safari, and React throws an error at runtime. I already have a workaround in place, but I didn’t expect it to happen at all.
Hope this gets fixed soon, and if you learn where can I open an issue please let me know.
I have done some digging and found out some more information.
The major browsers all have their own minor customizations to the CLDR / ICU data. In this particular case, it's a consequence of Apple modifying ICU to conform to the Apple Human Interface Guidelines, to make Safari consistent with the UI in the rest of their operating system. (The source code for Apple's modified ICU is here in case you feel like digging further.) But I learned it's not just Safari, Chrome also makes customizations to ICU which don't ship in Node.js! Despite them sharing a JS engine, they use different locale data, shown here in some locales that have different default numbering systems:
This is all permitted by the specification, due to this part being "implementation-defined". Given the intentional divergence here I think it probably wouldn't be helpful for the landscape of JS implementations to have a test262 test.
I'm not sure what I'd recommend your next steps should be. For now, the workaround is probably the right thing to do here when rendering an application server-side. It might be good to bring the problem to the attention of React so that they can take such mismatches into account when hydrating pages. You could also try opening a discussion on the issue tracker of tc39/ecma402 pointing out that different platforms' customization of ICU causes this type of error, with the goal of tightening the specification to disallow such customizations. (This isn't the only report we've gotten of a server-rendered page failing to hydrate.) But I wouldn't give that a high probability of success — it seems like there are good reasons for browsers to want to make these customizations. Maybe it would be possible to specify one special 'testing' locale where cutomizations are not allowed.
Thanks for the detailed report, it was very helpful. It's sad to see that there are more divergences than I imagined, but I understand that it's allowed to be implementation defined and it makes sense that there cannot be a test for this case.
I likely won't report an issue to ecma402, but may bring this up to the React project, which seems like the right party for it. I'm happy with my current workaround, and seeing that Chrome has modifications too makes it even more necessary.
After some digging, I understand that the supported way to handle these inconsistencies with React is to suppress the hydration warnings at expected places.
I guess there's no way to ensure the client and the server will behave exactly the same, so inevitable some parts will end up different. React itself will render a subtree up to a suspense boundary when it encounters a hydration mismatch, so uncaught mismatches won't create a big problem if there are fine grained suspense boundaries in the app.
Activity
ptomato commentedon Feb 1, 2023
Hi @frontsideair, thanks for the report!
It looks like the version with "at" should occur with
dateStyle: "full"ordateStyle: "long": https://github.com/unicode-org/cldr/blob/main/common/main/en.xml#L2437-L2463The standard disclaimer that I give when we get questions about the output of Intl formatter methods and
toLocaleString()is that these formats are "implementation-defined" which technically puts this out of scope for test262 because an engine could pretty much have any value they like and still be compliant. In practice, of course, that's not what happens: engines either have no locale data and noIntlobject at all, or sensible locale data.That said, we do have some locale-specific tests for particular bugs, and this isn't the first report of unexpected localization results in Safari 16.1 that I've heard of, so I'll ask around to see if anyone knows more about why this might be the case.
frontsideair commentedon Feb 1, 2023
Thanks for pointing me to the right direction, seems like the issue is with CLDR compliance, not DateTimeFormat, but it still affects the outcome. Sorry to hear that this happened before with Safari.
I wouldn’t mind too much since the output is acceptable to me, but to give more context about my issue is that when server-rendering a React application, there’s a hydration mismatch between Node.js and Safari, and React throws an error at runtime. I already have a workaround in place, but I didn’t expect it to happen at all.
Hope this gets fixed soon, and if you learn where can I open an issue please let me know.
ptomato commentedon Feb 14, 2023
I have done some digging and found out some more information.
The major browsers all have their own minor customizations to the CLDR / ICU data. In this particular case, it's a consequence of Apple modifying ICU to conform to the Apple Human Interface Guidelines, to make Safari consistent with the UI in the rest of their operating system. (The source code for Apple's modified ICU is here in case you feel like digging further.) But I learned it's not just Safari, Chrome also makes customizations to ICU which don't ship in Node.js! Despite them sharing a JS engine, they use different locale data, shown here in some locales that have different default numbering systems:
Chromium 109
Node.js 18.9.0
This is all permitted by the specification, due to this part being "implementation-defined". Given the intentional divergence here I think it probably wouldn't be helpful for the landscape of JS implementations to have a test262 test.
I'm not sure what I'd recommend your next steps should be. For now, the workaround is probably the right thing to do here when rendering an application server-side. It might be good to bring the problem to the attention of React so that they can take such mismatches into account when hydrating pages. You could also try opening a discussion on the issue tracker of tc39/ecma402 pointing out that different platforms' customization of ICU causes this type of error, with the goal of tightening the specification to disallow such customizations. (This isn't the only report we've gotten of a server-rendered page failing to hydrate.) But I wouldn't give that a high probability of success — it seems like there are good reasons for browsers to want to make these customizations. Maybe it would be possible to specify one special 'testing' locale where cutomizations are not allowed.
frontsideair commentedon Feb 14, 2023
Thanks for the detailed report, it was very helpful. It's sad to see that there are more divergences than I imagined, but I understand that it's allowed to be implementation defined and it makes sense that there cannot be a test for this case.
I likely won't report an issue to ecma402, but may bring this up to the React project, which seems like the right party for it. I'm happy with my current workaround, and seeing that Chrome has modifications too makes it even more necessary.
Again, thanks for looking into this!
frontsideair commentedon Feb 28, 2023
After some digging, I understand that the supported way to handle these inconsistencies with React is to suppress the hydration warnings at expected places.
I guess there's no way to ensure the client and the server will behave exactly the same, so inevitable some parts will end up different. React itself will render a subtree up to a suspense boundary when it encounters a hydration mismatch, so uncaught mismatches won't create a big problem if there are fine grained suspense boundaries in the app.
ptomato commentedon Feb 28, 2023
Thanks for following up, this is good advice for anyone else encountering the same problem.