Skip to content

Commit 35d6661

Browse files
TimothyGuMylesBorins
authored andcommitted
deps: cherry-pick 6989b3f6d7 from V8 upstream
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 <littledan@chromium.org> Reviewed-by: Daniel Ehrenberg <littledan@chromium.org> Cr-Commit-Position: refs/heads/master@{#52716} PR-URL: #20826Fixes: #15223 Refs: v8/v8@6989b3f Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent 4e788dc commit 35d6661

12 files changed

Lines changed: 119 additions & 46 deletions

File tree

‎common.gypi‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
# Reset this number to 0 on major V8 upgrades.
2929
# Increment by one for each non-official patch applied to deps/v8.
30-
'v8_embedder_string': '-node.6',
30+
'v8_embedder_string': '-node.7',
3131

3232
# Enable disassembler for `--print-code` v8 options
3333
'v8_enable_disassembler': 1,

‎deps/v8/src/js/intl.js‎

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -152,18 +152,11 @@ var AVAILABLE_LOCALES = {
152152
*/
153153
varDEFAULT_ICU_LOCALE=UNDEFINED;
154154

155-
functionGetDefaultICULocaleJS(service){
155+
functionGetDefaultICULocaleJS(){
156156
if(IS_UNDEFINED(DEFAULT_ICU_LOCALE)){
157157
DEFAULT_ICU_LOCALE=%GetDefaultICULocale();
158158
}
159-
// Check that this is a valid default for this service,
160-
// otherwise fall back to "und"
161-
// TODO(littledan,jshin): AvailableLocalesOf sometimes excludes locales
162-
// which don't require tailoring, but work fine with root data. Look into
163-
// exposing this fact in ICU or the way Chrome bundles data.
164-
return(IS_UNDEFINED(service)||
165-
HAS_OWN_PROPERTY(getAvailableLocalesOf(service),DEFAULT_ICU_LOCALE))
166-
? DEFAULT_ICU_LOCALE : "und";
159+
returnDEFAULT_ICU_LOCALE;
167160
}
168161

169162
/**
@@ -434,6 +427,48 @@ function resolveLocale(service, requestedLocales, options) {
434427
}
435428

436429

430+
/**
431+
* Look up the longest non-empty prefix of |locale| that is an element of
432+
* |availableLocales|. Returns undefined when the |locale| is completely
433+
* unsupported by |availableLocales|.
434+
*/
435+
functionbestAvailableLocale(availableLocales,locale){
436+
do{
437+
if(!IS_UNDEFINED(availableLocales[locale])){
438+
returnlocale;
439+
}
440+
// Truncate locale if possible.
441+
varpos=%StringLastIndexOf(locale,'-');
442+
if(pos===-1){
443+
break;
444+
}
445+
locale=%_Call(StringSubstring,locale,0,pos);
446+
}while(true);
447+
448+
returnUNDEFINED;
449+
}
450+
451+
452+
/**
453+
* Try to match any mutation of |requestedLocale| against |availableLocales|.
454+
*/
455+
functionattemptSingleLookup(availableLocales,requestedLocale){
456+
// Remove all extensions.
457+
varnoExtensionsLocale=%RegExpInternalReplace(
458+
GetAnyExtensionRE(),requestedLocale,'');
459+
varavailableLocale=bestAvailableLocale(
460+
availableLocales,requestedLocale);
461+
if(!IS_UNDEFINED(availableLocale)){
462+
// Return the resolved locale and extension.
463+
varextensionMatch=%regexp_internal_match(
464+
GetUnicodeExtensionRE(),requestedLocale);
465+
varextension=IS_NULL(extensionMatch) ? '' : extensionMatch[0];
466+
return{locale: availableLocale,extension: extension};
467+
}
468+
returnUNDEFINED;
469+
}
470+
471+
437472
/**
438473
* Returns best matched supported locale and extension info using basic
439474
* lookup algorithm.
@@ -446,31 +481,25 @@ function lookupMatcher(service, requestedLocales) {
446481
varavailableLocales=getAvailableLocalesOf(service);
447482

448483
for(vari=0;i<requestedLocales.length;++i){
449-
// Remove all extensions.
450-
varlocale=%RegExpInternalReplace(
451-
GetAnyExtensionRE(),requestedLocales[i],'');
452-
do{
453-
if(!IS_UNDEFINED(availableLocales[locale])){
454-
// Return the resolved locale and extension.
455-
varextensionMatch=%regexp_internal_match(
456-
GetUnicodeExtensionRE(),requestedLocales[i]);
457-
varextension=IS_NULL(extensionMatch) ? '' : extensionMatch[0];
458-
return{locale: locale,extension: extension,position: i};
459-
}
460-
// Truncate locale if possible.
461-
varpos=%StringLastIndexOf(locale,'-');
462-
if(pos===-1){
463-
break;
464-
}
465-
locale=%_Call(StringSubstring,locale,0,pos);
466-
}while(true);
484+
varresult=attemptSingleLookup(availableLocales,requestedLocales[i]);
485+
if(!IS_UNDEFINED(result)){
486+
returnresult;
487+
}
488+
}
489+
490+
vardefLocale=GetDefaultICULocaleJS();
491+
492+
// While ECMA-402 returns defLocale directly, we have to check if it is
493+
// supported, as such support is not guaranteed.
494+
varresult=attemptSingleLookup(availableLocales,defLocale);
495+
if(!IS_UNDEFINED(result)){
496+
returnresult;
467497
}
468498

469499
// Didn't find a match, return default.
470500
return{
471-
locale: GetDefaultICULocaleJS(service),
472-
extension: '',
473-
position: -1
501+
locale: 'und',
502+
extension: ''
474503
};
475504
}
476505

‎deps/v8/test/intl/assert.js‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ function assertFalse(value, user_message = '') {
132132
}
133133

134134

135+
/**
136+
* Throws if value is null.
137+
*/
138+
functionassertNotNull(value,user_message=''){
139+
if(value===null){
140+
fail("not null",value,user_message);
141+
}
142+
}
143+
144+
135145
/**
136146
* Runs code() and asserts that it throws the specified exception.
137147
*/
@@ -189,3 +199,34 @@ function assertInstanceof(obj, type) {
189199
(actualTypeName ? ' but of < '+actualTypeName+'>' : ''));
190200
}
191201
}
202+
203+
204+
/**
205+
* Split a BCP 47 language tag into locale and extension.
206+
*/
207+
functionsplitLanguageTag(tag){
208+
varextRe=/(-[0-9A-Za-z](-[0-9A-Za-z]{2,8})+)+$/;
209+
varmatch=%regexp_internal_match(extRe,tag);
210+
if(match){
211+
return{locale: tag.slice(0,match.index),extension: match[0]};
212+
}
213+
214+
return{locale: tag,extension: ''};
215+
}
216+
217+
218+
/**
219+
* Throw if |parent| is not a more general language tag of |child|, nor |child|
220+
* itself, per BCP 47 rules.
221+
*/
222+
functionassertLanguageTag(child,parent){
223+
varchildSplit=splitLanguageTag(child);
224+
varparentSplit=splitLanguageTag(parent);
225+
226+
// Do not compare extensions at this moment, as %GetDefaultICULocale()
227+
// doesn't always output something we support.
228+
if(childSplit.locale!==parentSplit.locale&&
229+
!childSplit.locale.startsWith(parentSplit.locale+'-')){
230+
fail(child,parent,'language tag comparison');
231+
}
232+
}

‎deps/v8/test/intl/break-iterator/default-locale.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
3737
assertFalse(options.locale==='');
3838
assertFalse(options.locale===undefined);
3939

40-
// Then check for equality.
41-
assertEquals(options.locale,%GetDefaultICULocale());
40+
// Then check for legitimacy.
41+
assertLanguageTag(%GetDefaultICULocale(),options.locale);
4242

4343
variteratorNone=newIntl.v8BreakIterator();
4444
assertEquals(options.locale,iteratorNone.resolvedOptions().locale);

‎deps/v8/test/intl/break-iterator/wellformed-unsupported-locale.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@
2929

3030
variterator=Intl.v8BreakIterator(['xx']);
3131

32-
assertEquals(iterator.resolvedOptions().locale,%GetDefaultICULocale());
32+
assertLanguageTag(%GetDefaultICULocale(),iterator.resolvedOptions().locale);

‎deps/v8/test/intl/collator/default-locale.js‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
3737
assertFalse(options.locale==='');
3838
assertFalse(options.locale===undefined);
3939

40-
// Then check for equality.
41-
assertEquals(options.locale,%GetDefaultICULocale());
40+
// Then check for legitimacy.
41+
assertLanguageTag(%GetDefaultICULocale(),options.locale);
4242

4343
varcollatorNone=newIntl.Collator();
4444
assertEquals(options.locale,collatorNone.resolvedOptions().locale);
@@ -48,5 +48,8 @@ var collatorBraket = new Intl.Collator({});
4848
assertEquals(options.locale,collatorBraket.resolvedOptions().locale);
4949

5050
varcollatorWithOptions=newIntl.Collator(undefined,{usage: 'search'});
51-
assertEquals(%GetDefaultICULocale()+'-u-co-search',
52-
collatorWithOptions.resolvedOptions().locale);
51+
assertLanguageTag(%GetDefaultICULocale(),
52+
collatorWithOptions.resolvedOptions().locale);
53+
assertNotNull(
54+
%regexp_internal_match(/-u(-[a-zA-Z]+-[a-zA-Z]+)*-co-search/,
55+
collatorWithOptions.resolvedOptions().locale));

‎deps/v8/test/intl/collator/wellformed-unsupported-locale.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@
2929

3030
varcollator=Intl.Collator(['xx']);
3131

32-
assertEquals(collator.resolvedOptions().locale,%GetDefaultICULocale());
32+
assertLanguageTag(%GetDefaultICULocale(),collator.resolvedOptions().locale);

‎deps/v8/test/intl/date-format/default-locale.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
3737
assertFalse(options.locale==='');
3838
assertFalse(options.locale===undefined);
3939

40-
// Then check for equality.
41-
assertEquals(options.locale,%GetDefaultICULocale());
40+
// Then check for legitimacy.
41+
assertLanguageTag(%GetDefaultICULocale(),options.locale);
4242

4343
vardtfNone=newIntl.DateTimeFormat();
4444
assertEquals(options.locale,dtfNone.resolvedOptions().locale);

‎deps/v8/test/intl/date-format/wellformed-unsupported-locale.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@
2929

3030
vardtf=Intl.DateTimeFormat(['xx']);
3131

32-
assertEquals(dtf.resolvedOptions().locale,%GetDefaultICULocale());
32+
assertLanguageTag(%GetDefaultICULocale(),dtf.resolvedOptions().locale);

‎deps/v8/test/intl/number-format/default-locale.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ assertFalse(options.locale === 'und');
3737
assertFalse(options.locale==='');
3838
assertFalse(options.locale===undefined);
3939

40-
// Then check for equality.
41-
assertEquals(options.locale,%GetDefaultICULocale());
40+
// Then check for legitimacy.
41+
assertLanguageTag(%GetDefaultICULocale(),options.locale);
4242

4343
varnfNone=newIntl.NumberFormat();
4444
assertEquals(options.locale,nfNone.resolvedOptions().locale);

0 commit comments

Comments
 (0)