Issue #2046 - Move a bunch of functions in builtin/intl/CommonFunctions.js into more-specific files, where those functions are only used in a single more-specific file

This commit is contained in:
Martok 2023-02-17 00:21:40 +01:00 committed by roytam1
commit 87eaaee953
3 changed files with 141 additions and 152 deletions

View file

@ -4,29 +4,6 @@
/* Portions Copyright Norbert Lindenberg 2011-2012. */
/********** Locales, Time Zones, and Currencies **********/
/**
* Convert s to upper case, but limited to characters a-z.
*
* Spec: ECMAScript Internationalization API Specification, 6.1.
*/
function toASCIIUpperCase(s) {
assert(typeof s === "string", "toASCIIUpperCase");
// String.prototype.toUpperCase may map non-ASCII characters into ASCII,
// so go character by character (actually code unit by code unit, but
// since we only care about ASCII characters here, that's OK).
var result = "";
for (var i = 0; i < s.length; i++) {
var c = callFunction(std_String_charCodeAt, s, i);
result += (0x61 <= c && c <= 0x7A)
? callFunction(std_String_fromCharCode, null, c & ~0x20)
: s[i];
}
return result;
}
/**
* Holder object for encapsulating regexp instances.
@ -314,6 +291,24 @@ function IsStructurallyValidLanguageTag(locale) {
!regexp_test_no_statics(duplicateSingletonRE, locale);
}
/**
* Joins the array elements in the given range with the supplied separator.
*/
function ArrayJoinRange(array, separator, from, to = array.length) {
assert(typeof separator === "string", "|separator| is a string value");
assert(typeof from === "number", "|from| is a number value");
assert(typeof to === "number", "|to| is a number value");
assert(0 <= from && from <= to && to <= array.length, "|from| and |to| form a valid range");
if (from === to)
return "";
var result = array[from];
for (var i = from + 1; i < to; i++) {
result += separator + array[i];
}
return result;
}
/**
* Canonicalizes the given structurally valid BCP 47 language tag, including
@ -443,25 +438,6 @@ function CanonicalizeLanguageTag(locale) {
return canonical;
}
/**
* Joins the array elements in the given range with the supplied separator.
*/
function ArrayJoinRange(array, separator, from, to = array.length) {
assert(typeof separator === "string", "|separator| is a string value");
assert(typeof from === "number", "|from| is a number value");
assert(typeof to === "number", "|to| is a number value");
assert(0 <= from && from <= to && to <= array.length, "|from| and |to| form a valid range");
if (from === to)
return "";
var result = array[from];
for (var i = from + 1; i < to; i++) {
result += separator + array[i];
}
return result;
}
function localeContainsNoUnicodeExtensions(locale) {
// No "-u-", no possible Unicode extension.
if (callFunction(std_String_indexOf, locale, "-u-") === -1)
@ -601,113 +577,6 @@ function DefaultLocale() {
}
/**
* Verifies that the given string is a well-formed ISO 4217 currency code.
*
* Spec: ECMAScript Internationalization API Specification, 6.3.1.
*/
function getIsWellFormedCurrencyCodeRE() {
return internalIntlRegExps.isWellFormedCurrencyCodeRE ||
(internalIntlRegExps.isWellFormedCurrencyCodeRE = RegExpCreate("[^A-Z]"));
}
function IsWellFormedCurrencyCode(currency) {
var c = ToString(currency);
var normalized = toASCIIUpperCase(c);
if (normalized.length !== 3)
return false;
return !regexp_test_no_statics(getIsWellFormedCurrencyCodeRE(), normalized);
}
var timeZoneCache = {
icuDefaultTimeZone: undefined,
defaultTimeZone: undefined,
};
/**
* 6.4.2 CanonicalizeTimeZoneName ( timeZone )
*
* Canonicalizes the given IANA time zone name.
*
* ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3
*/
function CanonicalizeTimeZoneName(timeZone) {
assert(typeof timeZone === "string", "CanonicalizeTimeZoneName");
// Step 1. (Not applicable, the input is already a valid IANA time zone.)
assert(timeZone !== "Etc/Unknown", "Invalid time zone");
assert(timeZone === intl_IsValidTimeZoneName(timeZone), "Time zone name not normalized");
// Step 2.
var ianaTimeZone = intl_canonicalizeTimeZone(timeZone);
assert(ianaTimeZone !== "Etc/Unknown", "Invalid canonical time zone");
assert(ianaTimeZone === intl_IsValidTimeZoneName(ianaTimeZone), "Unsupported canonical time zone");
// Step 3.
if (ianaTimeZone === "Etc/UTC" || ianaTimeZone === "Etc/GMT") {
// ICU/CLDR canonicalizes Etc/UCT to Etc/GMT, but following IANA and
// ECMA-402 to the letter means Etc/UCT is a separate time zone.
if (timeZone === "Etc/UCT" || timeZone === "UCT")
ianaTimeZone = "Etc/UCT";
else
ianaTimeZone = "UTC";
}
// Step 4.
return ianaTimeZone;
}
/**
* 6.4.3 DefaultTimeZone ()
*
* Returns the IANA time zone name for the host environment's current time zone.
*
* ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3
*/
function DefaultTimeZone() {
const icuDefaultTimeZone = intl_defaultTimeZone();
if (timeZoneCache.icuDefaultTimeZone === icuDefaultTimeZone)
return timeZoneCache.defaultTimeZone;
// Verify that the current ICU time zone is a valid ECMA-402 time zone.
var timeZone = intl_IsValidTimeZoneName(icuDefaultTimeZone);
if (timeZone === null) {
// Before defaulting to "UTC", try to represent the default time zone
// using the Etc/GMT + offset format. This format only accepts full
// hour offsets.
const msPerHour = 60 * 60 * 1000;
var offset = intl_defaultTimeZoneOffset();
assert(offset === (offset | 0),
"milliseconds offset shouldn't be able to exceed int32_t range");
var offsetHours = offset / msPerHour, offsetHoursFraction = offset % msPerHour;
if (offsetHoursFraction === 0) {
// Etc/GMT + offset uses POSIX-style signs, i.e. a positive offset
// means a location west of GMT.
timeZone = "Etc/GMT" + (offsetHours < 0 ? "+" : "-") + std_Math_abs(offsetHours);
// Check if the fallback is valid.
timeZone = intl_IsValidTimeZoneName(timeZone);
}
// Fallback to "UTC" if everything else fails.
if (timeZone === null)
timeZone = "UTC";
}
// Canonicalize the ICU time zone, e.g. change Etc/UTC to UTC.
var defaultTimeZone = CanonicalizeTimeZoneName(timeZone);
timeZoneCache.defaultTimeZone = defaultTimeZone;
timeZoneCache.icuDefaultTimeZone = icuDefaultTimeZone;
return defaultTimeZone;
}
/********** Locale and Parameter Negotiation **********/
/**
* Add old-style language tags without script code for locales that in current
* usage would include a script subtag. Also add an entry for the last-ditch
@ -1180,9 +1049,6 @@ function GetNumberOption(options, property, minimum, maximum, fallback) {
}
/********** Property access for Intl objects **********/
/**
* Weak map used to track the initialize-as-Intl status (and, if an object has
* been so initialized, the Intl-specific internal properties) of all objects.

View file

@ -128,6 +128,91 @@ var dateTimeComponentValues = {
var dateTimeComponents = std_Object_getOwnPropertyNames(dateTimeComponentValues);
var timeZoneCache = {
icuDefaultTimeZone: undefined,
defaultTimeZone: undefined,
};
/**
* 6.4.2 CanonicalizeTimeZoneName ( timeZone )
*
* Canonicalizes the given IANA time zone name.
*
* ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3
*/
function CanonicalizeTimeZoneName(timeZone) {
assert(typeof timeZone === "string", "CanonicalizeTimeZoneName");
// Step 1. (Not applicable, the input is already a valid IANA time zone.)
assert(timeZone !== "Etc/Unknown", "Invalid time zone");
assert(timeZone === intl_IsValidTimeZoneName(timeZone), "Time zone name not normalized");
// Step 2.
var ianaTimeZone = intl_canonicalizeTimeZone(timeZone);
assert(ianaTimeZone !== "Etc/Unknown", "Invalid canonical time zone");
assert(ianaTimeZone === intl_IsValidTimeZoneName(ianaTimeZone), "Unsupported canonical time zone");
// Step 3.
if (ianaTimeZone === "Etc/UTC" || ianaTimeZone === "Etc/GMT") {
// ICU/CLDR canonicalizes Etc/UCT to Etc/GMT, but following IANA and
// ECMA-402 to the letter means Etc/UCT is a separate time zone.
if (timeZone === "Etc/UCT" || timeZone === "UCT")
ianaTimeZone = "Etc/UCT";
else
ianaTimeZone = "UTC";
}
// Step 4.
return ianaTimeZone;
}
/**
* 6.4.3 DefaultTimeZone ()
*
* Returns the IANA time zone name for the host environment's current time zone.
*
* ES2017 Intl draft rev 4a23f407336d382ed5e3471200c690c9b020b5f3
*/
function DefaultTimeZone() {
const icuDefaultTimeZone = intl_defaultTimeZone();
if (timeZoneCache.icuDefaultTimeZone === icuDefaultTimeZone)
return timeZoneCache.defaultTimeZone;
// Verify that the current ICU time zone is a valid ECMA-402 time zone.
var timeZone = intl_IsValidTimeZoneName(icuDefaultTimeZone);
if (timeZone === null) {
// Before defaulting to "UTC", try to represent the default time zone
// using the Etc/GMT + offset format. This format only accepts full
// hour offsets.
const msPerHour = 60 * 60 * 1000;
var offset = intl_defaultTimeZoneOffset();
assert(offset === (offset | 0),
"milliseconds offset shouldn't be able to exceed int32_t range");
var offsetHours = offset / msPerHour, offsetHoursFraction = offset % msPerHour;
if (offsetHoursFraction === 0) {
// Etc/GMT + offset uses POSIX-style signs, i.e. a positive offset
// means a location west of GMT.
timeZone = "Etc/GMT" + (offsetHours < 0 ? "+" : "-") + std_Math_abs(offsetHours);
// Check if the fallback is valid.
timeZone = intl_IsValidTimeZoneName(timeZone);
}
// Fallback to "UTC" if everything else fails.
if (timeZone === null)
timeZone = "UTC";
}
// Canonicalize the ICU time zone, e.g. change Etc/UTC to UTC.
var defaultTimeZone = CanonicalizeTimeZoneName(timeZone);
timeZoneCache.defaultTimeZone = defaultTimeZone;
timeZoneCache.icuDefaultTimeZone = icuDefaultTimeZone;
return defaultTimeZone;
}
/**
* Initializes an object as a DateTimeFormat.

View file

@ -149,6 +149,44 @@ function SetNumberFormatDigitOptions(lazyData, options, mnfdDefault) {
}
}
/**
* Convert s to upper case, but limited to characters a-z.
*
* Spec: ECMAScript Internationalization API Specification, 6.1.
*/
function toASCIIUpperCase(s) {
assert(typeof s === "string", "toASCIIUpperCase");
// String.prototype.toUpperCase may map non-ASCII characters into ASCII,
// so go character by character (actually code unit by code unit, but
// since we only care about ASCII characters here, that's OK).
var result = "";
for (var i = 0; i < s.length; i++) {
var c = callFunction(std_String_charCodeAt, s, i);
result += (0x61 <= c && c <= 0x7A)
? callFunction(std_String_fromCharCode, null, c & ~0x20)
: s[i];
}
return result;
}
/**
* Verifies that the given string is a well-formed ISO 4217 currency code.
*
* Spec: ECMAScript Internationalization API Specification, 6.3.1.
*/
function getIsWellFormedCurrencyCodeRE() {
return internalIntlRegExps.isWellFormedCurrencyCodeRE ||
(internalIntlRegExps.isWellFormedCurrencyCodeRE = RegExpCreate("[^A-Z]"));
}
function IsWellFormedCurrencyCode(currency) {
var c = ToString(currency);
var normalized = toASCIIUpperCase(c);
if (normalized.length !== 3)
return false;
return !regexp_test_no_statics(getIsWellFormedCurrencyCodeRE(), normalized);
}
/**
* Initializes an object as a NumberFormat.