Skip to content

Commit

Permalink
Implement Intl.Locale.prototype.{minimize|maximize}
Browse files Browse the repository at this point in the history
  • Loading branch information
jackhorton committed Sep 8, 2018
1 parent 06bd8ce commit 7d2bd41
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 14 deletions.
1 change: 1 addition & 0 deletions lib/Runtime/Base/JnDirectFields.h
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ ENTRY(builtInJavascriptArrayEntryMap)
ENTRY(builtInJavascriptArrayEntryPush)
ENTRY(builtInJavascriptArrayEntryReduce)
ENTRY(builtInJavascriptArrayEntrySlice)
ENTRY(builtInJavascriptArrayEntrySort)
ENTRY(builtInJavascriptDateEntryGetDate)
ENTRY(builtInJavascriptDateEntryNow)
ENTRY(builtInJavascriptFunctionEntryApply)
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Library/EngineInterfaceObjectBuiltIns.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ GlobalBuiltIn(JavascriptArray, EntryMap)
GlobalBuiltIn(JavascriptArray, EntryReduce)
GlobalBuiltIn(JavascriptArray, EntrySlice)
GlobalBuiltIn(JavascriptArray, EntryConcat)
GlobalBuiltIn(JavascriptArray, EntrySort)

GlobalBuiltIn(JavascriptFunction, EntryBind)
GlobalBuiltIn(JavascriptFunction, EntryApply)
Expand Down
21 changes: 8 additions & 13 deletions lib/Runtime/Library/InJavascript/Intl.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,7 @@

return false;
},
sort(array, sortCallback) {
for (let i = 0; i < array.length; i++) {
for (let j = i; j < array.length; j++) {
const cond = sortCallback ? sortCallback(array[i], array[j]) : array[i] < array[j];
if (cond > 0) {
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
},
sort(array, sortCallback) { return callInstanceFunc(platform.builtInJavascriptArrayEntrySort, array, sortCallback); },

keys: platform.builtInJavascriptObjectEntryKeys,
hasOwnProperty(o, prop) { return callInstanceFunc(platform.builtInJavascriptObjectEntryHasOwnProperty, o, prop); },
Expand Down Expand Up @@ -2251,7 +2240,7 @@

const minMaxImpl = function (loc, methodName) {
const locInternals = getLocaleInternalsObject(loc, methodName);
const minimaximal = platform[`${methodName}Locale`](locInternals);
const minimaximal = platform[`${methodName}Locale`](locInternals.locale);
return new Locale(minimaximal);
};

Expand Down Expand Up @@ -2331,8 +2320,10 @@
}
} else {
const parts = langtagToParts(tag);
const savedLanguage = parts.language;
parts.language = language;
tag = partsToLangtag(parts);
parts.language = savedLanguage;
}
}

Expand All @@ -2355,6 +2346,8 @@
}
} else {
const langtagParts = langtagToParts(tag);
const savedScript = langtagParts.script;
const savedRegion = langtagParts.region;
if (script !== undefined) {
langtagParts.script = script;
}
Expand All @@ -2364,6 +2357,8 @@
}

tag = partsToLangtag(langtagParts);
langtagParts.script = savedScript;
langtagParts.region = savedRegion;
}

// 13. Return CanonicalizeLanguageTag(tag).
Expand Down
70 changes: 70 additions & 0 deletions lib/Runtime/Library/IntlEngineInterfaceExtensionObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3156,6 +3156,76 @@ DEFINE_ISXLOCALEAVAILABLE(PR, uloc)
#endif
}

#ifdef INTL_ICU
template <bool minimize>
static JavascriptString *MinMaxImpl(JavascriptString *langtag, ScriptContext *scriptContext)
{
UErrorCode status = U_ZERO_ERROR;
char localeID[ULOC_FULLNAME_CAPACITY] = { 0 };
LangtagToLocaleID(langtag, localeID);

char minmaxLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 };
int32_t minmaxLocaleIDLength = 0;
if (minimize)
{
minmaxLocaleIDLength = uloc_minimizeSubtags(localeID, minmaxLocaleID, ULOC_FULLNAME_CAPACITY, &status);
INTL_TRACE("Minimizing localeID %S to %S", localeID, minmaxLocaleID);
}
else
{
minmaxLocaleIDLength = uloc_addLikelySubtags(localeID, minmaxLocaleID, ULOC_FULLNAME_CAPACITY, &status);
INTL_TRACE("Maximizing localeID %S to %S", localeID, minmaxLocaleID);
}
ICU_ASSERT(status, minmaxLocaleIDLength < ULOC_FULLNAME_CAPACITY);

