Commit 30729e82 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

[Intl] Move Intl.getCanonicalLocales to C++

Bug: v8:5751
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: I20dc0e7eda58f2d9211d0e569d553dd6fcc14fd3
Reviewed-on: https://chromium-review.googlesource.com/c/1275807
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56747}
parent 5c5dd021
......@@ -2913,6 +2913,9 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
factory->NewJSObject(isolate_->object_function(), TENURED);
JSObject::AddProperty(isolate_, global, name, intl, DONT_ENUM);
SimpleInstallFunction(isolate(), intl, "getCanonicalLocales",
Builtins::kIntlGetCanonicalLocales, 1, false);
{
Handle<JSFunction> date_time_format_constructor = InstallFunction(
isolate_, intl, "DateTimeFormat", JS_INTL_DATE_TIME_FORMAT_TYPE,
......
......@@ -1371,6 +1371,8 @@ namespace internal {
CPP(DateTimeFormatPrototypeResolvedOptions) \
/* ecma402 #sec-intl.datetimeformat.supportedlocalesof */ \
CPP(DateTimeFormatSupportedLocalesOf) \
/* ecma402 #sec-intl.getcanonicallocales */ \
CPP(IntlGetCanonicalLocales) \
/* ecma402 #sec-intl-listformat-constructor */ \
CPP(ListFormatConstructor) \
/* ecma402 #sec-intl-list-format.prototype.format */ \
......
......@@ -485,6 +485,14 @@ BUILTIN(DateTimeFormatInternalFormat) {
isolate, date_format_holder, date));
}
BUILTIN(IntlGetCanonicalLocales) {
HandleScope scope(isolate);
Handle<Object> locales = args.atOrUndefined(isolate, 1);
RETURN_RESULT_OR_FAILURE(isolate,
Intl::GetCanonicalLocales(isolate, locales));
}
BUILTIN(ListFormatConstructor) {
HandleScope scope(isolate);
......
......@@ -17,85 +17,13 @@
// -------------------------------------------------------------------
// Imports
var ArrayPush;
var GlobalIntl = global.Intl;
var GlobalIntlDateTimeFormat = GlobalIntl.DateTimeFormat;
var GlobalIntlNumberFormat = GlobalIntl.NumberFormat;
var GlobalIntlCollator = GlobalIntl.Collator;
var GlobalIntlPluralRules = GlobalIntl.PluralRules;
var GlobalIntlv8BreakIterator = GlobalIntl.v8BreakIterator;
var InternalArray = utils.InternalArray;
utils.Import(function(from) {
ArrayPush = from.ArrayPush;
});
// -------------------------------------------------------------------
/**
* Caches available locales for each service.
*/
var AVAILABLE_LOCALES = {
__proto__ : null,
'collator': UNDEFINED,
'numberformat': UNDEFINED,
'dateformat': UNDEFINED,
'breakiterator': UNDEFINED,
'pluralrules': UNDEFINED,
'relativetimeformat': UNDEFINED,
'listformat': UNDEFINED,
'segmenter': UNDEFINED,
};
/* Make JS array[] out of InternalArray */
function makeArray(input) {
var array = [];
%MoveArrayContents(input, array);
return array;
}
/**
* Returns an InternalArray where all locales are canonicalized and duplicates
* removed.
* Throws on locales that are not well formed BCP47 tags.
* ECMA 402 8.2.1 steps 1 (ECMA 402 9.2.1) and 2.
*/
function canonicalizeLocaleList(locales) {
var seen = new InternalArray();
if (!IS_UNDEFINED(locales)) {
// We allow single string localeID.
if (typeof locales === 'string') {
%_Call(ArrayPush, seen, %CanonicalizeLanguageTag(locales));
return seen;
}
var o = TO_OBJECT(locales);
var len = TO_LENGTH(o.length);
for (var k = 0; k < len; k++) {
if (k in o) {
var value = o[k];
var tag = %CanonicalizeLanguageTag(value);
if (%ArrayIndexOf(seen, tag, 0) === -1) {
%_Call(ArrayPush, seen, tag);
}
}
}
}
return seen;
}
// ECMA 402 section 8.2.1
DEFINE_METHOD(
GlobalIntl,
getCanonicalLocales(locales) {
return makeArray(canonicalizeLocaleList(locales));
}
);
// Save references to Intl objects and methods we use, for added security.
var savedObjects = {
__proto__: null,
......
......@@ -1304,12 +1304,35 @@ std::vector<std::string> BestFitSupportedLocales(
return LookupSupportedLocales(available_locales, requested_locales);
}
enum MatcherOption { kBestFit, kLookup };
// ecma262 #sec-createarrayfromlist
Handle<JSArray> CreateArrayFromList(Isolate* isolate,
std::vector<std::string> elements,
PropertyAttributes attr) {
Factory* factory = isolate->factory();
// Let array be ! ArrayCreate(0).
Handle<JSArray> array = factory->NewJSArray(0);
uint32_t length = static_cast<uint32_t>(elements.size());
// 3. Let n be 0.
// 4. For each element e of elements, do
for (uint32_t i = 0; i < length; i++) {
// a. Let status be CreateDataProperty(array, ! ToString(n), e).
const std::string& part = elements[i];
Handle<String> value =
factory->NewStringFromUtf8(CStrVector(part.c_str())).ToHandleChecked();
JSObject::AddDataElement(array, i, value, attr);
}
// 5. Return array.
return array;
}
// TODO(bstell): should this be moved somewhere where it is reusable?
// Implement steps 5, 6, 7 for ECMA 402 9.2.9 SupportedLocales
// https://tc39.github.io/ecma402/#sec-supportedlocales
MaybeHandle<JSObject> CreateReadOnlyArray(Isolate* isolate,
std::vector<std::string> elements) {
Factory* factory = isolate->factory();
if (elements.size() >= kMaxUInt32) {
THROW_NEW_ERROR(
isolate, NewRangeError(MessageTemplate::kInvalidArrayLength), JSObject);
......@@ -1319,17 +1342,9 @@ MaybeHandle<JSObject> CreateReadOnlyArray(Isolate* isolate,
static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
// 5. Let subset be CreateArrayFromList(elements).
// 6. Let keys be subset.[[OwnPropertyKeys]]().
Handle<JSArray> subset = factory->NewJSArray(0);
Handle<JSArray> subset = CreateArrayFromList(isolate, elements, attr);
// 7. For each element P of keys in List order, do
uint32_t length = static_cast<uint32_t>(elements.size());
for (uint32_t i = 0; i < length; i++) {
const std::string& part = elements[i];
Handle<String> value =
factory->NewStringFromUtf8(CStrVector(part.c_str())).ToHandleChecked();
JSObject::AddDataElement(subset, i, value, attr);
}
// 6. Let keys be subset.[[OwnPropertyKeys]]().
// 7.a. Let desc be PropertyDescriptor { [[Configurable]]: false,
// [[Writable]]: false }.
......@@ -1409,6 +1424,19 @@ MaybeHandle<JSObject> SupportedLocales(
}
} // namespace
// ecma-402 #sec-intl.getcanonicallocales
MaybeHandle<JSArray> Intl::GetCanonicalLocales(Isolate* isolate,
Handle<Object> locales) {
// 1. Let ll be ? CanonicalizeLocaleList(locales).
Maybe<std::vector<std::string>> maybe_ll =
CanonicalizeLocaleList(isolate, locales, false);
MAYBE_RETURN(maybe_ll, MaybeHandle<JSArray>());
// 2. Return CreateArrayFromList(ll).
PropertyAttributes attr = static_cast<PropertyAttributes>(NONE);
return CreateArrayFromList(isolate, maybe_ll.FromJust(), attr);
}
// ECMA 402 Intl.*.supportedLocalesOf
MaybeHandle<JSObject> Intl::SupportedLocalesOf(Isolate* isolate,
ICUService service,
......
......@@ -135,6 +135,10 @@ class Intl {
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved);
// ecma-402 #sec-intl.getcanonicallocales
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> GetCanonicalLocales(
Isolate* isolate, Handle<Object> locales);
// For locale sensitive functions
V8_WARN_UNUSED_RESULT static MaybeHandle<String> StringLocaleConvertCase(
Isolate* isolate, Handle<String> s, bool is_upper,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment