Skip to content

Commit 7d2bd41

Browse files
committed
Implement Intl.Locale.prototype.{minimize|maximize}
1 parent 06bd8ce commit 7d2bd41

6 files changed

+97
-14
lines changed

lib/Runtime/Base/JnDirectFields.h

+1
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ ENTRY(builtInJavascriptArrayEntryMap)
658658
ENTRY(builtInJavascriptArrayEntryPush)
659659
ENTRY(builtInJavascriptArrayEntryReduce)
660660
ENTRY(builtInJavascriptArrayEntrySlice)
661+
ENTRY(builtInJavascriptArrayEntrySort)
661662
ENTRY(builtInJavascriptDateEntryGetDate)
662663
ENTRY(builtInJavascriptDateEntryNow)
663664
ENTRY(builtInJavascriptFunctionEntryApply)

lib/Runtime/Library/EngineInterfaceObjectBuiltIns.h

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ GlobalBuiltIn(JavascriptArray, EntryMap)
3030
GlobalBuiltIn(JavascriptArray, EntryReduce)
3131
GlobalBuiltIn(JavascriptArray, EntrySlice)
3232
GlobalBuiltIn(JavascriptArray, EntryConcat)
33+
GlobalBuiltIn(JavascriptArray, EntrySort)
3334

3435
GlobalBuiltIn(JavascriptFunction, EntryBind)
3536
GlobalBuiltIn(JavascriptFunction, EntryApply)

lib/Runtime/Library/InJavascript/Intl.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,7 @@
131131

132132
return false;
133133
},
134-
sort(array, sortCallback) {
135-
for (let i = 0; i < array.length; i++) {
136-
for (let j = i; j < array.length; j++) {
137-
const cond = sortCallback ? sortCallback(array[i], array[j]) : array[i] < array[j];
138-
if (cond > 0) {
139-
const temp = array[i];
140-
array[i] = array[j];
141-
array[j] = temp;
142-
}
143-
}
144-
}
145-
},
134+
sort(array, sortCallback) { return callInstanceFunc(platform.builtInJavascriptArrayEntrySort, array, sortCallback); },
146135

147136
keys: platform.builtInJavascriptObjectEntryKeys,
148137
hasOwnProperty(o, prop) { return callInstanceFunc(platform.builtInJavascriptObjectEntryHasOwnProperty, o, prop); },
@@ -2251,7 +2240,7 @@
22512240

22522241
const minMaxImpl = function (loc, methodName) {
22532242
const locInternals = getLocaleInternalsObject(loc, methodName);
2254-
const minimaximal = platform[`${methodName}Locale`](locInternals);
2243+
const minimaximal = platform[`${methodName}Locale`](locInternals.locale);
22552244
return new Locale(minimaximal);
22562245
};
22572246

@@ -2331,8 +2320,10 @@
23312320
}
23322321
} else {
23332322
const parts = langtagToParts(tag);
2323+
const savedLanguage = parts.language;
23342324
parts.language = language;
23352325
tag = partsToLangtag(parts);
2326+
parts.language = savedLanguage;
23362327
}
23372328
}
23382329

@@ -2355,6 +2346,8 @@
23552346
}
23562347
} else {
23572348
const langtagParts = langtagToParts(tag);
2349+
const savedScript = langtagParts.script;
2350+
const savedRegion = langtagParts.region;
23582351
if (script !== undefined) {
23592352
langtagParts.script = script;
23602353
}
@@ -2364,6 +2357,8 @@
23642357
}
23652358

23662359
tag = partsToLangtag(langtagParts);
2360+
langtagParts.script = savedScript;
2361+
langtagParts.region = savedRegion;
23672362
}
23682363

23692364
// 13. Return CanonicalizeLanguageTag(tag).

lib/Runtime/Library/IntlEngineInterfaceExtensionObject.cpp

+70
Original file line numberDiff line numberDiff line change
@@ -3156,6 +3156,76 @@ DEFINE_ISXLOCALEAVAILABLE(PR, uloc)
31563156
#endif
31573157
}
31583158

