-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
Intl.NumberFormat changed behavior (possibly after ICU 58 -> 59 bump) #15223
Comments
Just wondering, do you have full-icu installed? |
Nope! Only the small-icu that we have already packed. Also, this bug is not reproducible on Mac by default. |
Further investigation showed that the fallback logic for unknown locale changed:
|
And we don't have any test for that. We just verify that in case of unknown locale we return defaults here. |
Interestingly, @nodejs/intl Please weigh in. |
So it looks like the test case is hitting this piece of code in V8... node/deps/v8/src/objects/intl-objects.cc Lines 456 to 459 in 56a0577
the comment makes it look like there is a legitimate bug somewhere. Digging deeper... |
v8/v8@2b5a36d from July might or might not help with this. It's not in our tree yet. |
@bnoordhuis Unfortunately that commit does not fix this. I think I got to the bottom of this, however. The key lies in the following lines: node/deps/v8/src/objects/intl-objects.cc Lines 707 to 720 in 56a0577
The docs for
So the returned value should actually be used for the For the test case in the OP, If that were fixed, we should also use the default ICU locale instead of returning NULL, to truly fix the tests. All of this is included in the following patch, which fixes this bug and also factors out the common BCP 47 conversion code for me: From 588bb87e12c9867eca7141b93fff4329a38e5650 Mon Sep 17 00:00:00 2001
From: Timothy Gu <[email protected]>
Date: Thu, 7 Sep 2017 22:08:41 +0800
Subject: [PATCH] Fix BCP47-to-ICU conversion
---
deps/v8/src/objects/intl-objects.cc | 77 ++++++++++---------------------------
1 file changed, 21 insertions(+), 56 deletions(-)
diff --git a/deps/v8/src/objects/intl-objects.cc b/deps/v8/src/objects/intl-objects.cc
index fd6546b390..7a56821a19 100644
--- a/deps/v8/src/objects/intl-objects.cc
+++ b/deps/v8/src/objects/intl-objects.cc
@@ -698,26 +698,30 @@ void SetResolvedBreakIteratorSettings(Isolate* isolate,
.Assert();
}
}
+
+// Convert BCP47 into ICU locale format.
+icu::Locale ConvertFromBCP47(Handle<String> locale) {
+ v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
+ if (bcp47_locale.length() != 0) {
+ UErrorCode status = U_ZERO_ERROR;
+ char icu_result[ULOC_FULLNAME_CAPACITY];
+ int icu_length = uloc_forLanguageTag(*bcp47_locale, icu_result,
+ ULOC_FULLNAME_CAPACITY, nullptr,
+ &status);
+ if (!U_FAILURE(status) && icu_length != 0) {
+ return icu::Locale(icu_result);
+ }
+ }
+ return icu::Locale();
+}
+
} // namespace
// static
icu::SimpleDateFormat* DateFormat::InitializeDateTimeFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
- // Convert BCP47 into ICU locale format.
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
- if (bcp47_locale.length() != 0) {
- uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &status);
- if (U_FAILURE(status) || icu_length == 0) {
- return NULL;
- }
- icu_locale = icu::Locale(icu_result);
- }
+ icu::Locale icu_locale = ConvertFromBCP47(locale);
icu::SimpleDateFormat* date_format =
CreateICUDateFormat(isolate, icu_locale, options);
@@ -753,20 +757,7 @@ void DateFormat::DeleteDateFormat(const v8::WeakCallbackInfo<void>& data) {
icu::DecimalFormat* NumberFormat::InitializeNumberFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
- // Convert BCP47 into ICU locale format.
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
- if (bcp47_locale.length() != 0) {
- uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &status);
- if (U_FAILURE(status) || icu_length == 0) {
- return NULL;
- }
- icu_locale = icu::Locale(icu_result);
- }
+ icu::Locale icu_locale = ConvertFromBCP47(locale);
icu::DecimalFormat* number_format =
CreateICUNumberFormat(isolate, icu_locale, options);
@@ -804,20 +795,7 @@ icu::Collator* Collator::InitializeCollator(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved) {
- // Convert BCP47 into ICU locale format.
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
- if (bcp47_locale.length() != 0) {
- uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &status);
- if (U_FAILURE(status) || icu_length == 0) {
- return NULL;
- }
- icu_locale = icu::Locale(icu_result);
- }
+ icu::Locale icu_locale = ConvertFromBCP47(locale);
icu::Collator* collator = CreateICUCollator(isolate, icu_locale, options);
if (!collator) {
@@ -852,20 +830,7 @@ void Collator::DeleteCollator(const v8::WeakCallbackInfo<void>& data) {
icu::BreakIterator* V8BreakIterator::InitializeBreakIterator(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
- // Convert BCP47 into ICU locale format.
- UErrorCode status = U_ZERO_ERROR;
- icu::Locale icu_locale;
- char icu_result[ULOC_FULLNAME_CAPACITY];
- int icu_length = 0;
- v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
- if (bcp47_locale.length() != 0) {
- uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
- &icu_length, &status);
- if (U_FAILURE(status) || icu_length == 0) {
- return NULL;
- }
- icu_locale = icu::Locale(icu_result);
- }
+ icu::Locale icu_locale = ConvertFromBCP47(locale);
icu::BreakIterator* break_iterator =
CreateICUBreakIterator(isolate, icu_locale, options);
--
2.11.0 Does this patch look okay to be submitted to V8? /cc @nodejs/v8 @addaleax |
@sclinede I don't think this is a bug. The display for |
@srl295 I think the problem lies in the fact that V8 isn't getting the default ICU locale, not that ICU changed its behaviors. The default locale did not change between 58 and 59, nor did the from/toLanguageTag functions. |
@TimothyGu ok - read through the code now (and the change I mentioned above is an old one, so nevermind that). So:
If there are other errors besides parse errors here, it might want to propagate those. |
@srl295 as for me the problem is not about actual sign for the dollar. I understand that there are different kinds of dollars exist. The problem is that logic changed silently. So my thoughts were it should be mentioned in upgrade notes or there should be no diff to previous version of Node. |
@sclinede Again the difference of behavior is a bug in V8. We are working to resolve it. |
Good point. |
@TimothyGu thanks for the clarification |
@TimothyGu I can’t say much about the patch’s content beyond that I don’t see anything wrong with it, and it seems perfectly fine to be submitted to me – let me know if you need anything or run into any trouble! |
So this bug actually goes deeper than #15223 (comment), but about how V8 checks if a system default is supported fundamentally. I've filed a CL at V8 (https://chromium-review.googlesource.com/c/v8/v8/+/668350) that would address those issues, while I will be submitting the patch in #15223 (comment) separately. |
Appears to affect |
@TimothyGu any chance you can provide a status update on this? Doesn't look like your patch landed in V8 yet? |
@apapirovski it was reviewed and ready to get in but seems like the V8 team forgot about it :/ |
With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: nodejs/node#15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{#52716}
@TimothyGu so, is this issue fixed by https://chromium-review.googlesource.com/c/v8/v8/+/668350? If so, we'll have to backport the patch to Node 8 and master (v10.x will get it from there) |
@targos Yes I believe so. I'll try to find time to backport it, but if not it would be great if someone else could :) |
Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: nodejs#15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{nodejs#52716} Refs: v8/v8@6989b3f Fixes: nodejs#15223
Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: nodejs#15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{nodejs#52716} PR-URL: nodejs#20826 Fixes: nodejs#15223 Refs: v8/v8@6989b3f Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: #15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{#52716} PR-URL: #20826 Fixes: #15223 Refs: v8/v8@6989b3f Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: nodejs#15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{nodejs#52716} PR-URL: nodejs#20826 Fixes: nodejs#15223 Refs: v8/v8@6989b3f Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: #15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{#52716} PR-URL: #20826 Fixes: #15223 Refs: v8/v8@6989b3f Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: #15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{#52716} PR-URL: #20826 Fixes: #15223 Refs: v8/v8@6989b3f Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: #15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg <[email protected]> Reviewed-by: Daniel Ehrenberg <[email protected]> Cr-Commit-Position: refs/heads/master@{#52716} PR-URL: #20826 Fixes: #15223 Refs: v8/v8@6989b3f Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
v8.4.0
Linux 8a6b069d5b19 4.10.0-22-generic Simple project messaging. #24~16.04.1-Ubuntu SMP Tue May 23 17:03:51 UTC 2017 x86_64 GNU/Linux
Ubuntu
We're using Jest on Travis for testing and discovered that after Node upgraded from v7.9.0 to v8.4.0 some tests failed. That's okay I thought, but. Finally, I found this odd behavior:
Maybe I missed some breaking changes, so I'll appreciate any help with that.
Otherwise, I think it's a regression and we should reflect on the proper solution.
The text was updated successfully, but these errors were encountered: