mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1433303 - Part 1: Implement Intl.Locale proposal. r=jwalden
Intl.Locale.m{ax,in}imize() are implemented in part 2. Differential Revision: https://phabricator.services.mozilla.com/D38874 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
15afab0390
commit
2684e5023e
@ -839,7 +839,7 @@ static const uint32_t JSCLASS_FOREGROUND_FINALIZE =
|
||||
// application.
|
||||
static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
|
||||
static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
|
||||
JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 38;
|
||||
JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 39;
|
||||
|
||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||
(JSCLASS_IS_GLOBAL | \
|
||||
|
@ -568,6 +568,82 @@ function parseLanguageTag(locale) {
|
||||
return tagObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input normalized to lower case if it matches the
|
||||
* 'unicode_language_subtag' production. Otherwise returns null.
|
||||
*/
|
||||
function parseStandaloneLanguage(language) {
|
||||
// unicode_language_subtag = alpha{2,3} | alpha{5,8} ;
|
||||
var length = language.length;
|
||||
if (length < 2 || length === 4 || length > 8 || !IsASCIIAlphaString(language)) {
|
||||
// Four character language subtags are not allowed in Unicode BCP 47
|
||||
// locale identifiers. Also see the comparison to Unicode CLDR locale
|
||||
// identifiers in <https://unicode.org/reports/tr35/#BCP_47_Conformance>.
|
||||
return null;
|
||||
}
|
||||
|
||||
return callFunction(std_String_toLowerCase, language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input normalized to title case if it matches the
|
||||
* 'unicode_script_subtag' production. Otherwise returns null.
|
||||
*/
|
||||
function parseStandaloneScript(script) {
|
||||
// unicode_script_subtag = alpha{4} ;
|
||||
if (script.length !== 4 || !IsASCIIAlphaString(script)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// The first character of a script code needs to be capitalized.
|
||||
// "hans" -> "Hans"
|
||||
return callFunction(std_String_toUpperCase, script[0]) +
|
||||
callFunction(std_String_toLowerCase, Substring(script, 1, script.length - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input normalized to upper case if it matches the
|
||||
* 'unicode_region_subtag' production. Otherwise returns null.
|
||||
*/
|
||||
function parseStandaloneRegion(region) {
|
||||
// unicode_region_subtag = (alpha{2} | digit{3}) ;
|
||||
var length = region.length;
|
||||
if ((length !== 2 || !IsASCIIAlphaString(region)) &&
|
||||
(length !== 3 || !IsASCIIDigitString(region)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Region codes need to be in upper-case. "bu" -> "BU"
|
||||
return callFunction(std_String_toUpperCase, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input normalized to lower case if it can be parsed as a
|
||||
* '(3*8alphanum) *("-" (3*8alphanum))' subtag sequence. Otherwise returns
|
||||
* null.
|
||||
*/
|
||||
function parseStandaloneUnicodeExtensionType(type) {
|
||||
// Reuse the BCP 47 parser for Unicode extension types.
|
||||
var ts = new BCP47TokenStream(type);
|
||||
NEXT_TOKEN_OR_RETURN_NULL(ts);
|
||||
|
||||
// Unicode extension 'type' subtags must match the following ABNF.
|
||||
//
|
||||
// type = (3*8alphanum) *("-" (3*8alphanum))
|
||||
// alphanum = (ALPHA / DIGIT) ; letters and numbers
|
||||
// ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
|
||||
// DIGIT = %x30-39 ; 0-9
|
||||
do {
|
||||
if (ts.tokenLength < 3 || ts.tokenLength > 8)
|
||||
return null;
|
||||
|
||||
NEXT_TOKEN_OR_RETURN_NULL(ts);
|
||||
} while (ts.token !== NONE);
|
||||
|
||||
return ts.localeLowercase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the locale and fields components of the given valid Transform
|
||||
* extension subtag.
|
||||
@ -807,7 +883,7 @@ function CanonicalizeLanguageTagObject(localeObj) {
|
||||
// Canonicalize Unicode locale extension subtag if present.
|
||||
if (ext[0] === "u") {
|
||||
var {attributes, keywords} = UnicodeExtensionComponents(ext);
|
||||
extensions[i] = CanonicalizeUnicodeExtension(attributes, keywords);
|
||||
extensions[i] = CanonicalizeUnicodeExtension(attributes, keywords, false);
|
||||
}
|
||||
|
||||
// Canonicalize Unicode BCP 47 T extension if present.
|
||||
@ -934,7 +1010,7 @@ function UnicodeExtensionComponents(extension) {
|
||||
* - All keys and types use the canonical form (from the name attribute;
|
||||
* see Section 3.6.4 U Extension Data Files).
|
||||
*/
|
||||
function CanonicalizeUnicodeExtension(attributes, keywords) {
|
||||
function CanonicalizeUnicodeExtension(attributes, keywords, canonicalForm) {
|
||||
assert(attributes.length > 0 || keywords.length > 0,
|
||||
"unexpected empty Unicode locale extension components");
|
||||
|
||||
@ -969,14 +1045,42 @@ function CanonicalizeUnicodeExtension(attributes, keywords) {
|
||||
|
||||
// Append all attributes.
|
||||
for (var i = 0; i < attributes.length; i++) {
|
||||
var attribute = attributes[i];
|
||||
assert(attribute === callFunction(std_String_toLowerCase, attribute),
|
||||
"Attributes are already canonicalized to lower case");
|
||||
|
||||
// UnicodeExtensionComponents ignores duplicate attributes.
|
||||
if (canonicalForm && i > 0 && attributes[i - 1] === attribute) {
|
||||
continue;
|
||||
}
|
||||
|
||||
extension += "-" + attributes[i];
|
||||
}
|
||||
|
||||
// Append all keywords.
|
||||
for (var i = 0; i < keywords.length; i++) {
|
||||
var {key, value} = keywords[i];
|
||||
assert(key === callFunction(std_String_toLowerCase, key) &&
|
||||
value === callFunction(std_String_toLowerCase, value),
|
||||
"Keywords are already canonicalized to lower case");
|
||||
|
||||
|
||||
// UnicodeExtensionComponents ignores duplicate keys.
|
||||
if (canonicalForm && i > 0 && keywords[i - 1].key === key) {
|
||||
continue;
|
||||
}
|
||||
|
||||
extension += "-" + key;
|
||||
|
||||
if (canonicalForm &&
|
||||
hasOwn(key, deprecatedUnicodeExtensionTypes) &&
|
||||
hasOwn(value, deprecatedUnicodeExtensionTypes[key]))
|
||||
{
|
||||
value = deprecatedUnicodeExtensionTypes[key][value];
|
||||
assert(value === callFunction(std_String_toLowerCase, value),
|
||||
"Preferred keyword value is already in lower case");
|
||||
}
|
||||
|
||||
// Type value "true" is removed.
|
||||
if (value !== "" && value !== "true")
|
||||
extension += "-" + value;
|
||||
@ -1132,6 +1236,20 @@ function IsASCIIAlphaString(s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the input contains only ASCII digit characters.
|
||||
*/
|
||||
function IsASCIIDigitString(s) {
|
||||
assert(typeof s === "string", "IsASCIIDigitString");
|
||||
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
var c = callFunction(std_String_charCodeAt, s, i);
|
||||
if (!(0x30 <= c && c <= 0x39))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and canonicalizes the given language tag.
|
||||
*/
|
||||
@ -1325,6 +1443,10 @@ function CanonicalizeLocaleList(locales) {
|
||||
if (typeof locales === "string")
|
||||
return [ValidateAndCanonicalizeLanguageTag(locales)];
|
||||
|
||||
var unboxedLocale = callFunction(unboxLocaleOrNull, locales);
|
||||
if (unboxedLocale !== null)
|
||||
return [StringFromLanguageTagObject(unboxedLocale.locale)]
|
||||
|
||||
// Step 2.
|
||||
var seen = [];
|
||||
|
||||
@ -1348,11 +1470,11 @@ function CanonicalizeLocaleList(locales) {
|
||||
if (!(typeof kValue === "string" || IsObject(kValue)))
|
||||
ThrowTypeError(JSMSG_INVALID_LOCALES_ELEMENT);
|
||||
|
||||
// Step 7.c.iii.
|
||||
var tag = ToString(kValue);
|
||||
|
||||
// Step 7.c.iv.
|
||||
tag = ValidateAndCanonicalizeLanguageTag(tag);
|
||||
// Steps 7.c.iii-iv.
|
||||
var unboxedLocale = callFunction(unboxLocaleOrNull, kValue);
|
||||
var tag = unboxedLocale !== null
|
||||
? StringFromLanguageTagObject(unboxedLocale.locale)
|
||||
: ValidateAndCanonicalizeLanguageTag(ToString(kValue));
|
||||
|
||||
// Step 7.c.v.
|
||||
if (callFunction(ArrayIndexOf, seen, tag) === -1)
|
||||
|
167
js/src/builtin/intl/Locale.cpp
Normal file
167
js/src/builtin/intl/Locale.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Intl.Locale implementation. */
|
||||
|
||||
#include "builtin/intl/Locale.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "builtin/intl/CommonFunctions.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
||||
#include "vm/JSObject-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
const Class LocaleObject::class_ = {
|
||||
js_Object_str,
|
||||
JSCLASS_HAS_RESERVED_SLOTS(LocaleObject::SLOT_COUNT),
|
||||
};
|
||||
|
||||
static bool locale_toSource(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setString(cx->names().Locale);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const JSFunctionSpec locale_methods[] = {
|
||||
JS_SELF_HOSTED_FN("toString", "Intl_Locale_toString", 0, 0),
|
||||
JS_FN(js_toSource_str, locale_toSource, 0, 0), JS_FS_END};
|
||||
|
||||
static const JSPropertySpec locale_properties[] = {
|
||||
JS_SELF_HOSTED_GET("baseName", "$Intl_Locale_baseName_get", 0),
|
||||
JS_SELF_HOSTED_GET("calendar", "$Intl_Locale_calendar_get", 0),
|
||||
JS_SELF_HOSTED_GET("collation", "$Intl_Locale_collation_get", 0),
|
||||
JS_SELF_HOSTED_GET("hourCycle", "$Intl_Locale_hourCycle_get", 0),
|
||||
JS_SELF_HOSTED_GET("caseFirst", "$Intl_Locale_caseFirst_get", 0),
|
||||
JS_SELF_HOSTED_GET("numeric", "$Intl_Locale_numeric_get", 0),
|
||||
JS_SELF_HOSTED_GET("numberingSystem", "$Intl_Locale_numberingSystem_get",
|
||||
0),
|
||||
JS_SELF_HOSTED_GET("language", "$Intl_Locale_language_get", 0),
|
||||
JS_SELF_HOSTED_GET("script", "$Intl_Locale_script_get", 0),
|
||||
JS_SELF_HOSTED_GET("region", "$Intl_Locale_region_get", 0),
|
||||
JS_STRING_SYM_PS(toStringTag, "Intl.Locale", JSPROP_READONLY),
|
||||
JS_PS_END};
|
||||
|
||||
static LocaleObject* CreateLocaleObject(JSContext* cx, HandleObject prototype) {
|
||||
RootedObject proto(cx, prototype);
|
||||
if (!proto) {
|
||||
proto = GlobalObject::getOrCreateLocalePrototype(cx, cx->global());
|
||||
if (!proto) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LocaleObject* locale = NewObjectWithGivenProto<LocaleObject>(cx, proto);
|
||||
if (!locale) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
locale->setReservedSlot(LocaleObject::INTERNALS_SLOT, NullValue());
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intl.Locale( tag[, options] )
|
||||
*/
|
||||
static bool Locale(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1.
|
||||
if (!ThrowIfNotConstructing(cx, args, "Intl.Locale")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 2-6 (Inlined 9.1.14, OrdinaryCreateFromConstructor).
|
||||
RootedObject proto(cx);
|
||||
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_Null, &proto)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Rooted<LocaleObject*> locale(cx, CreateLocaleObject(cx, proto));
|
||||
if (!locale) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HandleValue tag = args.get(0);
|
||||
HandleValue options = args.get(1);
|
||||
|
||||
// Steps 7-37.
|
||||
if (!intl::InitializeObject(cx, locale, cx->names().InitializeLocale, tag,
|
||||
options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 38.
|
||||
args.rval().setObject(*locale);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject* js::CreateLocalePrototype(JSContext* cx, HandleObject Intl,
|
||||
Handle<GlobalObject*> global) {
|
||||
RootedFunction ctor(
|
||||
cx, GlobalObject::createConstructor(cx, &Locale, cx->names().Locale, 1));
|
||||
if (!ctor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedObject proto(
|
||||
cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
||||
if (!proto) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!LinkConstructorAndPrototype(cx, ctor, proto)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!DefinePropertiesAndFunctions(cx, proto, locale_properties,
|
||||
locale_methods)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedValue ctorValue(cx, ObjectValue(*ctor));
|
||||
if (!DefineDataProperty(cx, Intl, cx->names().Locale, ctorValue, 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
/* static */ bool js::GlobalObject::addLocaleConstructor(JSContext* cx,
|
||||
HandleObject intl) {
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
|
||||
{
|
||||
const Value& proto = global->getReservedSlot(LOCALE_PROTO);
|
||||
if (!proto.isUndefined()) {
|
||||
MOZ_ASSERT(proto.isObject());
|
||||
JS_ReportErrorASCII(cx,
|
||||
"the Locale constructor can't be added multiple "
|
||||
"times in the same global");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject* localeProto = CreateLocalePrototype(cx, intl, global);
|
||||
if (!localeProto) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global->setReservedSlot(LOCALE_PROTO, ObjectValue(*localeProto));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool js::AddLocaleConstructor(JSContext* cx, JS::Handle<JSObject*> intl) {
|
||||
return GlobalObject::addLocaleConstructor(cx, intl);
|
||||
}
|
||||
|
38
js/src/builtin/intl/Locale.h
Normal file
38
js/src/builtin/intl/Locale.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef builtin_intl_Locale_h
|
||||
#define builtin_intl_Locale_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "js/Class.h"
|
||||
#include "vm/NativeObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class GlobalObject;
|
||||
|
||||
class LocaleObject : public NativeObject {
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
static constexpr uint32_t INTERNALS_SLOT = 0;
|
||||
static constexpr uint32_t SLOT_COUNT = 1;
|
||||
|
||||
static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
|
||||
"INTERNALS_SLOT must match self-hosting define for internals "
|
||||
"object slot");
|
||||
};
|
||||
|
||||
extern JSObject* CreateLocalePrototype(JSContext* cx,
|
||||
JS::Handle<JSObject*> Intl,
|
||||
JS::Handle<GlobalObject*> global);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* builtin_intl_Locale_h */
|
605
js/src/builtin/intl/Locale.js
Normal file
605
js/src/builtin/intl/Locale.js
Normal file
@ -0,0 +1,605 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Intl.Locale internal properties.
|
||||
*/
|
||||
var localeInternalProperties = {
|
||||
relevantExtensionKeys: ["ca", "co", "hc", "kf", "kn", "nu"],
|
||||
};
|
||||
|
||||
/**
|
||||
* ApplyOptionsToTag( tag, options )
|
||||
*/
|
||||
function ApplyOptionsToTag(tagObj, options) {
|
||||
// Steps 1-2 (Already performed in caller).
|
||||
|
||||
// Step 3.
|
||||
var languageOption = GetOption(options, "language", "string", undefined, undefined);
|
||||
|
||||
// Step 4.
|
||||
var language;
|
||||
if (languageOption !== undefined) {
|
||||
language = parseStandaloneLanguage(languageOption);
|
||||
if (language === null)
|
||||
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "language", languageOption);
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
var scriptOption = GetOption(options, "script", "string", undefined, undefined);
|
||||
|
||||
// Step 6.
|
||||
var script;
|
||||
if (scriptOption !== undefined) {
|
||||
script = parseStandaloneScript(scriptOption);
|
||||
if (script === null)
|
||||
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "script", scriptOption);
|
||||
}
|
||||
|
||||
// Step 7.
|
||||
var regionOption = GetOption(options, "region", "string", undefined, undefined);
|
||||
|
||||
// Step 8.
|
||||
var region;
|
||||
if (regionOption !== undefined) {
|
||||
region = parseStandaloneRegion(regionOption);
|
||||
if (region === null)
|
||||
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "region", regionOption);
|
||||
}
|
||||
|
||||
// Step 9 (Already performed in caller).
|
||||
|
||||
// Return early when no subtags were modified.
|
||||
if (language === undefined && script === undefined && region === undefined)
|
||||
return;
|
||||
|
||||
// Step 10.
|
||||
if (language !== undefined)
|
||||
tagObj.language = language;
|
||||
|
||||
// Step 11.
|
||||
if (script !== undefined)
|
||||
tagObj.script = script;
|
||||
|
||||
// Step 12.
|
||||
if (region !== undefined)
|
||||
tagObj.region = region;
|
||||
|
||||
// Replacing the "language" subtag may have turned this locale tag
|
||||
// into a grandfathered language tag. For example consider the
|
||||
// case `new Intl.Locale("en-hakka", {language: "zh"})`, where
|
||||
// "zh-hakka" is a regular grandfathered language tag.
|
||||
if (language !== undefined)
|
||||
updateGrandfatheredMappings(tagObj);
|
||||
|
||||
// Step 13.
|
||||
// Optimized to only update the mappings, because all other canonicalization
|
||||
// steps already happended earlier, so there's no need to repeat them here.
|
||||
updateLocaleIdMappings(tagObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* ApplyUnicodeExtensionToTag( tag, options, relevantExtensionKeys )
|
||||
*/
|
||||
function ApplyUnicodeExtensionToTag(tagObj, options, relevantExtensionKeys) {
|
||||
// Steps 1-2 (Not applicable).
|
||||
|
||||
// Step 3.a
|
||||
// Find the Unicode extension subtag index in |tagObj.extensions|.
|
||||
var extensions = tagObj.extensions;
|
||||
var extensionIndex = -1;
|
||||
for (var i = 0; i < extensions.length; i++) {
|
||||
if (extensions[i][0] === "u") {
|
||||
extensionIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If Unicode extensions are neither present in |tagObj| nor in |options|,
|
||||
// we can skip everything below and directly return here.
|
||||
if (extensionIndex < 0) {
|
||||
var hasUnicodeOptions = false;
|
||||
for (var i = 0; i < relevantExtensionKeys.length; i++) {
|
||||
if (options[relevantExtensionKeys[i]] !== undefined) {
|
||||
hasUnicodeOptions = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasUnicodeOptions)
|
||||
return;
|
||||
}
|
||||
|
||||
var attributes, keywords;
|
||||
if (extensionIndex >= 0) {
|
||||
// Step 3.b.
|
||||
var components = UnicodeExtensionComponents(extensions[extensionIndex]);
|
||||
|
||||
// Step 3.c.
|
||||
attributes = components.attributes;
|
||||
|
||||
// Step 3.d.
|
||||
keywords = components.keywords;
|
||||
} else {
|
||||
// Step 4.a.
|
||||
attributes = [];
|
||||
|
||||
// Step 4.b.
|
||||
keywords = [];
|
||||
}
|
||||
|
||||
// Step 5 (Not applicable).
|
||||
|
||||
// Step 6.
|
||||
for (var i = 0; i < relevantExtensionKeys.length; i++) {
|
||||
var key = relevantExtensionKeys[i];
|
||||
|
||||
// Step 6.a.
|
||||
var value = undefined;
|
||||
|
||||
// Steps 6.b-c.
|
||||
var entry = null;
|
||||
for (var j = 0; j < keywords.length; j++) {
|
||||
if (keywords[j].key === key) {
|
||||
entry = keywords[j];
|
||||
value = entry.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6.d.
|
||||
assert(hasOwn(key, options), "option value for each extension key present");
|
||||
|
||||
// Step 6.e.
|
||||
var optionsValue = options[key];
|
||||
|
||||
// Step 6.f.
|
||||
if (optionsValue !== undefined) {
|
||||
// Step 6.f.i.
|
||||
assert(typeof optionsValue === "string", "optionsValue is a string");
|
||||
|
||||
// Step 6.f.ii.
|
||||
value = optionsValue;
|
||||
|
||||
// Steps 6.f.iii-iv.
|
||||
if (entry !== null)
|
||||
entry.value = value;
|
||||
else
|
||||
_DefineDataProperty(keywords, keywords.length, {key, value});
|
||||
}
|
||||
|
||||
// Step 6.g (Modify |options| in place).
|
||||
options[key] = value;
|
||||
}
|
||||
|
||||
// Step 7 (Not applicable).
|
||||
|
||||
// Step 8.
|
||||
var newExtension = CanonicalizeUnicodeExtension(attributes, keywords, true);
|
||||
|
||||
// Step 9 (Inlined call to InsertUnicodeExtension).
|
||||
// If the shortcut below step 3.a wasn't taken, the Unicode extension is
|
||||
// definitely non-empty; assert this here.
|
||||
assert(newExtension !== "", "unexpected empty Unicode extension");
|
||||
|
||||
// Update or add the new Unicode extension sequence.
|
||||
if (extensionIndex >= 0) {
|
||||
extensions[extensionIndex] = newExtension;
|
||||
} else {
|
||||
_DefineDataProperty(extensions, extensions.length, newExtension);
|
||||
|
||||
// Extension sequences are sorted by their singleton characters.
|
||||
if (extensions.length > 1) {
|
||||
callFunction(ArraySort, extensions);
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 10-11 (Not applicable).
|
||||
}
|
||||
|
||||
/**
|
||||
* Intl.Locale( tag[, options] )
|
||||
*/
|
||||
function InitializeLocale(locale, tag, options) {
|
||||
// Step 7.
|
||||
if (!(typeof tag === "string" || IsObject(tag)))
|
||||
ThrowTypeError(JSMSG_INVALID_LOCALES_ELEMENT);
|
||||
|
||||
// Steps 8-9.
|
||||
var unboxedLocale = callFunction(unboxLocaleOrNull, tag);
|
||||
if (unboxedLocale === null)
|
||||
tag = ToString(tag);
|
||||
|
||||
// Steps 10-11.
|
||||
var hasOptions = options !== undefined;
|
||||
if (hasOptions)
|
||||
options = ToObject(options);
|
||||
|
||||
// Step 12.
|
||||
var tagObj;
|
||||
if (unboxedLocale === null) {
|
||||
tagObj = parseLanguageTag(tag);
|
||||
if (tagObj === null)
|
||||
ThrowRangeError(JSMSG_INVALID_LANGUAGE_TAG, tag);
|
||||
|
||||
// ApplyOptionsToTag, step 9.
|
||||
CanonicalizeLanguageTagObject(tagObj);
|
||||
} else {
|
||||
tagObj = copyLanguageTagObject(unboxedLocale.locale);
|
||||
|
||||
// |tagObj| is already canonicalized for Intl.Locale objects, so we can
|
||||
// skip ApplyOptionsToTag, step 9.
|
||||
}
|
||||
|
||||
// Step 13.
|
||||
var opt = new Record();
|
||||
|
||||
// Skip rest of step 12 and steps 14-29 if no options were passed to the
|
||||
// Intl.Locale constructor.
|
||||
if (hasOptions) {
|
||||
// Step 12.
|
||||
ApplyOptionsToTag(tagObj, options);
|
||||
|
||||
// Step 14.
|
||||
var calendar = GetOption(options, "calendar", "string", undefined, undefined);
|
||||
|
||||
// Step 15.
|
||||
if (calendar !== undefined) {
|
||||
var standaloneCalendar = parseStandaloneUnicodeExtensionType(calendar);
|
||||
if (standaloneCalendar === null)
|
||||
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "calendar", calendar);
|
||||
|
||||
calendar = standaloneCalendar;
|
||||
}
|
||||
|
||||
// Step 16.
|
||||
opt.ca = calendar;
|
||||
|
||||
// Step 17.
|
||||
var collation = GetOption(options, "collation", "string", undefined, undefined);
|
||||
|
||||
// Step 18.
|
||||
if (collation !== undefined) {
|
||||
var standaloneCollation = parseStandaloneUnicodeExtensionType(collation);
|
||||
if (standaloneCollation === null)
|
||||
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "collation", collation);
|
||||
|
||||
collation = standaloneCollation;
|
||||
}
|
||||
|
||||
// Step 19.
|
||||
opt.co = collation;
|
||||
|
||||
// Steps 20-21.
|
||||
opt.hc = GetOption(options, "hourCycle", "string", ["h11", "h12", "h23", "h24"],
|
||||
undefined);
|
||||
|
||||
// Steps 22-23.
|
||||
opt.kf = GetOption(options, "caseFirst", "string", ["upper", "lower", "false"],
|
||||
undefined);
|
||||
|
||||
// Step 24.
|
||||
var numeric = GetOption(options, "numeric", "boolean", undefined, undefined);
|
||||
|
||||
// Step 25.
|
||||
if (numeric !== undefined)
|
||||
numeric = ToString(numeric);
|
||||
|
||||
// Step 26.
|
||||
opt.kn = numeric;
|
||||
|
||||
// Step 27.
|
||||
var numberingSystem = GetOption(options, "numberingSystem", "string", undefined,
|
||||
undefined);
|
||||
|
||||
// Step 28.
|
||||
if (numberingSystem !== undefined) {
|
||||
var standaloneNumberingSystem = parseStandaloneUnicodeExtensionType(numberingSystem);
|
||||
if (standaloneNumberingSystem === null)
|
||||
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "numberingSystem", numberingSystem);
|
||||
|
||||
numberingSystem = standaloneNumberingSystem;
|
||||
}
|
||||
|
||||
// Step 29.
|
||||
opt.nu = numberingSystem;
|
||||
} else {
|
||||
// Steps 14-29.
|
||||
opt.ca = undefined;
|
||||
opt.co = undefined;
|
||||
opt.hc = undefined;
|
||||
opt.kf = undefined;
|
||||
opt.kn = undefined;
|
||||
opt.nu = undefined;
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
var {relevantExtensionKeys} = localeInternalProperties;
|
||||
|
||||
// Step 30.
|
||||
if (hasOptions || unboxedLocale === null) {
|
||||
ApplyUnicodeExtensionToTag(tagObj, opt, relevantExtensionKeys);
|
||||
} else {
|
||||
// Directly copy the Unicode extension keys from the source object if
|
||||
// no options were passed to the constructor.
|
||||
opt.ca = unboxedLocale.calendar;
|
||||
opt.co = unboxedLocale.collation;
|
||||
opt.hc = unboxedLocale.hourCycle;
|
||||
opt.kf = unboxedLocale.caseFirst;
|
||||
opt.kn = unboxedLocale.numeric;
|
||||
opt.nu = unboxedLocale.numberingSystem;
|
||||
}
|
||||
|
||||
// Steps 31-37.
|
||||
var internals = new Record();
|
||||
internals.locale = tagObj;
|
||||
internals.calendar = opt.ca;
|
||||
internals.collation = opt.co;
|
||||
internals.hourCycle = opt.hc;
|
||||
internals.caseFirst = opt.kf;
|
||||
internals.numeric = opt.kn === "true" || opt.kn === "";
|
||||
internals.numberingSystem = opt.nu;
|
||||
|
||||
assert(UnsafeGetReservedSlot(locale, INTL_INTERNALS_OBJECT_SLOT) === null,
|
||||
"Internal slot already initialized?");
|
||||
UnsafeSetReservedSlot(locale, INTL_INTERNALS_OBJECT_SLOT, internals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unboxes the |this| argument if it is an Intl.Locale object, otherwise
|
||||
* returns null.
|
||||
*/
|
||||
function unboxLocaleOrNull() {
|
||||
if (!IsObject(this))
|
||||
return null;
|
||||
|
||||
var loc = GuardToLocale(this);
|
||||
if (loc !== null)
|
||||
return getLocaleInternals(loc);
|
||||
if (IsWrappedLocale(this))
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "unboxLocaleOrNull");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the given language tag object.
|
||||
*/
|
||||
function copyLanguageTagObject(tagObj) {
|
||||
assert(IsObject(tagObj), "copyLanguageTagObject called with non-object");
|
||||
|
||||
var variants = [];
|
||||
for (var i = 0; i < tagObj.variants.length; i++)
|
||||
_DefineDataProperty(variants, i, tagObj.variants[i]);
|
||||
|
||||
var extensions = [];
|
||||
for (var i = 0; i < tagObj.extensions.length; i++)
|
||||
_DefineDataProperty(extensions, i, tagObj.extensions[i]);
|
||||
|
||||
return {
|
||||
language: tagObj.language,
|
||||
script: tagObj.script,
|
||||
region: tagObj.region,
|
||||
variants,
|
||||
extensions,
|
||||
privateuse: tagObj.privateuse,
|
||||
};
|
||||
}
|
||||
|
||||
function getLocaleInternals(obj) {
|
||||
assert(IsObject(obj), "getLocaleInternals called with non-object");
|
||||
assert(GuardToLocale(obj) !== null, "getLocaleInternals called with non-Locale");
|
||||
|
||||
var internals = UnsafeGetReservedSlot(obj, INTL_INTERNALS_OBJECT_SLOT);
|
||||
assert(IsObject(internals), "Internal slot not initialized?");
|
||||
|
||||
return internals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intl.Locale.prototype.toString ()
|
||||
*/
|
||||
function Intl_Locale_toString() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "Intl_Locale_toString");
|
||||
|
||||
// Step 3.
|
||||
var tagObj = getLocaleInternals(loc).locale;
|
||||
return StringFromLanguageTagObject(tagObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.baseName
|
||||
*/
|
||||
function $Intl_Locale_baseName_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_baseName_get");
|
||||
|
||||
// Step 3.
|
||||
var tagObj = getLocaleInternals(loc).locale;
|
||||
|
||||
// Step 4.
|
||||
// FIXME: spec bug - unicode_locale_id is always matched.
|
||||
|
||||
// Step 5.
|
||||
// FIXME: spec bug - subtag production names not updated.
|
||||
var baseName = tagObj.language;
|
||||
|
||||
if (tagObj.script !== undefined)
|
||||
baseName += "-" + tagObj.script;
|
||||
if (tagObj.region !== undefined)
|
||||
baseName += "-" + tagObj.region;
|
||||
if (tagObj.variants.length > 0)
|
||||
baseName += "-" + callFunction(std_Array_join, tagObj.variants, "-");
|
||||
|
||||
return baseName;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_baseName_get, "get baseName");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.calendar
|
||||
*/
|
||||
function $Intl_Locale_calendar_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_calendar_get");
|
||||
|
||||
// Step 3.
|
||||
return getLocaleInternals(loc).calendar;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_calendar_get, "get calendar");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.collation
|
||||
*/
|
||||
function $Intl_Locale_collation_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_collation_get");
|
||||
|
||||
// Step 3.
|
||||
return getLocaleInternals(loc).collation;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_collation_get, "get collation");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.hourCycle
|
||||
*/
|
||||
function $Intl_Locale_hourCycle_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_hourCycle_get");
|
||||
|
||||
// Step 3.
|
||||
return getLocaleInternals(loc).hourCycle;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_hourCycle_get, "get hourCycle");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.caseFirst
|
||||
*/
|
||||
function $Intl_Locale_caseFirst_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_caseFirst_get");
|
||||
|
||||
// Step 3.
|
||||
return getLocaleInternals(loc).caseFirst;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_caseFirst_get, "get caseFirst");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.numeric
|
||||
*/
|
||||
function $Intl_Locale_numeric_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_numeric_get");
|
||||
|
||||
// Step 3.
|
||||
return getLocaleInternals(loc).numeric;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_numeric_get, "get numeric");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.numberingSystem
|
||||
*/
|
||||
function $Intl_Locale_numberingSystem_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_numberingSystem_get");
|
||||
|
||||
// Step 3.
|
||||
return getLocaleInternals(loc).numberingSystem;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_numberingSystem_get, "get numberingSystem");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.language
|
||||
*/
|
||||
function $Intl_Locale_language_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_language_get");
|
||||
|
||||
// Step 3.
|
||||
var tagObj = getLocaleInternals(loc).locale;
|
||||
|
||||
// Step 4 (Unnecessary assertion).
|
||||
|
||||
// Step 5.
|
||||
return tagObj.language;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_language_get, "get language");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.script
|
||||
*/
|
||||
function $Intl_Locale_script_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_script_get");
|
||||
|
||||
// Step 3.
|
||||
var tagObj = getLocaleInternals(loc).locale;
|
||||
|
||||
// Step 4 (Unnecessary assertion).
|
||||
|
||||
// Steps 5-6.
|
||||
// FIXME: spec bug - not all production names updated.
|
||||
return tagObj.script;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_script_get, "get script");
|
||||
|
||||
/**
|
||||
* get Intl.Locale.prototype.region
|
||||
*/
|
||||
function $Intl_Locale_region_get() {
|
||||
// Step 1.
|
||||
var loc = this;
|
||||
|
||||
// Step 2.
|
||||
if (!IsObject(loc) || (loc = GuardToLocale(loc)) === null)
|
||||
return callFunction(CallLocaleMethodIfWrapped, this, "$Intl_Locale_region_get");
|
||||
|
||||
// Step 3.
|
||||
var tagObj = getLocaleInternals(loc).locale;
|
||||
|
||||
// Step 4 (Unnecessary assertion).
|
||||
|
||||
// Steps 5-6.
|
||||
// FIXME: spec bug - not all production names updated.
|
||||
return tagObj.region;
|
||||
}
|
||||
_SetCanonicalName($Intl_Locale_region_get, "get region");
|
371
js/src/builtin/intl/UnicodeExtensionsGenerated.js
Normal file
371
js/src/builtin/intl/UnicodeExtensionsGenerated.js
Normal file
@ -0,0 +1,371 @@
|
||||
// Generated by make_intl_data.py. DO NOT EDIT.
|
||||
// Version: CLDR-35.1
|
||||
// URL: https://unicode.org/Public/cldr/35.1/core.zip
|
||||
|
||||
/**
|
||||
* Mapping from deprecated BCP 47 Unicode extension types to their preferred
|
||||
* values.
|
||||
*
|
||||
* Spec: https://www.unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files
|
||||
*/
|
||||
var deprecatedUnicodeExtensionTypes = {
|
||||
ca: {
|
||||
// Ethiopic calendar, Amete Alem (epoch approx. 5493 B.C.E)
|
||||
"ethiopic-amete-alem": "ethioaa",
|
||||
|
||||
// Civil (algorithmic) Arabic calendar
|
||||
"islamicc": "islamic-civil",
|
||||
},
|
||||
kb: {
|
||||
// The second level to be backwards
|
||||
"yes": "true",
|
||||
},
|
||||
kc: {
|
||||
// The case level is inserted in front of tertiary
|
||||
"yes": "true",
|
||||
},
|
||||
kh: {
|
||||
// Hiragana to be sorted before all non-variable on quaternary level
|
||||
"yes": "true",
|
||||
},
|
||||
kk: {
|
||||
// Convert text into Normalization Form D before calculating collation weights
|
||||
"yes": "true",
|
||||
},
|
||||
kn: {
|
||||
// A sequence of decimal digits is sorted at primary level with its numeric value
|
||||
"yes": "true",
|
||||
},
|
||||
ks: {
|
||||
// The primary level
|
||||
"primary": "level1",
|
||||
|
||||
// The tertiary level
|
||||
"tertiary": "level3",
|
||||
},
|
||||
ms: {
|
||||
// UK System of measurement: feet, pints, etc.; pints are 20oz
|
||||
"imperial": "uksystem",
|
||||
},
|
||||
rg: {
|
||||
"cn11": "cnbj",
|
||||
"cn12": "cntj",
|
||||
"cn13": "cnhe",
|
||||
"cn14": "cnsx",
|
||||
"cn15": "cnmn",
|
||||
"cn21": "cnln",
|
||||
"cn22": "cnjl",
|
||||
"cn23": "cnhl",
|
||||
"cn31": "cnsh",
|
||||
"cn32": "cnjs",
|
||||
"cn33": "cnzj",
|
||||
"cn34": "cnah",
|
||||
"cn35": "cnfj",
|
||||
"cn36": "cnjx",
|
||||
"cn37": "cnsd",
|
||||
"cn41": "cnha",
|
||||
"cn42": "cnhb",
|
||||
"cn43": "cnhn",
|
||||
"cn44": "cngd",
|
||||
"cn45": "cngx",
|
||||
"cn46": "cnhi",
|
||||
"cn50": "cncq",
|
||||
"cn51": "cnsc",
|
||||
"cn52": "cngz",
|
||||
"cn53": "cnyn",
|
||||
"cn54": "cnxz",
|
||||
"cn61": "cnsn",
|
||||
"cn62": "cngs",
|
||||
"cn63": "cnqh",
|
||||
"cn64": "cnnx",
|
||||
"cn65": "cnxj",
|
||||
"cz10a": "cz110",
|
||||
"cz10b": "cz111",
|
||||
"cz10c": "cz112",
|
||||
"cz10d": "cz113",
|
||||
"cz10e": "cz114",
|
||||
"cz10f": "cz115",
|
||||
"cz611": "cz663",
|
||||
"cz612": "cz632",
|
||||
"cz613": "cz633",
|
||||
"cz614": "cz634",
|
||||
"cz615": "cz635",
|
||||
"cz621": "cz641",
|
||||
"cz622": "cz642",
|
||||
"cz623": "cz643",
|
||||
"cz624": "cz644",
|
||||
"cz626": "cz646",
|
||||
"cz627": "cz647",
|
||||
"czjc": "cz31",
|
||||
"czjm": "cz64",
|
||||
"czka": "cz41",
|
||||
"czkr": "cz52",
|
||||
"czli": "cz51",
|
||||
"czmo": "cz80",
|
||||
"czol": "cz71",
|
||||
"czpa": "cz53",
|
||||
"czpl": "cz32",
|
||||
"czpr": "cz10",
|
||||
"czst": "cz20",
|
||||
"czus": "cz42",
|
||||
"czvy": "cz63",
|
||||
"czzl": "cz72",
|
||||
"fra": "frges",
|
||||
"frb": "frnaq",
|
||||
"frc": "frara",
|
||||
"frd": "frbfc",
|
||||
"fre": "frbre",
|
||||
"frf": "frcvl",
|
||||
"frg": "frges",
|
||||
"frh": "frcor",
|
||||
"fri": "frbfc",
|
||||
"frj": "fridf",
|
||||
"frk": "frocc",
|
||||
"frl": "frnaq",
|
||||
"frm": "frges",
|
||||
"frn": "frocc",
|
||||
"fro": "frhdf",
|
||||
"frp": "frnor",
|
||||
"frq": "frnor",
|
||||
"frr": "frpdl",
|
||||
"frs": "frhdf",
|
||||
"frt": "frnaq",
|
||||
"fru": "frpac",
|
||||
"frv": "frara",
|
||||
"laxn": "laxs",
|
||||
"lud": "lucl",
|
||||
"lug": "luec",
|
||||
"lul": "luca",
|
||||
"mrnkc": "mr13",
|
||||
"nzn": "nzauk",
|
||||
"nzs": "nzcan",
|
||||
"omba": "ombj",
|
||||
"omsh": "omsj",
|
||||
"plds": "pl02",
|
||||
"plkp": "pl04",
|
||||
"pllb": "pl08",
|
||||
"plld": "pl10",
|
||||
"pllu": "pl06",
|
||||
"plma": "pl12",
|
||||
"plmz": "pl14",
|
||||
"plop": "pl16",
|
||||
"plpd": "pl20",
|
||||
"plpk": "pl18",
|
||||
"plpm": "pl22",
|
||||
"plsk": "pl26",
|
||||
"plsl": "pl24",
|
||||
"plwn": "pl28",
|
||||
"plwp": "pl30",
|
||||
"plzp": "pl32",
|
||||
"tteto": "tttob",
|
||||
"ttrcm": "ttmrc",
|
||||
"ttwto": "tttob",
|
||||
"twkhq": "twkhh",
|
||||
"twtnq": "twtnn",
|
||||
"twtpq": "twnwt",
|
||||
"twtxq": "twtxg",
|
||||
},
|
||||
sd: {
|
||||
"cn11": "cnbj",
|
||||
"cn12": "cntj",
|
||||
"cn13": "cnhe",
|
||||
"cn14": "cnsx",
|
||||
"cn15": "cnmn",
|
||||
"cn21": "cnln",
|
||||
"cn22": "cnjl",
|
||||
"cn23": "cnhl",
|
||||
"cn31": "cnsh",
|
||||
"cn32": "cnjs",
|
||||
"cn33": "cnzj",
|
||||
"cn34": "cnah",
|
||||
"cn35": "cnfj",
|
||||
"cn36": "cnjx",
|
||||
"cn37": "cnsd",
|
||||
"cn41": "cnha",
|
||||
"cn42": "cnhb",
|
||||
"cn43": "cnhn",
|
||||
"cn44": "cngd",
|
||||
"cn45": "cngx",
|
||||
"cn46": "cnhi",
|
||||
"cn50": "cncq",
|
||||
"cn51": "cnsc",
|
||||
"cn52": "cngz",
|
||||
"cn53": "cnyn",
|
||||
"cn54": "cnxz",
|
||||
"cn61": "cnsn",
|
||||
"cn62": "cngs",
|
||||
"cn63": "cnqh",
|
||||
"cn64": "cnnx",
|
||||
"cn65": "cnxj",
|
||||
"cz10a": "cz110",
|
||||
"cz10b": "cz111",
|
||||
"cz10c": "cz112",
|
||||
"cz10d": "cz113",
|
||||
"cz10e": "cz114",
|
||||
"cz10f": "cz115",
|
||||
"cz611": "cz663",
|
||||
"cz612": "cz632",
|
||||
"cz613": "cz633",
|
||||
"cz614": "cz634",
|
||||
"cz615": "cz635",
|
||||
"cz621": "cz641",
|
||||
"cz622": "cz642",
|
||||
"cz623": "cz643",
|
||||
"cz624": "cz644",
|
||||
"cz626": "cz646",
|
||||
"cz627": "cz647",
|
||||
"czjc": "cz31",
|
||||
"czjm": "cz64",
|
||||
"czka": "cz41",
|
||||
"czkr": "cz52",
|
||||
"czli": "cz51",
|
||||
"czmo": "cz80",
|
||||
"czol": "cz71",
|
||||
"czpa": "cz53",
|
||||
"czpl": "cz32",
|
||||
"czpr": "cz10",
|
||||
"czst": "cz20",
|
||||
"czus": "cz42",
|
||||
"czvy": "cz63",
|
||||
"czzl": "cz72",
|
||||
"fra": "frges",
|
||||
"frb": "frnaq",
|
||||
"frc": "frara",
|
||||
"frd": "frbfc",
|
||||
"fre": "frbre",
|
||||
"frf": "frcvl",
|
||||
"frg": "frges",
|
||||
"frh": "frcor",
|
||||
"fri": "frbfc",
|
||||
"frj": "fridf",
|
||||
"frk": "frocc",
|
||||
"frl": "frnaq",
|
||||
"frm": "frges",
|
||||
"frn": "frocc",
|
||||
"fro": "frhdf",
|
||||
"frp": "frnor",
|
||||
"frq": "frnor",
|
||||
"frr": "frpdl",
|
||||
"frs": "frhdf",
|
||||
"frt": "frnaq",
|
||||
"fru": "frpac",
|
||||
"frv": "frara",
|
||||
"laxn": "laxs",
|
||||
"lud": "lucl",
|
||||
"lug": "luec",
|
||||
"lul": "luca",
|
||||
"mrnkc": "mr13",
|
||||
"nzn": "nzauk",
|
||||
"nzs": "nzcan",
|
||||
"omba": "ombj",
|
||||
"omsh": "omsj",
|
||||
"plds": "pl02",
|
||||
"plkp": "pl04",
|
||||
"pllb": "pl08",
|
||||
"plld": "pl10",
|
||||
"pllu": "pl06",
|
||||
"plma": "pl12",
|
||||
"plmz": "pl14",
|
||||
"plop": "pl16",
|
||||
"plpd": "pl20",
|
||||
"plpk": "pl18",
|
||||
"plpm": "pl22",
|
||||
"plsk": "pl26",
|
||||
"plsl": "pl24",
|
||||
"plwn": "pl28",
|
||||
"plwp": "pl30",
|
||||
"plzp": "pl32",
|
||||
"tteto": "tttob",
|
||||
"ttrcm": "ttmrc",
|
||||
"ttwto": "tttob",
|
||||
"twkhq": "twkhh",
|
||||
"twtnq": "twtnn",
|
||||
"twtpq": "twnwt",
|
||||
"twtxq": "twtxg",
|
||||
},
|
||||
tz: {
|
||||
// Amundsen-Scott Station, South Pole
|
||||
"aqams": "nzakl",
|
||||
|
||||
// Chongqing, China
|
||||
"cnckg": "cnsha",
|
||||
|
||||
// Harbin, China
|
||||
"cnhrb": "cnsha",
|
||||
|
||||
// Kashgar, China
|
||||
"cnkhg": "cnurc",
|
||||
|
||||
// Havana, Cuba
|
||||
"cuba": "cuhav",
|
||||
|
||||
// Cairo, Egypt
|
||||
"egypt": "egcai",
|
||||
|
||||
// Dublin, Ireland
|
||||
"eire": "iedub",
|
||||
|
||||
// 5 hours behind UTC
|
||||
"est": "utcw05",
|
||||
|
||||
// Greenwich Mean Time
|
||||
"gmt0": "gmt",
|
||||
|
||||
// Hong Kong SAR China
|
||||
"hongkong": "hkhkg",
|
||||
|
||||
// 10 hours behind UTC
|
||||
"hst": "utcw10",
|
||||
|
||||
// Reykjavik, Iceland
|
||||
"iceland": "isrey",
|
||||
|
||||
// Tehran, Iran
|
||||
"iran": "irthr",
|
||||
|
||||
// Jerusalem
|
||||
"israel": "jeruslm",
|
||||
|
||||
// Jamaica
|
||||
"jamaica": "jmkin",
|
||||
|
||||
// Tokyo, Japan
|
||||
"japan": "jptyo",
|
||||
|
||||
// Tripoli, Libya
|
||||
"libya": "lytip",
|
||||
|
||||
// 7 hours behind UTC
|
||||
"mst": "utcw07",
|
||||
|
||||
// Denver, United States
|
||||
"navajo": "usden",
|
||||
|
||||
// Warsaw, Poland
|
||||
"poland": "plwaw",
|
||||
|
||||
// Lisbon, Portugal
|
||||
"portugal": "ptlis",
|
||||
|
||||
// Shanghai, China
|
||||
"prc": "cnsha",
|
||||
|
||||
// Taipei, Taiwan
|
||||
"roc": "twtpe",
|
||||
|
||||
// Seoul, South Korea
|
||||
"rok": "krsel",
|
||||
|
||||
// Istanbul, Turkey
|
||||
"turkey": "trist",
|
||||
|
||||
// UTC (Coordinated Universal Time)
|
||||
"uct": "utc",
|
||||
|
||||
// Shiprock (Navajo), United States
|
||||
"usnavajo": "usden",
|
||||
|
||||
// UTC (Coordinated Universal Time)
|
||||
"zulu": "utc",
|
||||
},
|
||||
};
|
@ -9,6 +9,7 @@
|
||||
make_intl_data.py langtags [ldmlSupplemental.dtd supplementalMetadata.xml likelySubtags.xml]
|
||||
make_intl_data.py tzdata
|
||||
make_intl_data.py currency
|
||||
make_intl_data.py unicode-ext
|
||||
|
||||
|
||||
Target "langtags":
|
||||
@ -26,6 +27,10 @@
|
||||
|
||||
Target "currency":
|
||||
Generates the mapping from currency codes to decimal digits used for them.
|
||||
|
||||
Target "unicode-ext":
|
||||
Generates the mapping from deprecated BCP 47 Unicode extension values to
|
||||
their preferred values.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
@ -42,6 +47,7 @@ from contextlib import closing
|
||||
from functools import partial, total_ordering
|
||||
from itertools import chain, groupby, tee
|
||||
from operator import attrgetter, itemgetter
|
||||
from zipfile import ZipFile
|
||||
|
||||
if sys.version_info.major == 2:
|
||||
from itertools import ifilter as filter, ifilterfalse as filterfalse, imap as map
|
||||
@ -1603,6 +1609,224 @@ def updateCurrency(topsrcdir, args):
|
||||
updateFrom(currencyTmpFile.name)
|
||||
|
||||
|
||||
def writeUnicodeExtensionsFile(version, url, mapping, out):
|
||||
with io.open(out, mode="w", encoding="utf-8", newline="") as f:
|
||||
println = partial(print, file=f)
|
||||
|
||||
println(generatedFileWarning)
|
||||
println(u"// Version: CLDR-{}".format(version))
|
||||
println(u"// URL: {}".format(url))
|
||||
|
||||
println(u"""
|
||||
/**
|
||||
* Mapping from deprecated BCP 47 Unicode extension types to their preferred
|
||||
* values.
|
||||
*
|
||||
* Spec: https://www.unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files
|
||||
*/""")
|
||||
println(u"var deprecatedUnicodeExtensionTypes = {")
|
||||
for ext_name in sorted(mapping):
|
||||
println(u" {}: {{".format(ext_name))
|
||||
is_first = True
|
||||
for type in sorted(mapping[ext_name]):
|
||||
mapped = mapping[ext_name][type]
|
||||
has_description = mapped["description"] is not None
|
||||
|
||||
if not is_first and has_description:
|
||||
println(u"")
|
||||
is_first = False
|
||||
|
||||
if has_description:
|
||||
println(u" // {}".format(mapped["description"]))
|
||||
println(u" \"{}\": \"{}\",".format(type, mapped["preferred"]))
|
||||
println(u" },")
|
||||
println(u"};")
|
||||
|
||||
|
||||
def updateUnicodeExtensions(args):
|
||||
""" Update the UnicodeExtensionsGenerated.js file. """
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
version = args.version
|
||||
url = args.url
|
||||
out = args.out
|
||||
filename = args.file
|
||||
|
||||
url = url.replace("<VERSION>", version)
|
||||
|
||||
print("Arguments:")
|
||||
print("\tCLDR version: %s" % version)
|
||||
print("\tDownload url: %s" % url)
|
||||
if filename is not None:
|
||||
print("\tLocal CLDR core.zip file: %s" % filename)
|
||||
print("\tOutput file: %s" % out)
|
||||
print("")
|
||||
|
||||
def updateFrom(data):
|
||||
# Match all xml-files in the BCP 47 directory.
|
||||
bcpFileRE = re.compile(r"^common/bcp47/.+\.xml$")
|
||||
|
||||
# https://www.unicode.org/reports/tr35/#Unicode_locale_identifier
|
||||
#
|
||||
# type = alphanum{3,8} (sep alphanum{3,8})* ;
|
||||
typeRE = re.compile(r"^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$")
|
||||
|
||||
# Mapping from Unicode extension types to dict of deprecated to
|
||||
# preferred values.
|
||||
mapping = {}
|
||||
|
||||
with ZipFile(data) as zip_file:
|
||||
for name in zip_file.namelist():
|
||||
if not bcpFileRE.match(name):
|
||||
continue
|
||||
|
||||
tree = ET.parse(zip_file.open(name))
|
||||
for keyword in tree.iterfind(".//keyword/key"):
|
||||
# Skip over keywords whose extension is not "u".
|
||||
if keyword.get("extension", "u") != "u":
|
||||
continue
|
||||
|
||||
extension_name = keyword.get("name")
|
||||
|
||||
for type in keyword.iterfind("type"):
|
||||
# <https://unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files>:
|
||||
#
|
||||
# The key or type name used by Unicode locale extension with 'u' extension
|
||||
# syntax or the 't' extensions syntax. When alias below is absent, this
|
||||
# name can be also used with the old style "@key=type" syntax.
|
||||
name = type.get("name")
|
||||
|
||||
# Ignore the special name:
|
||||
# - <https://unicode.org/reports/tr35/#CODEPOINTS>
|
||||
# - <https://unicode.org/reports/tr35/#REORDER_CODE>
|
||||
# - <https://unicode.org/reports/tr35/#RG_KEY_VALUE>
|
||||
# - <https://unicode.org/reports/tr35/#SUBDIVISION_CODE>
|
||||
# - <https://unicode.org/reports/tr35/#PRIVATE_USE>
|
||||
if name in ("CODEPOINTS", "REORDER_CODE", "RG_KEY_VALUE",
|
||||
"SUBDIVISION_CODE", "PRIVATE_USE"):
|
||||
continue
|
||||
|
||||
# All other names should match the 'type' production.
|
||||
assert typeRE.match(name) is not None, (
|
||||
"{} matches the 'type' production".format(name))
|
||||
|
||||
# <https://unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files>:
|
||||
#
|
||||
# The preferred value of the deprecated key, type or attribute element.
|
||||
# When a key, type or attribute element is deprecated, this attribute is
|
||||
# used for specifying a new canonical form if available.
|
||||
preferred = type.get("preferred")
|
||||
|
||||
# <https://unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files>:
|
||||
#
|
||||
# The BCP 47 form is the canonical form, and recommended. Other aliases are
|
||||
# included only for backwards compatibility.
|
||||
alias = type.get("alias")
|
||||
|
||||
# <https://unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files>:
|
||||
#
|
||||
# The description of the key, type or attribute element.
|
||||
description = type.get("description")
|
||||
|
||||
# <https://unicode.org/reports/tr35/#Canonical_Unicode_Locale_Identifiers>
|
||||
#
|
||||
# Use the bcp47 data to replace keys, types, tfields, and tvalues by their
|
||||
# canonical forms. See Section 3.6.4 U Extension Data Files) and Section
|
||||
# 3.7.1 T Extension Data Files. The aliases are in the alias attribute
|
||||
# value, while the canonical is in the name attribute value.
|
||||
|
||||
# 'preferred' contains the new preferred name, 'alias' the compatibility
|
||||
# name, but then there's this entry where 'preferred' and 'alias' are the
|
||||
# same. So which one to choose? Assume 'preferred' is the actual canonical
|
||||
# name.
|
||||
#
|
||||
# <type name="islamicc"
|
||||
# description="Civil (algorithmic) Arabic calendar"
|
||||
# deprecated="true"
|
||||
# preferred="islamic-civil"
|
||||
# alias="islamic-civil"/>
|
||||
|
||||
if preferred is not None:
|
||||
assert typeRE.match(preferred), preferred
|
||||
mapping.setdefault(extension_name, {})[name] = {
|
||||
"preferred": preferred,
|
||||
"description": description,
|
||||
}
|
||||
|
||||
if alias is not None:
|
||||
for alias_name in alias.lower().split(" "):
|
||||
# Ignore alias entries which don't match the 'type' production.
|
||||
if typeRE.match(alias_name) is None:
|
||||
continue
|
||||
|
||||
# See comment above when 'alias' and 'preferred' are both present.
|
||||
if (preferred is not None and
|
||||
name in mapping[extension_name]):
|
||||
continue
|
||||
|
||||
# Skip over entries where 'name' and 'alias' are equal.
|
||||
#
|
||||
# <type name="pst8pdt"
|
||||
# description="POSIX style time zone for US Pacific Time"
|
||||
# alias="PST8PDT"
|
||||
# since="1.8"/>
|
||||
if name == alias_name:
|
||||
continue
|
||||
|
||||
mapping.setdefault(extension_name, {})[alias_name] = {
|
||||
"preferred": name,
|
||||
"description": description,
|
||||
}
|
||||
|
||||
# Find subdivision and region replacements.
|
||||
#
|
||||
# <https://www.unicode.org/reports/tr35/#Canonical_Unicode_Locale_Identifiers>
|
||||
#
|
||||
# Replace aliases in special key values:
|
||||
# - If there is an 'sd' or 'rg' key, replace any subdivision alias
|
||||
# in its value in the same way, using subdivisionAlias data.
|
||||
tree = ET.parse(zip_file.open("common/supplemental/supplementalMetadata.xml"))
|
||||
for alias in tree.iterfind(".//subdivisionAlias"):
|
||||
type = alias.get("type")
|
||||
assert typeRE.match(type) is not None, (
|
||||
"{} matches the 'type' production".format(type))
|
||||
|
||||
# Take the first replacement when multiple ones are present.
|
||||
replacement = alias.get("replacement").split(" ")[0].lower()
|
||||
|
||||
# Skip over invalid replacements.
|
||||
#
|
||||
# <subdivisionAlias type="fi01" replacement="AX" reason="overlong"/>
|
||||
#
|
||||
# It's not entirely clear to me if CLDR actually wants to use
|
||||
# "axzzzz" as the replacement for this case.
|
||||
if typeRE.match(replacement) is None:
|
||||
continue
|
||||
|
||||
# 'subdivisionAlias' applies to 'rg' and 'sd' keys.
|
||||
mapping.setdefault("rg", {})[type] = {
|
||||
"preferred": replacement,
|
||||
"description": None,
|
||||
}
|
||||
mapping.setdefault("sd", {})[type] = {
|
||||
"preferred": replacement,
|
||||
"description": None,
|
||||
}
|
||||
|
||||
writeUnicodeExtensionsFile(version, url, mapping, out)
|
||||
|
||||
if filename is not None:
|
||||
print("Always make sure you have the newest CLDR core.zip!")
|
||||
with open(filename, "rb") as cldr_file:
|
||||
updateFrom(cldr_file)
|
||||
else:
|
||||
print("Downloading CLDR core.zip...")
|
||||
with closing(urlopen(url)) as cldr_file:
|
||||
cldr_data = io.BytesIO(cldr_file.read())
|
||||
updateFrom(cldr_data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
@ -1673,5 +1897,23 @@ if __name__ == "__main__":
|
||||
help="Local currency code list file, if omitted uses <URL>")
|
||||
parser_currency.set_defaults(func=partial(updateCurrency, topsrcdir))
|
||||
|
||||
parser_unicode_ext = subparsers.add_parser("unicode-ext", help="Update Unicode extensions")
|
||||
parser_unicode_ext.add_argument("--version",
|
||||
metavar="VERSION",
|
||||
required=True,
|
||||
help="CLDR version number")
|
||||
parser_unicode_ext.add_argument("--url",
|
||||
metavar="URL",
|
||||
default="https://unicode.org/Public/cldr/<VERSION>/core.zip",
|
||||
type=EnsureHttps,
|
||||
help="Download url CLDR data (default: %(default)s)")
|
||||
parser_unicode_ext.add_argument("--out",
|
||||
default="UnicodeExtensionsGenerated.js",
|
||||
help="Output file (default: %(default)s)")
|
||||
parser_unicode_ext.add_argument("file",
|
||||
nargs="?",
|
||||
help="Local cldr-core.zip file, if omitted uses <URL>")
|
||||
parser_unicode_ext.set_defaults(func=updateUnicodeExtensions)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
@ -31,6 +31,7 @@
|
||||
\
|
||||
_(IntlGuardToCollator) \
|
||||
_(IntlGuardToDateTimeFormat) \
|
||||
_(IntlGuardToLocale) \
|
||||
_(IntlGuardToNumberFormat) \
|
||||
_(IntlGuardToPluralRules) \
|
||||
_(IntlGuardToRelativeTimeFormat) \
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "builtin/AtomicsObject.h"
|
||||
#include "builtin/intl/Collator.h"
|
||||
#include "builtin/intl/DateTimeFormat.h"
|
||||
#include "builtin/intl/Locale.h"
|
||||
#include "builtin/intl/NumberFormat.h"
|
||||
#include "builtin/intl/PluralRules.h"
|
||||
#include "builtin/intl/RelativeTimeFormat.h"
|
||||
@ -108,6 +109,7 @@ static bool CanInlineCrossRealm(InlinableNative native) {
|
||||
|
||||
case InlinableNative::IntlGuardToCollator:
|
||||
case InlinableNative::IntlGuardToDateTimeFormat:
|
||||
case InlinableNative::IntlGuardToLocale:
|
||||
case InlinableNative::IntlGuardToNumberFormat:
|
||||
case InlinableNative::IntlGuardToPluralRules:
|
||||
case InlinableNative::IntlGuardToRelativeTimeFormat:
|
||||
@ -314,6 +316,8 @@ IonBuilder::InliningResult IonBuilder::inlineNativeCall(CallInfo& callInfo,
|
||||
return inlineGuardToClass(callInfo, &CollatorObject::class_);
|
||||
case InlinableNative::IntlGuardToDateTimeFormat:
|
||||
return inlineGuardToClass(callInfo, &DateTimeFormatObject::class_);
|
||||
case InlinableNative::IntlGuardToLocale:
|
||||
return inlineGuardToClass(callInfo, &LocaleObject::class_);
|
||||
case InlinableNative::IntlGuardToNumberFormat:
|
||||
return inlineGuardToClass(callInfo, &NumberFormatObject::class_);
|
||||
case InlinableNative::IntlGuardToPluralRules:
|
||||
|
@ -2630,6 +2630,10 @@ extern JS_FRIEND_API JSObject* ToWindowIfWindowProxy(JSObject* obj);
|
||||
extern bool AddMozDateTimeFormatConstructor(JSContext* cx,
|
||||
JS::Handle<JSObject*> intl);
|
||||
|
||||
// Create and add the Intl.Locale constructor function to the provided object.
|
||||
// This function throws if called more than once per realm/global object.
|
||||
extern bool AddLocaleConstructor(JSContext* cx, JS::Handle<JSObject*> intl);
|
||||
|
||||
class MOZ_STACK_CLASS JS_FRIEND_API AutoAssertNoContentJS {
|
||||
public:
|
||||
explicit AutoAssertNoContentJS(JSContext* cx);
|
||||
|
@ -212,6 +212,7 @@ UNIFIED_SOURCES += [
|
||||
'builtin/intl/CommonFunctions.cpp',
|
||||
'builtin/intl/DateTimeFormat.cpp',
|
||||
'builtin/intl/IntlObject.cpp',
|
||||
'builtin/intl/Locale.cpp',
|
||||
'builtin/intl/NumberFormat.cpp',
|
||||
'builtin/intl/PluralRules.cpp',
|
||||
'builtin/intl/RelativeTimeFormat.cpp',
|
||||
@ -435,9 +436,11 @@ selfhosted.inputs = [
|
||||
'builtin/intl/DateTimeFormat.js',
|
||||
'builtin/intl/IntlObject.js',
|
||||
'builtin/intl/LangTagMappingsGenerated.js',
|
||||
'builtin/intl/Locale.js',
|
||||
'builtin/intl/NumberFormat.js',
|
||||
'builtin/intl/PluralRules.js',
|
||||
'builtin/intl/RelativeTimeFormat.js',
|
||||
'builtin/intl/UnicodeExtensionsGenerated.js',
|
||||
'builtin/Iterator.js',
|
||||
'builtin/Map.js',
|
||||
'builtin/Module.js',
|
||||
|
@ -1260,6 +1260,10 @@ static bool AddIntlExtras(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!js::AddLocaleConstructor(cx, intl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
@ -222,6 +222,7 @@
|
||||
MACRO(InitializeCollator, InitializeCollator, "InitializeCollator") \
|
||||
MACRO(InitializeDateTimeFormat, InitializeDateTimeFormat, \
|
||||
"InitializeDateTimeFormat") \
|
||||
MACRO(InitializeLocale, InitializeLocale, "InitializeLocale") \
|
||||
MACRO(InitializeNumberFormat, InitializeNumberFormat, \
|
||||
"InitializeNumberFormat") \
|
||||
MACRO(InitializePluralRules, InitializePluralRules, "InitializePluralRules") \
|
||||
@ -262,6 +263,7 @@
|
||||
MACRO(lineNumber, lineNumber, "lineNumber") \
|
||||
MACRO(literal, literal, "literal") \
|
||||
MACRO(loc, loc, "loc") \
|
||||
MACRO(Locale, Locale, "Locale") \
|
||||
MACRO(locale, locale, "locale") \
|
||||
MACRO(lookupGetter, lookupGetter, "__lookupGetter__") \
|
||||
MACRO(lookupSetter, lookupSetter, "__lookupSetter__") \
|
||||
|
@ -95,6 +95,7 @@ class GlobalObject : public NativeObject {
|
||||
DATE_TIME_FORMAT_PROTO,
|
||||
PLURAL_RULES_PROTO,
|
||||
RELATIVE_TIME_FORMAT_PROTO,
|
||||
LOCALE_PROTO,
|
||||
MODULE_PROTO,
|
||||
IMPORT_ENTRY_PROTO,
|
||||
EXPORT_ENTRY_PROTO,
|
||||
@ -538,6 +539,11 @@ class GlobalObject : public NativeObject {
|
||||
initIntlObject);
|
||||
}
|
||||
|
||||
static JSObject* getOrCreateLocalePrototype(JSContext* cx,
|
||||
Handle<GlobalObject*> global) {
|
||||
return getOrCreateObject(cx, global, LOCALE_PROTO, initIntlObject);
|
||||
}
|
||||
|
||||
static bool ensureModulePrototypesCreated(JSContext* cx,
|
||||
Handle<GlobalObject*> global);
|
||||
|
||||
@ -840,6 +846,9 @@ class GlobalObject : public NativeObject {
|
||||
// Implemented in builtin/intl/IntlObject.cpp.
|
||||
static bool initIntlObject(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
||||
// Implemented in builtin/intl/Locale.cpp.
|
||||
static bool addLocaleConstructor(JSContext* cx, HandleObject intl);
|
||||
|
||||
// Implemented in builtin/ModuleObject.cpp
|
||||
static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
|
||||
static bool initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "builtin/intl/Collator.h"
|
||||
#include "builtin/intl/DateTimeFormat.h"
|
||||
#include "builtin/intl/IntlObject.h"
|
||||
#include "builtin/intl/Locale.h"
|
||||
#include "builtin/intl/NumberFormat.h"
|
||||
#include "builtin/intl/PluralRules.h"
|
||||
#include "builtin/intl/RelativeTimeFormat.h"
|
||||
@ -2508,6 +2509,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
JS_INLINABLE_FN("GuardToDateTimeFormat",
|
||||
intrinsic_GuardToBuiltin<DateTimeFormatObject>, 1, 0,
|
||||
IntlGuardToDateTimeFormat),
|
||||
JS_INLINABLE_FN("GuardToLocale", intrinsic_GuardToBuiltin<LocaleObject>, 1,
|
||||
0, IntlGuardToLocale),
|
||||
JS_INLINABLE_FN("GuardToNumberFormat",
|
||||
intrinsic_GuardToBuiltin<NumberFormatObject>, 1, 0,
|
||||
IntlGuardToNumberFormat),
|
||||
@ -2520,6 +2523,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
|
||||
JS_FN("IsWrappedDateTimeFormat",
|
||||
intrinsic_IsWrappedInstanceOfBuiltin<DateTimeFormatObject>, 1, 0),
|
||||
JS_FN("IsWrappedLocale", intrinsic_IsWrappedInstanceOfBuiltin<LocaleObject>,
|
||||
1, 0),
|
||||
JS_FN("IsWrappedNumberFormat",
|
||||
intrinsic_IsWrappedInstanceOfBuiltin<NumberFormatObject>, 1, 0),
|
||||
|
||||
@ -2527,6 +2532,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
CallNonGenericSelfhostedMethod<Is<CollatorObject>>, 2, 0),
|
||||
JS_FN("CallDateTimeFormatMethodIfWrapped",
|
||||
CallNonGenericSelfhostedMethod<Is<DateTimeFormatObject>>, 2, 0),
|
||||
JS_FN("CallLocaleMethodIfWrapped",
|
||||
CallNonGenericSelfhostedMethod<Is<LocaleObject>>, 2, 0),
|
||||
JS_FN("CallNumberFormatMethodIfWrapped",
|
||||
CallNonGenericSelfhostedMethod<Is<NumberFormatObject>>, 2, 0),
|
||||
JS_FN("CallPluralRulesMethodIfWrapped",
|
||||
|
Loading…
Reference in New Issue
Block a user