3159+
#ifdef INTL_ICU
3160+
template <bool minimize>
3161+
static JavascriptString *MinMaxImpl(JavascriptString *langtag, ScriptContext *scriptContext)
3162+
{
3163+
UErrorCode status = U_ZERO_ERROR;
3164+
char localeID[ULOC_FULLNAME_CAPACITY] = { 0 };
3165+
LangtagToLocaleID(langtag, localeID);
3166+
3167+
char minmaxLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 };
3168+
int32_t minmaxLocaleIDLength = 0;
3169+
if (minimize)
3170+
{
3171+
minmaxLocaleIDLength = uloc_minimizeSubtags(localeID, minmaxLocaleID, ULOC_FULLNAME_CAPACITY, &status);
3172+
INTL_TRACE("Minimizing localeID %S to %S", localeID, minmaxLocaleID);
3173+
}
3174+
else
3175+
{
3176+
minmaxLocaleIDLength = uloc_addLikelySubtags(localeID, minmaxLocaleID, ULOC_FULLNAME_CAPACITY, &status);
3177+
INTL_TRACE("Maximizing localeID %S to %S", localeID, minmaxLocaleID);
3178+
}
3179+
ICU_ASSERT(status, minmaxLocaleIDLength < ULOC_FULLNAME_CAPACITY);
3180+
3181+
char minmaxLangtag[ULOC_FULLNAME_CAPACITY] = { 0 };
3182+
int minmaxLangtagLength = uloc_toLanguageTag(minmaxLocaleID, minmaxLangtag, ULOC_FULLNAME_CAPACITY, true, &status);
3183+
ICU_ASSERT(status, minmaxLangtagLength > 0);
3184+
3185+
// allocate maximizedLangtagLength + 1 to leave room for null terminator
3186+
char16 *minmaxLangtag16 = RecyclerNewArrayLeaf(scriptContext->GetRecycler(), char16, minmaxLangtagLength + 1);
3187+
charcount_t minmaxLangtag16Length = 0;
3188+
HRESULT hr = utf8::NarrowStringToWideNoAlloc(
3189+
minmaxLangtag,
3190+
minmaxLangtagLength,
3191+
minmaxLangtag16,
3192+
minmaxLangtagLength + 1,
3193+
&minmaxLangtag16Length
3194+
);
3195+
AssertOrFailFast(hr == S_OK && ((int)minmaxLangtag16Length) == minmaxLangtagLength);
3196+
3197+
return JavascriptString::NewWithBuffer(minmaxLangtag16, minmaxLangtagLength, scriptContext);
3198+
}
3199+
#endif
3200+
3201+
Var IntlEngineInterfaceExtensionObject::EntryIntl_MinimizeLocale(RecyclableObject *function, CallInfo callInfo, ...)
3202+
{
3203+
#ifdef INTL_ICU
3204+
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
3205+
3206+
INTL_CHECK_ARGS(args.Info.Count == 2 && JavascriptString::Is(args.Values[1]));
3207+
3208+
return MinMaxImpl<true>(JavascriptString::UnsafeFromVar(args.Values[1]), scriptContext);
3209+
#else
3210+
AssertOrFailFastMsg(false, "Intl-WinGlob should not be using MinimizeLocale");
3211+
return nullptr;
3212+
#endif
3213+
}
3214+
3215+
Var IntlEngineInterfaceExtensionObject::EntryIntl_MaximizeLocale(RecyclableObject *function, CallInfo callInfo, ...)
3216+
{
3217+
#ifdef INTL_ICU
3218+
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
3219+
3220+
INTL_CHECK_ARGS(args.Info.Count == 2 && JavascriptString::Is(args.Values[1]));
3221+
3222+
return MinMaxImpl<false>(JavascriptString::UnsafeFromVar(args.Values[1]), scriptContext);
3223+
#else
3224+
AssertOrFailFastMsg(false, "Intl-WinGlob should not be using MaximizeLocale");
3225+
return nullptr;
3226+
#endif
3227+
}
3228+
31593229
/*
31603230
* This function registers built in functions when Intl initializes.
31613231
* Call with (Function : toRegister, integer : id)

lib/Runtime/Library/IntlExtensionObjectBuiltIns.h

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ INTL_ENTRY(getLocaleData, GetLocaleData)
3737
INTL_ENTRY(localeCompare, LocaleCompare)
3838
INTL_ENTRY(pluralRulesSelect, PluralRulesSelect)
3939
INTL_ENTRY(pluralRulesKeywords, PluralRulesKeywords)
40+
INTL_ENTRY(minimizeLocale, MinimizeLocale)
41+
INTL_ENTRY(maximizeLocale, MaximizeLocale)
4042

4143
INTL_ENTRY(registerBuiltInFunction, RegisterBuiltInFunction)
4244
INTL_ENTRY(getHiddenObject, GetHiddenObject)

test/Intl/Locale.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,24 @@ testRunner.runTests([
5858
assert.areEqual("de", deUnihan.language);
5959
assert.areEqual("unihan", deUnihan.collation);
6060

61-
esUnihanH24 = new Intl.Locale(deUnihan, { language: "es", hourCycle: "h24" });
61+
const esUnihanH24 = new Intl.Locale(deUnihan, { language: "es", hourCycle: "h24" });
6262
assert.areEqual("es", esUnihanH24.language);
6363
assert.areEqual("unihan", esUnihanH24.collation);
6464
assert.areEqual("h24", esUnihanH24.hourCycle);
6565
}
6666
},
67+
{
68+
name: "Maximizing and minimizing",
69+
body() {
70+
function test(input, expected, minimal, maximal) {
71+
const locale = new Intl.Locale(input);
72+
assert.areEqual(expected, locale.toString(), `Incorrect canonicalization of ${input}`);
73+
assert.areEqual(minimal, locale.minimize().toString(), `Incorrect minimization of ${input}`);
74+
assert.areEqual(maximal, locale.maximize().toString(), `Incorrect maximization of ${input}`);
75+
}
76+
77+
test("en", "en", "en", "en-Latn-US");
78+
test("DE-de", "de-DE", "de", "de-Latn-DE");
79+
}
80+
},
6781
], { verbose: false })

0 commit comments

Comments
 (0)