char minmaxLangtag[ULOC_FULLNAME_CAPACITY] = { 0 };
int minmaxLangtagLength = uloc_toLanguageTag(minmaxLocaleID, minmaxLangtag, ULOC_FULLNAME_CAPACITY, true, &status);
ICU_ASSERT(status, minmaxLangtagLength > 0);

// allocate maximizedLangtagLength + 1 to leave room for null terminator
char16 *minmaxLangtag16 = RecyclerNewArrayLeaf(scriptContext->GetRecycler(), char16, minmaxLangtagLength + 1);
charcount_t minmaxLangtag16Length = 0;
HRESULT hr = utf8::NarrowStringToWideNoAlloc(
minmaxLangtag,
minmaxLangtagLength,
minmaxLangtag16,
minmaxLangtagLength + 1,
&minmaxLangtag16Length
);
AssertOrFailFast(hr == S_OK && ((int)minmaxLangtag16Length) == minmaxLangtagLength);

return JavascriptString::NewWithBuffer(minmaxLangtag16, minmaxLangtagLength, scriptContext);
}
#endif

Var IntlEngineInterfaceExtensionObject::EntryIntl_MinimizeLocale(RecyclableObject *function, CallInfo callInfo, ...)
{
#ifdef INTL_ICU
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

INTL_CHECK_ARGS(args.Info.Count == 2 && JavascriptString::Is(args.Values[1]));

return MinMaxImpl<true>(JavascriptString::UnsafeFromVar(args.Values[1]), scriptContext);
#else
AssertOrFailFastMsg(false, "Intl-WinGlob should not be using MinimizeLocale");
return nullptr;
#endif
}

Var IntlEngineInterfaceExtensionObject::EntryIntl_MaximizeLocale(RecyclableObject *function, CallInfo callInfo, ...)
{
#ifdef INTL_ICU
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

INTL_CHECK_ARGS(args.Info.Count == 2 && JavascriptString::Is(args.Values[1]));

return MinMaxImpl<false>(JavascriptString::UnsafeFromVar(args.Values[1]), scriptContext);
#else
AssertOrFailFastMsg(false, "Intl-WinGlob should not be using MaximizeLocale");
return nullptr;
#endif
}

/*
* This function registers built in functions when Intl initializes.
* Call with (Function : toRegister, integer : id)
Expand Down
2 changes: 2 additions & 0 deletions lib/Runtime/Library/IntlExtensionObjectBuiltIns.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ INTL_ENTRY(getLocaleData, GetLocaleData)
INTL_ENTRY(localeCompare, LocaleCompare)
INTL_ENTRY(pluralRulesSelect, PluralRulesSelect)
INTL_ENTRY(pluralRulesKeywords, PluralRulesKeywords)
INTL_ENTRY(minimizeLocale, MinimizeLocale)
INTL_ENTRY(maximizeLocale, MaximizeLocale)

INTL_ENTRY(registerBuiltInFunction, RegisterBuiltInFunction)
INTL_ENTRY(getHiddenObject, GetHiddenObject)
Expand Down
16 changes: 15 additions & 1 deletion test/Intl/Locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,24 @@ testRunner.runTests([
assert.areEqual("de", deUnihan.language);
assert.areEqual("unihan", deUnihan.collation);

esUnihanH24 = new Intl.Locale(deUnihan, { language: "es", hourCycle: "h24" });
const esUnihanH24 = new Intl.Locale(deUnihan, { language: "es", hourCycle: "h24" });
assert.areEqual("es", esUnihanH24.language);
assert.areEqual("unihan", esUnihanH24.collation);
assert.areEqual("h24", esUnihanH24.hourCycle);
}
},
{
name: "Maximizing and minimizing",
body() {
function test(input, expected, minimal, maximal) {
const locale = new Intl.Locale(input);
assert.areEqual(expected, locale.toString(), `Incorrect canonicalization of ${input}`);
assert.areEqual(minimal, locale.minimize().toString(), `Incorrect minimization of ${input}`);
assert.areEqual(maximal, locale.maximize().toString(), `Incorrect maximization of ${input}`);
}

test("en", "en", "en", "en-Latn-US");
test("DE-de", "de-DE", "de", "de-Latn-DE");
}
},
], { verbose: false })

0 comments on commit 7d2bd41

Please sign in to comment.