summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/intl402/shell.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/test262/intl402/shell.js')
-rw-r--r--js/src/tests/test262/intl402/shell.js2717
1 files changed, 2717 insertions, 0 deletions
diff --git a/js/src/tests/test262/intl402/shell.js b/js/src/tests/test262/intl402/shell.js
new file mode 100644
index 0000000000..33526c6378
--- /dev/null
+++ b/js/src/tests/test262/intl402/shell.js
@@ -0,0 +1,2717 @@
+// GENERATED, DO NOT EDIT
+// file: testIntl.js
+// Copyright (C) 2011 2012 Norbert Lindenberg. All rights reserved.
+// Copyright (C) 2012 2013 Mozilla Corporation. All rights reserved.
+// Copyright (C) 2020 Apple Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ This file contains shared functions for the tests in the conformance test
+ suite for the ECMAScript Internationalization API.
+author: Norbert Lindenberg
+defines:
+ - testWithIntlConstructors
+ - taintDataProperty
+ - taintMethod
+ - taintProperties
+ - taintArray
+ - getLocaleSupportInfo
+ - getInvalidLanguageTags
+ - isCanonicalizedStructurallyValidLanguageTag
+ - getInvalidLocaleArguments
+ - testOption
+ - testForUnwantedRegExpChanges
+ - allCalendars
+ - allCollations
+ - allNumberingSystems
+ - isValidNumberingSystem
+ - numberingSystemDigits
+ - allSimpleSanctionedUnits
+ - testNumberFormat
+ - getDateTimeComponents
+ - getDateTimeComponentValues
+ - isCanonicalizedStructurallyValidTimeZoneName
+ - partitionDurationFormatPattern
+ - formatDurationFormatPattern
+---*/
+/**
+ */
+
+
+/**
+ * @description Calls the provided function for every service constructor in
+ * the Intl object.
+ * @param {Function} f the function to call for each service constructor in
+ * the Intl object.
+ * @param {Function} Constructor the constructor object to test with.
+ */
+function testWithIntlConstructors(f) {
+ var constructors = ["Collator", "NumberFormat", "DateTimeFormat"];
+
+ // Optionally supported Intl constructors.
+ // NB: Intl.Locale isn't an Intl service constructor!
+ // Intl.DisplayNames cannot be called without type in options.
+ ["PluralRules", "RelativeTimeFormat", "ListFormat"].forEach(function(constructor) {
+ if (typeof Intl[constructor] === "function") {
+ constructors[constructors.length] = constructor;
+ }
+ });
+
+ constructors.forEach(function (constructor) {
+ var Constructor = Intl[constructor];
+ try {
+ f(Constructor);
+ } catch (e) {
+ e.message += " (Testing with " + constructor + ".)";
+ throw e;
+ }
+ });
+}
+
+
+/**
+ * Taints a named data property of the given object by installing
+ * a setter that throws an exception.
+ * @param {object} obj the object whose data property to taint
+ * @param {string} property the property to taint
+ */
+function taintDataProperty(obj, property) {
+ Object.defineProperty(obj, property, {
+ set: function(value) {
+ throw new Test262Error("Client code can adversely affect behavior: setter for " + property + ".");
+ },
+ enumerable: false,
+ configurable: true
+ });
+}
+
+
+/**
+ * Taints a named method of the given object by replacing it with a function
+ * that throws an exception.
+ * @param {object} obj the object whose method to taint
+ * @param {string} property the name of the method to taint
+ */
+function taintMethod(obj, property) {
+ Object.defineProperty(obj, property, {
+ value: function() {
+ throw new Test262Error("Client code can adversely affect behavior: method " + property + ".");
+ },
+ writable: true,
+ enumerable: false,
+ configurable: true
+ });
+}
+
+
+/**
+ * Taints the given properties (and similarly named properties) by installing
+ * setters on Object.prototype that throw exceptions.
+ * @param {Array} properties an array of property names to taint
+ */
+function taintProperties(properties) {
+ properties.forEach(function (property) {
+ var adaptedProperties = [property, "__" + property, "_" + property, property + "_", property + "__"];
+ adaptedProperties.forEach(function (property) {
+ taintDataProperty(Object.prototype, property);
+ });
+ });
+}
+
+
+/**
+ * Taints the Array object by creating a setter for the property "0" and
+ * replacing some key methods with functions that throw exceptions.
+ */
+function taintArray() {
+ taintDataProperty(Array.prototype, "0");
+ taintMethod(Array.prototype, "indexOf");
+ taintMethod(Array.prototype, "join");
+ taintMethod(Array.prototype, "push");
+ taintMethod(Array.prototype, "slice");
+ taintMethod(Array.prototype, "sort");
+}
+
+
+/**
+ * Gets locale support info for the given constructor object, which must be one
+ * of Intl constructors.
+ * @param {object} Constructor the constructor for which to get locale support info
+ * @param {object} options the options while calling the constructor
+ * @return {object} locale support info with the following properties:
+ * supported: array of fully supported language tags
+ * byFallback: array of language tags that are supported through fallbacks
+ * unsupported: array of unsupported language tags
+ */
+function getLocaleSupportInfo(Constructor, options) {
+ var languages = ["zh", "es", "en", "hi", "ur", "ar", "ja", "pa"];
+ var scripts = ["Latn", "Hans", "Deva", "Arab", "Jpan", "Hant", "Guru"];
+ var countries = ["CN", "IN", "US", "PK", "JP", "TW", "HK", "SG", "419"];
+
+ var allTags = [];
+ var i, j, k;
+ var language, script, country;
+ for (i = 0; i < languages.length; i++) {
+ language = languages[i];
+ allTags.push(language);
+ for (j = 0; j < scripts.length; j++) {
+ script = scripts[j];
+ allTags.push(language + "-" + script);
+ for (k = 0; k < countries.length; k++) {
+ country = countries[k];
+ allTags.push(language + "-" + script + "-" + country);
+ }
+ }
+ for (k = 0; k < countries.length; k++) {
+ country = countries[k];
+ allTags.push(language + "-" + country);
+ }
+ }
+
+ var supported = [];
+ var byFallback = [];
+ var unsupported = [];
+ for (i = 0; i < allTags.length; i++) {
+ var request = allTags[i];
+ var result = new Constructor([request], options).resolvedOptions().locale;
+ if (request === result) {
+ supported.push(request);
+ } else if (request.indexOf(result) === 0) {
+ byFallback.push(request);
+ } else {
+ unsupported.push(request);
+ }
+ }
+
+ return {
+ supported: supported,
+ byFallback: byFallback,
+ unsupported: unsupported
+ };
+}
+
+
+/**
+ * Returns an array of strings for which IsStructurallyValidLanguageTag() returns false
+ */
+function getInvalidLanguageTags() {
+ var invalidLanguageTags = [
+ "", // empty tag
+ "i", // singleton alone
+ "x", // private use without subtag
+ "u", // extension singleton in first place
+ "419", // region code in first place
+ "u-nu-latn-cu-bob", // extension sequence without language
+ "hans-cmn-cn", // "hans" could theoretically be a 4-letter language code,
+ // but those can't be followed by extlang codes.
+ "cmn-hans-cn-u-u", // duplicate singleton
+ "cmn-hans-cn-t-u-ca-u", // duplicate singleton
+ "de-gregory-gregory", // duplicate variant
+ "*", // language range
+ "de-*", // language range
+ "中文", // non-ASCII letters
+ "en-ß", // non-ASCII letters
+ "ıd", // non-ASCII letters
+ "es-Latn-latn", // two scripts
+ "pl-PL-pl", // two regions
+ "u-ca-gregory", // extension in first place
+ "de-1996-1996", // duplicate numeric variant
+ "pt-u-ca-gregory-u-nu-latn", // duplicate singleton subtag
+
+ // Invalid tags starting with: https://github.com/tc39/ecma402/pull/289
+ "no-nyn", // regular grandfathered in BCP47, but invalid in UTS35
+ "i-klingon", // irregular grandfathered in BCP47, but invalid in UTS35
+ "zh-hak-CN", // language with extlang in BCP47, but invalid in UTS35
+ "sgn-ils", // language with extlang in BCP47, but invalid in UTS35
+ "x-foo", // privateuse-only in BCP47, but invalid in UTS35
+ "x-en-US-12345", // more privateuse-only variants.
+ "x-12345-12345-en-US",
+ "x-en-US-12345-12345",
+ "x-en-u-foo",
+ "x-en-u-foo-u-bar",
+ "x-u-foo",
+
+ // underscores in different parts of the language tag
+ "de_DE",
+ "DE_de",
+ "cmn_Hans",
+ "cmn-hans_cn",
+ "es_419",
+ "es-419-u-nu-latn-cu_bob",
+ "i_klingon",
+ "cmn-hans-cn-t-ca-u-ca-x_t-u",
+ "enochian_enochian",
+ "de-gregory_u-ca-gregory",
+
+ "en\u0000", // null-terminator sequence
+ " en", // leading whitespace
+ "en ", // trailing whitespace
+ "it-IT-Latn", // country before script tag
+ "de-u", // incomplete Unicode extension sequences
+ "de-u-",
+ "de-u-ca-",
+ "de-u-ca-gregory-",
+ "si-x", // incomplete private-use tags
+ "x-",
+ "x-y-",
+ ];
+
+ // make sure the data above is correct
+ for (var i = 0; i < invalidLanguageTags.length; ++i) {
+ var invalidTag = invalidLanguageTags[i];
+ assert(
+ !isCanonicalizedStructurallyValidLanguageTag(invalidTag),
+ "Test data \"" + invalidTag + "\" is a canonicalized and structurally valid language tag."
+ );
+ }
+
+ return invalidLanguageTags;
+}
+
+
+/**
+ * @description Tests whether locale is a String value representing a
+ * structurally valid and canonicalized BCP 47 language tag, as defined in
+ * sections 6.2.2 and 6.2.3 of the ECMAScript Internationalization API
+ * Specification.
+ * @param {String} locale the string to be tested.
+ * @result {Boolean} whether the test succeeded.
+ */
+function isCanonicalizedStructurallyValidLanguageTag(locale) {
+
+ /**
+ * Regular expression defining Unicode BCP 47 Locale Identifiers.
+ *
+ * Spec: https://unicode.org/reports/tr35/#Unicode_locale_identifier
+ */
+ var alpha = "[a-z]",
+ digit = "[0-9]",
+ alphanum = "[a-z0-9]",
+ variant = "(" + alphanum + "{5,8}|(?:" + digit + alphanum + "{3}))",
+ region = "(" + alpha + "{2}|" + digit + "{3})",
+ script = "(" + alpha + "{4})",
+ language = "(" + alpha + "{2,3}|" + alpha + "{5,8})",
+ privateuse = "(x(-[a-z0-9]{1,8})+)",
+ singleton = "(" + digit + "|[a-wy-z])",
+ attribute= "(" + alphanum + "{3,8})",
+ keyword = "(" + alphanum + alpha + "(-" + alphanum + "{3,8})*)",
+ unicode_locale_extensions = "(u((-" + keyword + ")+|((-" + attribute + ")+(-" + keyword + ")*)))",
+ tlang = "(" + language + "(-" + script + ")?(-" + region + ")?(-" + variant + ")*)",
+ tfield = "(" + alpha + digit + "(-" + alphanum + "{3,8})+)",
+ transformed_extensions = "(t((-" + tlang + "(-" + tfield + ")*)|(-" + tfield + ")+))",
+ other_singleton = "(" + digit + "|[a-sv-wy-z])",
+ other_extensions = "(" + other_singleton + "(-" + alphanum + "{2,8})+)",
+ extension = "(" + unicode_locale_extensions + "|" + transformed_extensions + "|" + other_extensions + ")",
+ locale_id = language + "(-" + script + ")?(-" + region + ")?(-" + variant + ")*(-" + extension + ")*(-" + privateuse + ")?",
+ languageTag = "^(" + locale_id + ")$",
+ languageTagRE = new RegExp(languageTag, "i");
+
+ var duplicateSingleton = "-" + singleton + "-(.*-)?\\1(?!" + alphanum + ")",
+ duplicateSingletonRE = new RegExp(duplicateSingleton, "i"),
+ duplicateVariant = "(" + alphanum + "{2,8}-)+" + variant + "-(" + alphanum + "{2,8}-)*\\2(?!" + alphanum + ")",
+ duplicateVariantRE = new RegExp(duplicateVariant, "i");
+
+ var transformKeyRE = new RegExp("^" + alpha + digit + "$", "i");
+
+ /**
+ * Verifies that the given string is a well-formed Unicode BCP 47 Locale Identifier
+ * with no duplicate variant or singleton subtags.
+ *
+ * Spec: ECMAScript Internationalization API Specification, draft, 6.2.2.
+ */
+ function isStructurallyValidLanguageTag(locale) {
+ if (!languageTagRE.test(locale)) {
+ return false;
+ }
+ locale = locale.split(/-x-/)[0];
+ return !duplicateSingletonRE.test(locale) && !duplicateVariantRE.test(locale);
+ }
+
+
+ /**
+ * Mappings from complete tags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __tagMappings = {
+ // property names must be in lower case; values in canonical form
+
+ "art-lojban": "jbo",
+ "cel-gaulish": "xtg",
+ "zh-guoyu": "zh",
+ "zh-hakka": "hak",
+ "zh-xiang": "hsn",
+ };
+
+
+ /**
+ * Mappings from language subtags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __languageMappings = {
+ // property names and values must be in canonical case
+
+ "aam": "aas",
+ "aar": "aa",
+ "abk": "ab",
+ "adp": "dz",
+ "afr": "af",
+ "aju": "jrb",
+ "aka": "ak",
+ "alb": "sq",
+ "als": "sq",
+ "amh": "am",
+ "ara": "ar",
+ "arb": "ar",
+ "arg": "an",
+ "arm": "hy",
+ "asd": "snz",
+ "asm": "as",
+ "aue": "ktz",
+ "ava": "av",
+ "ave": "ae",
+ "aym": "ay",
+ "ayr": "ay",
+ "ayx": "nun",
+ "aze": "az",
+ "azj": "az",
+ "bak": "ba",
+ "bam": "bm",
+ "baq": "eu",
+ "bcc": "bal",
+ "bcl": "bik",
+ "bel": "be",
+ "ben": "bn",
+ "bgm": "bcg",
+ "bh": "bho",
+ "bih": "bho",
+ "bis": "bi",
+ "bjd": "drl",
+ "bod": "bo",
+ "bos": "bs",
+ "bre": "br",
+ "bul": "bg",
+ "bur": "my",
+ "bxk": "luy",
+ "bxr": "bua",
+ "cat": "ca",
+ "ccq": "rki",
+ "ces": "cs",
+ "cha": "ch",
+ "che": "ce",
+ "chi": "zh",
+ "chu": "cu",
+ "chv": "cv",
+ "cjr": "mom",
+ "cka": "cmr",
+ "cld": "syr",
+ "cmk": "xch",
+ "cmn": "zh",
+ "cor": "kw",
+ "cos": "co",
+ "coy": "pij",
+ "cqu": "quh",
+ "cre": "cr",
+ "cwd": "cr",
+ "cym": "cy",
+ "cze": "cs",
+ "dan": "da",
+ "deu": "de",
+ "dgo": "doi",
+ "dhd": "mwr",
+ "dik": "din",
+ "diq": "zza",
+ "dit": "dif",
+ "div": "dv",
+ "drh": "mn",
+ "dut": "nl",
+ "dzo": "dz",
+ "ekk": "et",
+ "ell": "el",
+ "emk": "man",
+ "eng": "en",
+ "epo": "eo",
+ "esk": "ik",
+ "est": "et",
+ "eus": "eu",
+ "ewe": "ee",
+ "fao": "fo",
+ "fas": "fa",
+ "fat": "ak",
+ "fij": "fj",
+ "fin": "fi",
+ "fra": "fr",
+ "fre": "fr",
+ "fry": "fy",
+ "fuc": "ff",
+ "ful": "ff",
+ "gav": "dev",
+ "gaz": "om",
+ "gbo": "grb",
+ "geo": "ka",
+ "ger": "de",
+ "gfx": "vaj",
+ "ggn": "gvr",
+ "gla": "gd",
+ "gle": "ga",
+ "glg": "gl",
+ "glv": "gv",
+ "gno": "gon",
+ "gre": "el",
+ "grn": "gn",
+ "gti": "nyc",
+ "gug": "gn",
+ "guj": "gu",
+ "guv": "duz",
+ "gya": "gba",
+ "hat": "ht",
+ "hau": "ha",
+ "hdn": "hai",
+ "hea": "hmn",
+ "heb": "he",
+ "her": "hz",
+ "him": "srx",
+ "hin": "hi",
+ "hmo": "ho",
+ "hrr": "jal",
+ "hrv": "hr",
+ "hun": "hu",
+ "hye": "hy",
+ "ibi": "opa",
+ "ibo": "ig",
+ "ice": "is",
+ "ido": "io",
+ "iii": "ii",
+ "ike": "iu",
+ "iku": "iu",
+ "ile": "ie",
+ "ilw": "gal",
+ "in": "id",
+ "ina": "ia",
+ "ind": "id",
+ "ipk": "ik",
+ "isl": "is",
+ "ita": "it",
+ "iw": "he",
+ "jav": "jv",
+ "jeg": "oyb",
+ "ji": "yi",
+ "jpn": "ja",
+ "jw": "jv",
+ "kal": "kl",
+ "kan": "kn",
+ "kas": "ks",
+ "kat": "ka",
+ "kau": "kr",
+ "kaz": "kk",
+ "kgc": "tdf",
+ "kgh": "kml",
+ "khk": "mn",
+ "khm": "km",
+ "kik": "ki",
+ "kin": "rw",
+ "kir": "ky",
+ "kmr": "ku",
+ "knc": "kr",
+ "kng": "kg",
+ "knn": "kok",
+ "koj": "kwv",
+ "kom": "kv",
+ "kon": "kg",
+ "kor": "ko",
+ "kpv": "kv",
+ "krm": "bmf",
+ "ktr": "dtp",
+ "kua": "kj",
+ "kur": "ku",
+ "kvs": "gdj",
+ "kwq": "yam",
+ "kxe": "tvd",
+ "kzj": "dtp",
+ "kzt": "dtp",
+ "lao": "lo",
+ "lat": "la",
+ "lav": "lv",
+ "lbk": "bnc",
+ "lii": "raq",
+ "lim": "li",
+ "lin": "ln",
+ "lit": "lt",
+ "llo": "ngt",
+ "lmm": "rmx",
+ "ltz": "lb",
+ "lub": "lu",
+ "lug": "lg",
+ "lvs": "lv",
+ "mac": "mk",
+ "mah": "mh",
+ "mal": "ml",
+ "mao": "mi",
+ "mar": "mr",
+ "may": "ms",
+ "meg": "cir",
+ "mhr": "chm",
+ "mkd": "mk",
+ "mlg": "mg",
+ "mlt": "mt",
+ "mnk": "man",
+ "mo": "ro",
+ "mol": "ro",
+ "mon": "mn",
+ "mri": "mi",
+ "msa": "ms",
+ "mst": "mry",
+ "mup": "raj",
+ "mwj": "vaj",
+ "mya": "my",
+ "myd": "aog",
+ "myt": "mry",
+ "nad": "xny",
+ "nau": "na",
+ "nav": "nv",
+ "nbl": "nr",
+ "ncp": "kdz",
+ "nde": "nd",
+ "ndo": "ng",
+ "nep": "ne",
+ "nld": "nl",
+ "nno": "nn",
+ "nns": "nbr",
+ "nnx": "ngv",
+ "no": "nb",
+ "nob": "nb",
+ "nor": "nb",
+ "npi": "ne",
+ "nts": "pij",
+ "nya": "ny",
+ "oci": "oc",
+ "ojg": "oj",
+ "oji": "oj",
+ "ori": "or",
+ "orm": "om",
+ "ory": "or",
+ "oss": "os",
+ "oun": "vaj",
+ "pan": "pa",
+ "pbu": "ps",
+ "pcr": "adx",
+ "per": "fa",
+ "pes": "fa",
+ "pli": "pi",
+ "plt": "mg",
+ "pmc": "huw",
+ "pmu": "phr",
+ "pnb": "lah",
+ "pol": "pl",
+ "por": "pt",
+ "ppa": "bfy",
+ "ppr": "lcq",
+ "pry": "prt",
+ "pus": "ps",
+ "puz": "pub",
+ "que": "qu",
+ "quz": "qu",
+ "rmy": "rom",
+ "roh": "rm",
+ "ron": "ro",
+ "rum": "ro",
+ "run": "rn",
+ "rus": "ru",
+ "sag": "sg",
+ "san": "sa",
+ "sca": "hle",
+ "scc": "sr",
+ "scr": "hr",
+ "sin": "si",
+ "skk": "oyb",
+ "slk": "sk",
+ "slo": "sk",
+ "slv": "sl",
+ "sme": "se",
+ "smo": "sm",
+ "sna": "sn",
+ "snd": "sd",
+ "som": "so",
+ "sot": "st",
+ "spa": "es",
+ "spy": "kln",
+ "sqi": "sq",
+ "src": "sc",
+ "srd": "sc",
+ "srp": "sr",
+ "ssw": "ss",
+ "sun": "su",
+ "swa": "sw",
+ "swe": "sv",
+ "swh": "sw",
+ "tah": "ty",
+ "tam": "ta",
+ "tat": "tt",
+ "tdu": "dtp",
+ "tel": "te",
+ "tgk": "tg",
+ "tgl": "fil",
+ "tha": "th",
+ "thc": "tpo",
+ "thx": "oyb",
+ "tib": "bo",
+ "tie": "ras",
+ "tir": "ti",
+ "tkk": "twm",
+ "tl": "fil",
+ "tlw": "weo",
+ "tmp": "tyj",
+ "tne": "kak",
+ "ton": "to",
+ "tsf": "taj",
+ "tsn": "tn",
+ "tso": "ts",
+ "ttq": "tmh",
+ "tuk": "tk",
+ "tur": "tr",
+ "tw": "ak",
+ "twi": "ak",
+ "uig": "ug",
+ "ukr": "uk",
+ "umu": "del",
+ "uok": "ema",
+ "urd": "ur",
+ "uzb": "uz",
+ "uzn": "uz",
+ "ven": "ve",
+ "vie": "vi",
+ "vol": "vo",
+ "wel": "cy",
+ "wln": "wa",
+ "wol": "wo",
+ "xba": "cax",
+ "xho": "xh",
+ "xia": "acn",
+ "xkh": "waw",
+ "xpe": "kpe",
+ "xsj": "suj",
+ "xsl": "den",
+ "ybd": "rki",
+ "ydd": "yi",
+ "yid": "yi",
+ "yma": "lrr",
+ "ymt": "mtm",
+ "yor": "yo",
+ "yos": "zom",
+ "yuu": "yug",
+ "zai": "zap",
+ "zha": "za",
+ "zho": "zh",
+ "zsm": "ms",
+ "zul": "zu",
+ "zyb": "za",
+ };
+
+
+ /**
+ * Mappings from region subtags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __regionMappings = {
+ // property names and values must be in canonical case
+
+ "004": "AF",
+ "008": "AL",
+ "010": "AQ",
+ "012": "DZ",
+ "016": "AS",
+ "020": "AD",
+ "024": "AO",
+ "028": "AG",
+ "031": "AZ",
+ "032": "AR",
+ "036": "AU",
+ "040": "AT",
+ "044": "BS",
+ "048": "BH",
+ "050": "BD",
+ "051": "AM",
+ "052": "BB",
+ "056": "BE",
+ "060": "BM",
+ "062": "034",
+ "064": "BT",
+ "068": "BO",
+ "070": "BA",
+ "072": "BW",
+ "074": "BV",
+ "076": "BR",
+ "084": "BZ",
+ "086": "IO",
+ "090": "SB",
+ "092": "VG",
+ "096": "BN",
+ "100": "BG",
+ "104": "MM",
+ "108": "BI",
+ "112": "BY",
+ "116": "KH",
+ "120": "CM",
+ "124": "CA",
+ "132": "CV",
+ "136": "KY",
+ "140": "CF",
+ "144": "LK",
+ "148": "TD",
+ "152": "CL",
+ "156": "CN",
+ "158": "TW",
+ "162": "CX",
+ "166": "CC",
+ "170": "CO",
+ "174": "KM",
+ "175": "YT",
+ "178": "CG",
+ "180": "CD",
+ "184": "CK",
+ "188": "CR",
+ "191": "HR",
+ "192": "CU",
+ "196": "CY",
+ "203": "CZ",
+ "204": "BJ",
+ "208": "DK",
+ "212": "DM",
+ "214": "DO",
+ "218": "EC",
+ "222": "SV",
+ "226": "GQ",
+ "230": "ET",
+ "231": "ET",
+ "232": "ER",
+ "233": "EE",
+ "234": "FO",
+ "238": "FK",
+ "239": "GS",
+ "242": "FJ",
+ "246": "FI",
+ "248": "AX",
+ "249": "FR",
+ "250": "FR",
+ "254": "GF",
+ "258": "PF",
+ "260": "TF",
+ "262": "DJ",
+ "266": "GA",
+ "268": "GE",
+ "270": "GM",
+ "275": "PS",
+ "276": "DE",
+ "278": "DE",
+ "280": "DE",
+ "288": "GH",
+ "292": "GI",
+ "296": "KI",
+ "300": "GR",
+ "304": "GL",
+ "308": "GD",
+ "312": "GP",
+ "316": "GU",
+ "320": "GT",
+ "324": "GN",
+ "328": "GY",
+ "332": "HT",
+ "334": "HM",
+ "336": "VA",
+ "340": "HN",
+ "344": "HK",
+ "348": "HU",
+ "352": "IS",
+ "356": "IN",
+ "360": "ID",
+ "364": "IR",
+ "368": "IQ",
+ "372": "IE",
+ "376": "IL",
+ "380": "IT",
+ "384": "CI",
+ "388": "JM",
+ "392": "JP",
+ "398": "KZ",
+ "400": "JO",
+ "404": "KE",
+ "408": "KP",
+ "410": "KR",
+ "414": "KW",
+ "417": "KG",
+ "418": "LA",
+ "422": "LB",
+ "426": "LS",
+ "428": "LV",
+ "430": "LR",
+ "434": "LY",
+ "438": "LI",
+ "440": "LT",
+ "442": "LU",
+ "446": "MO",
+ "450": "MG",
+ "454": "MW",
+ "458": "MY",
+ "462": "MV",
+ "466": "ML",
+ "470": "MT",
+ "474": "MQ",
+ "478": "MR",
+ "480": "MU",
+ "484": "MX",
+ "492": "MC",
+ "496": "MN",
+ "498": "MD",
+ "499": "ME",
+ "500": "MS",
+ "504": "MA",
+ "508": "MZ",
+ "512": "OM",
+ "516": "NA",
+ "520": "NR",
+ "524": "NP",
+ "528": "NL",
+ "531": "CW",
+ "533": "AW",
+ "534": "SX",
+ "535": "BQ",
+ "540": "NC",
+ "548": "VU",
+ "554": "NZ",
+ "558": "NI",
+ "562": "NE",
+ "566": "NG",
+ "570": "NU",
+ "574": "NF",
+ "578": "NO",
+ "580": "MP",
+ "581": "UM",
+ "583": "FM",
+ "584": "MH",
+ "585": "PW",
+ "586": "PK",
+ "591": "PA",
+ "598": "PG",
+ "600": "PY",
+ "604": "PE",
+ "608": "PH",
+ "612": "PN",
+ "616": "PL",
+ "620": "PT",
+ "624": "GW",
+ "626": "TL",
+ "630": "PR",
+ "634": "QA",
+ "638": "RE",
+ "642": "RO",
+ "643": "RU",
+ "646": "RW",
+ "652": "BL",
+ "654": "SH",
+ "659": "KN",
+ "660": "AI",
+ "662": "LC",
+ "663": "MF",
+ "666": "PM",
+ "670": "VC",
+ "674": "SM",
+ "678": "ST",
+ "682": "SA",
+ "686": "SN",
+ "688": "RS",
+ "690": "SC",
+ "694": "SL",
+ "702": "SG",
+ "703": "SK",
+ "704": "VN",
+ "705": "SI",
+ "706": "SO",
+ "710": "ZA",
+ "716": "ZW",
+ "720": "YE",
+ "724": "ES",
+ "728": "SS",
+ "729": "SD",
+ "732": "EH",
+ "736": "SD",
+ "740": "SR",
+ "744": "SJ",
+ "748": "SZ",
+ "752": "SE",
+ "756": "CH",
+ "760": "SY",
+ "762": "TJ",
+ "764": "TH",
+ "768": "TG",
+ "772": "TK",
+ "776": "TO",
+ "780": "TT",
+ "784": "AE",
+ "788": "TN",
+ "792": "TR",
+ "795": "TM",
+ "796": "TC",
+ "798": "TV",
+ "800": "UG",
+ "804": "UA",
+ "807": "MK",
+ "818": "EG",
+ "826": "GB",
+ "830": "JE",
+ "831": "GG",
+ "832": "JE",
+ "833": "IM",
+ "834": "TZ",
+ "840": "US",
+ "850": "VI",
+ "854": "BF",
+ "858": "UY",
+ "860": "UZ",
+ "862": "VE",
+ "876": "WF",
+ "882": "WS",
+ "886": "YE",
+ "887": "YE",
+ "891": "RS",
+ "894": "ZM",
+ "958": "AA",
+ "959": "QM",
+ "960": "QN",
+ "962": "QP",
+ "963": "QQ",
+ "964": "QR",
+ "965": "QS",
+ "966": "QT",
+ "967": "EU",
+ "968": "QV",
+ "969": "QW",
+ "970": "QX",
+ "971": "QY",
+ "972": "QZ",
+ "973": "XA",
+ "974": "XB",
+ "975": "XC",
+ "976": "XD",
+ "977": "XE",
+ "978": "XF",
+ "979": "XG",
+ "980": "XH",
+ "981": "XI",
+ "982": "XJ",
+ "983": "XK",
+ "984": "XL",
+ "985": "XM",
+ "986": "XN",
+ "987": "XO",
+ "988": "XP",
+ "989": "XQ",
+ "990": "XR",
+ "991": "XS",
+ "992": "XT",
+ "993": "XU",
+ "994": "XV",
+ "995": "XW",
+ "996": "XX",
+ "997": "XY",
+ "998": "XZ",
+ "999": "ZZ",
+ "BU": "MM",
+ "CS": "RS",
+ "CT": "KI",
+ "DD": "DE",
+ "DY": "BJ",
+ "FQ": "AQ",
+ "FX": "FR",
+ "HV": "BF",
+ "JT": "UM",
+ "MI": "UM",
+ "NH": "VU",
+ "NQ": "AQ",
+ "PU": "UM",
+ "PZ": "PA",
+ "QU": "EU",
+ "RH": "ZW",
+ "TP": "TL",
+ "UK": "GB",
+ "VD": "VN",
+ "WK": "UM",
+ "YD": "YE",
+ "YU": "RS",
+ "ZR": "CD",
+ };
+
+
+ /**
+ * Complex mappings from language subtags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __complexLanguageMappings = {
+ // property names and values must be in canonical case
+
+ "cnr": {language: "sr", region: "ME"},
+ "drw": {language: "fa", region: "AF"},
+ "hbs": {language: "sr", script: "Latn"},
+ "prs": {language: "fa", region: "AF"},
+ "sh": {language: "sr", script: "Latn"},
+ "swc": {language: "sw", region: "CD"},
+ "tnf": {language: "fa", region: "AF"},
+ };
+
+
+ /**
+ * Complex mappings from region subtags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __complexRegionMappings = {
+ // property names and values must be in canonical case
+
+ "172": {
+ default: "RU",
+ "ab": "GE",
+ "az": "AZ",
+ "be": "BY",
+ "crh": "UA",
+ "gag": "MD",
+ "got": "UA",
+ "hy": "AM",
+ "ji": "UA",
+ "ka": "GE",
+ "kaa": "UZ",
+ "kk": "KZ",
+ "ku-Yezi": "GE",
+ "ky": "KG",
+ "os": "GE",
+ "rue": "UA",
+ "sog": "UZ",
+ "tg": "TJ",
+ "tk": "TM",
+ "tkr": "AZ",
+ "tly": "AZ",
+ "ttt": "AZ",
+ "ug-Cyrl": "KZ",
+ "uk": "UA",
+ "und-Armn": "AM",
+ "und-Chrs": "UZ",
+ "und-Geor": "GE",
+ "und-Goth": "UA",
+ "und-Sogd": "UZ",
+ "und-Sogo": "UZ",
+ "und-Yezi": "GE",
+ "uz": "UZ",
+ "xco": "UZ",
+ "xmf": "GE",
+ },
+ "200": {
+ default: "CZ",
+ "sk": "SK",
+ },
+ "530": {
+ default: "CW",
+ "vic": "SX",
+ },
+ "532": {
+ default: "CW",
+ "vic": "SX",
+ },
+ "536": {
+ default: "SA",
+ "akk": "IQ",
+ "ckb": "IQ",
+ "ku-Arab": "IQ",
+ "mis": "IQ",
+ "syr": "IQ",
+ "und-Hatr": "IQ",
+ "und-Syrc": "IQ",
+ "und-Xsux": "IQ",
+ },
+ "582": {
+ default: "FM",
+ "mh": "MH",
+ "pau": "PW",
+ },
+ "810": {
+ default: "RU",
+ "ab": "GE",
+ "az": "AZ",
+ "be": "BY",
+ "crh": "UA",
+ "et": "EE",
+ "gag": "MD",
+ "got": "UA",
+ "hy": "AM",
+ "ji": "UA",
+ "ka": "GE",
+ "kaa": "UZ",
+ "kk": "KZ",
+ "ku-Yezi": "GE",
+ "ky": "KG",
+ "lt": "LT",
+ "ltg": "LV",
+ "lv": "LV",
+ "os": "GE",
+ "rue": "UA",
+ "sgs": "LT",
+ "sog": "UZ",
+ "tg": "TJ",
+ "tk": "TM",
+ "tkr": "AZ",
+ "tly": "AZ",
+ "ttt": "AZ",
+ "ug-Cyrl": "KZ",
+ "uk": "UA",
+ "und-Armn": "AM",
+ "und-Chrs": "UZ",
+ "und-Geor": "GE",
+ "und-Goth": "UA",
+ "und-Sogd": "UZ",
+ "und-Sogo": "UZ",
+ "und-Yezi": "GE",
+ "uz": "UZ",
+ "vro": "EE",
+ "xco": "UZ",
+ "xmf": "GE",
+ },
+ "890": {
+ default: "RS",
+ "bs": "BA",
+ "hr": "HR",
+ "mk": "MK",
+ "sl": "SI",
+ },
+ "AN": {
+ default: "CW",
+ "vic": "SX",
+ },
+ "NT": {
+ default: "SA",
+ "akk": "IQ",
+ "ckb": "IQ",
+ "ku-Arab": "IQ",
+ "mis": "IQ",
+ "syr": "IQ",
+ "und-Hatr": "IQ",
+ "und-Syrc": "IQ",
+ "und-Xsux": "IQ",
+ },
+ "PC": {
+ default: "FM",
+ "mh": "MH",
+ "pau": "PW",
+ },
+ "SU": {
+ default: "RU",
+ "ab": "GE",
+ "az": "AZ",
+ "be": "BY",
+ "crh": "UA",
+ "et": "EE",
+ "gag": "MD",
+ "got": "UA",
+ "hy": "AM",
+ "ji": "UA",
+ "ka": "GE",
+ "kaa": "UZ",
+ "kk": "KZ",
+ "ku-Yezi": "GE",
+ "ky": "KG",
+ "lt": "LT",
+ "ltg": "LV",
+ "lv": "LV",
+ "os": "GE",
+ "rue": "UA",
+ "sgs": "LT",
+ "sog": "UZ",
+ "tg": "TJ",
+ "tk": "TM",
+ "tkr": "AZ",
+ "tly": "AZ",
+ "ttt": "AZ",
+ "ug-Cyrl": "KZ",
+ "uk": "UA",
+ "und-Armn": "AM",
+ "und-Chrs": "UZ",
+ "und-Geor": "GE",
+ "und-Goth": "UA",
+ "und-Sogd": "UZ",
+ "und-Sogo": "UZ",
+ "und-Yezi": "GE",
+ "uz": "UZ",
+ "vro": "EE",
+ "xco": "UZ",
+ "xmf": "GE",
+ },
+ };
+
+
+ /**
+ * Mappings from variant subtags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __variantMappings = {
+ // property names and values must be in canonical case
+
+ "aaland": {type: "region", replacement: "AX"},
+ "arevela": {type: "language", replacement: "hy"},
+ "arevmda": {type: "language", replacement: "hyw"},
+ "heploc": {type: "variant", replacement: "alalc97"},
+ "polytoni": {type: "variant", replacement: "polyton"},
+ };
+
+
+ /**
+ * Mappings from Unicode extension subtags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __unicodeMappings = {
+ // property names and values must be in canonical case
+
+ "ca": {
+ "ethiopic-amete-alem": "ethioaa",
+ "islamicc": "islamic-civil",
+ },
+ "kb": {
+ "yes": "true",
+ },
+ "kc": {
+ "yes": "true",
+ },
+ "kh": {
+ "yes": "true",
+ },
+ "kk": {
+ "yes": "true",
+ },
+ "kn": {
+ "yes": "true",
+ },
+ "ks": {
+ "primary": "level1",
+ "tertiary": "level3",
+ },
+ "ms": {
+ "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",
+ "no23": "no50",
+ "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",
+ "no23": "no50",
+ "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": {
+ "aqams": "nzakl",
+ "cnckg": "cnsha",
+ "cnhrb": "cnsha",
+ "cnkhg": "cnurc",
+ "cuba": "cuhav",
+ "egypt": "egcai",
+ "eire": "iedub",
+ "est": "utcw05",
+ "gmt0": "gmt",
+ "hongkong": "hkhkg",
+ "hst": "utcw10",
+ "iceland": "isrey",
+ "iran": "irthr",
+ "israel": "jeruslm",
+ "jamaica": "jmkin",
+ "japan": "jptyo",
+ "libya": "lytip",
+ "mst": "utcw07",
+ "navajo": "usden",
+ "poland": "plwaw",
+ "portugal": "ptlis",
+ "prc": "cnsha",
+ "roc": "twtpe",
+ "rok": "krsel",
+ "turkey": "trist",
+ "uct": "utc",
+ "usnavajo": "usden",
+ "zulu": "utc",
+ },
+ };
+
+
+ /**
+ * Mappings from Unicode extension subtags to preferred values.
+ *
+ * Spec: http://unicode.org/reports/tr35/#Identifiers
+ * Version: CLDR, version 36.1
+ */
+ var __transformMappings = {
+ // property names and values must be in canonical case
+
+ "d0": {
+ "name": "charname",
+ },
+ "m0": {
+ "names": "prprname",
+ },
+ };
+
+ /**
+ * Canonicalizes the given well-formed BCP 47 language tag, including regularized case of subtags.
+ *
+ * Spec: ECMAScript Internationalization API Specification, draft, 6.2.3.
+ * Spec: RFC 5646, section 4.5.
+ */
+ function canonicalizeLanguageTag(locale) {
+
+ // start with lower case for easier processing, and because most subtags will need to be lower case anyway
+ locale = locale.toLowerCase();
+
+ // handle mappings for complete tags
+ if (__tagMappings.hasOwnProperty(locale)) {
+ return __tagMappings[locale];
+ }
+
+ var subtags = locale.split("-");
+ var i = 0;
+
+ // handle standard part: all subtags before first variant or singleton subtag
+ var language;
+ var script;
+ var region;
+ while (i < subtags.length) {
+ var subtag = subtags[i];
+ if (i === 0) {
+ language = subtag;
+ } else if (subtag.length === 2 || subtag.length === 3) {
+ region = subtag.toUpperCase();
+ } else if (subtag.length === 4 && !("0" <= subtag[0] && subtag[0] <= "9")) {
+ script = subtag[0].toUpperCase() + subtag.substring(1).toLowerCase();
+ } else {
+ break;
+ }
+ i++;
+ }
+
+ if (__languageMappings.hasOwnProperty(language)) {
+ language = __languageMappings[language];
+ } else if (__complexLanguageMappings.hasOwnProperty(language)) {
+ var mapping = __complexLanguageMappings[language];
+
+ language = mapping.language;
+ if (script === undefined && mapping.hasOwnProperty("script")) {
+ script = mapping.script;
+ }
+ if (region === undefined && mapping.hasOwnProperty("region")) {
+ region = mapping.region;
+ }
+ }
+
+ if (region !== undefined) {
+ if (__regionMappings.hasOwnProperty(region)) {
+ region = __regionMappings[region];
+ } else if (__complexRegionMappings.hasOwnProperty(region)) {
+ var mapping = __complexRegionMappings[region];
+
+ var mappingKey = language;
+ if (script !== undefined) {
+ mappingKey += "-" + script;
+ }
+
+ if (mapping.hasOwnProperty(mappingKey)) {
+ region = mapping[mappingKey];
+ } else {
+ region = mapping.default;
+ }
+ }
+ }
+
+ // handle variants
+ var variants = [];
+ while (i < subtags.length && subtags[i].length > 1) {
+ var variant = subtags[i];
+
+ if (__variantMappings.hasOwnProperty(variant)) {
+ var mapping = __variantMappings[variant];
+ switch (mapping.type) {
+ case "language":
+ language = mapping.replacement;
+ break;
+
+ case "region":
+ region = mapping.replacement;
+ break;
+
+ case "variant":
+ variants.push(mapping.replacement);
+ break;
+
+ default:
+ throw new Error("illegal variant mapping type");
+ }
+ } else {
+ variants.push(variant);
+ }
+
+ i += 1;
+ }
+ variants.sort();
+
+ // handle extensions
+ var extensions = [];
+ while (i < subtags.length && subtags[i] !== "x") {
+ var extensionStart = i;
+ i++;
+ while (i < subtags.length && subtags[i].length > 1) {
+ i++;
+ }
+
+ var extension;
+ var extensionKey = subtags[extensionStart];
+ if (extensionKey === "u") {
+ var j = extensionStart + 1;
+
+ // skip over leading attributes
+ while (j < i && subtags[j].length > 2) {
+ j++;
+ }
+
+ extension = subtags.slice(extensionStart, j).join("-");
+
+ while (j < i) {
+ var keyStart = j;
+ j++;
+
+ while (j < i && subtags[j].length > 2) {
+ j++;
+ }
+
+ var key = subtags[keyStart];
+ var value = subtags.slice(keyStart + 1, j).join("-");
+
+ if (__unicodeMappings.hasOwnProperty(key)) {
+ var mapping = __unicodeMappings[key];
+ if (mapping.hasOwnProperty(value)) {
+ value = mapping[value];
+ }
+ }
+
+ extension += "-" + key;
+ if (value !== "" && value !== "true") {
+ extension += "-" + value;
+ }
+ }
+ } else if (extensionKey === "t") {
+ var j = extensionStart + 1;
+
+ while (j < i && !transformKeyRE.test(subtags[j])) {
+ j++;
+ }
+
+ extension = "t";
+
+ var transformLanguage = subtags.slice(extensionStart + 1, j).join("-");
+ if (transformLanguage !== "") {
+ extension += "-" + canonicalizeLanguageTag(transformLanguage).toLowerCase();
+ }
+
+ while (j < i) {
+ var keyStart = j;
+ j++;
+
+ while (j < i && subtags[j].length > 2) {
+ j++;
+ }
+
+ var key = subtags[keyStart];
+ var value = subtags.slice(keyStart + 1, j).join("-");
+
+ if (__transformMappings.hasOwnProperty(key)) {
+ var mapping = __transformMappings[key];
+ if (mapping.hasOwnProperty(value)) {
+ value = mapping[value];
+ }
+ }
+
+ extension += "-" + key + "-" + value;
+ }
+ } else {
+ extension = subtags.slice(extensionStart, i).join("-");
+ }
+
+ extensions.push(extension);
+ }
+ extensions.sort();
+
+ // handle private use
+ var privateUse;
+ if (i < subtags.length) {
+ privateUse = subtags.slice(i).join("-");
+ }
+
+ // put everything back together
+ var canonical = language;
+ if (script !== undefined) {
+ canonical += "-" + script;
+ }
+ if (region !== undefined) {
+ canonical += "-" + region;
+ }
+ if (variants.length > 0) {
+ canonical += "-" + variants.join("-");
+ }
+ if (extensions.length > 0) {
+ canonical += "-" + extensions.join("-");
+ }
+ if (privateUse !== undefined) {
+ if (canonical.length > 0) {
+ canonical += "-" + privateUse;
+ } else {
+ canonical = privateUse;
+ }
+ }
+
+ return canonical;
+ }
+
+ return typeof locale === "string" && isStructurallyValidLanguageTag(locale) &&
+ canonicalizeLanguageTag(locale) === locale;
+}
+
+
+/**
+ * Returns an array of error cases handled by CanonicalizeLocaleList().
+ */
+function getInvalidLocaleArguments() {
+ function CustomError() {}
+
+ var topLevelErrors = [
+ // fails ToObject
+ [null, TypeError],
+
+ // fails Get
+ [{ get length() { throw new CustomError(); } }, CustomError],
+
+ // fail ToLength
+ [{ length: Symbol.toPrimitive }, TypeError],
+ [{ length: { get [Symbol.toPrimitive]() { throw new CustomError(); } } }, CustomError],
+ [{ length: { [Symbol.toPrimitive]() { throw new CustomError(); } } }, CustomError],
+ [{ length: { get valueOf() { throw new CustomError(); } } }, CustomError],
+ [{ length: { valueOf() { throw new CustomError(); } } }, CustomError],
+ [{ length: { get toString() { throw new CustomError(); } } }, CustomError],
+ [{ length: { toString() { throw new CustomError(); } } }, CustomError],
+
+ // fail type check
+ [[undefined], TypeError],
+ [[null], TypeError],
+ [[true], TypeError],
+ [[Symbol.toPrimitive], TypeError],
+ [[1], TypeError],
+ [[0.1], TypeError],
+ [[NaN], TypeError],
+ ];
+
+ var invalidLanguageTags = [
+ "", // empty tag
+ "i", // singleton alone
+ "x", // private use without subtag
+ "u", // extension singleton in first place
+ "419", // region code in first place
+ "u-nu-latn-cu-bob", // extension sequence without language
+ "hans-cmn-cn", // "hans" could theoretically be a 4-letter language code,
+ // but those can't be followed by extlang codes.
+ "abcdefghi", // overlong language
+ "cmn-hans-cn-u-u", // duplicate singleton
+ "cmn-hans-cn-t-u-ca-u", // duplicate singleton
+ "de-gregory-gregory", // duplicate variant
+ "*", // language range
+ "de-*", // language range
+ "中文", // non-ASCII letters
+ "en-ß", // non-ASCII letters
+ "ıd" // non-ASCII letters
+ ];
+
+ return topLevelErrors.concat(
+ invalidLanguageTags.map(tag => [tag, RangeError]),
+ invalidLanguageTags.map(tag => [[tag], RangeError]),
+ invalidLanguageTags.map(tag => [["en", tag], RangeError]),
+ )
+}
+
+/**
+ * Tests whether the named options property is correctly handled by the given constructor.
+ * @param {object} Constructor the constructor to test.
+ * @param {string} property the name of the options property to test.
+ * @param {string} type the type that values of the property are expected to have
+ * @param {Array} [values] an array of allowed values for the property. Not needed for boolean.
+ * @param {any} fallback the fallback value that the property assumes if not provided.
+ * @param {object} testOptions additional options:
+ * @param {boolean} isOptional whether support for this property is optional for implementations.
+ * @param {boolean} noReturn whether the resulting value of the property is not returned.
+ * @param {boolean} isILD whether the resulting value of the property is implementation and locale dependent.
+ * @param {object} extra additional option to pass along, properties are value -> {option: value}.
+ */
+function testOption(Constructor, property, type, values, fallback, testOptions) {
+ var isOptional = testOptions !== undefined && testOptions.isOptional === true;
+ var noReturn = testOptions !== undefined && testOptions.noReturn === true;
+ var isILD = testOptions !== undefined && testOptions.isILD === true;
+
+ function addExtraOptions(options, value, testOptions) {
+ if (testOptions !== undefined && testOptions.extra !== undefined) {
+ var extra;
+ if (value !== undefined && testOptions.extra[value] !== undefined) {
+ extra = testOptions.extra[value];
+ } else if (testOptions.extra.any !== undefined) {
+ extra = testOptions.extra.any;
+ }
+ if (extra !== undefined) {
+ Object.getOwnPropertyNames(extra).forEach(function (prop) {
+ options[prop] = extra[prop];
+ });
+ }
+ }
+ }
+
+ var testValues, options, obj, expected, actual, error;
+
+ // test that the specified values are accepted. Also add values that convert to specified values.
+ if (type === "boolean") {
+ if (values === undefined) {
+ values = [true, false];
+ }
+ testValues = values.slice(0);
+ testValues.push(888);
+ testValues.push(0);
+ } else if (type === "string") {
+ testValues = values.slice(0);
+ testValues.push({toString: function () { return values[0]; }});
+ }
+ testValues.forEach(function (value) {
+ options = {};
+ options[property] = value;
+ addExtraOptions(options, value, testOptions);
+ obj = new Constructor(undefined, options);
+ if (noReturn) {
+ if (obj.resolvedOptions().hasOwnProperty(property)) {
+ throw new Test262Error("Option property " + property + " is returned, but shouldn't be.");
+ }
+ } else {
+ actual = obj.resolvedOptions()[property];
+ if (isILD) {
+ if (actual !== undefined && values.indexOf(actual) === -1) {
+ throw new Test262Error("Invalid value " + actual + " returned for property " + property + ".");
+ }
+ } else {
+ if (type === "boolean") {
+ expected = Boolean(value);
+ } else if (type === "string") {
+ expected = String(value);
+ }
+ if (actual !== expected && !(isOptional && actual === undefined)) {
+ throw new Test262Error("Option value " + value + " for property " + property +
+ " was not accepted; got " + actual + " instead.");
+ }
+ }
+ }
+ });
+
+ // test that invalid values are rejected
+ if (type === "string") {
+ var invalidValues = ["invalidValue", -1, null];
+ // assume that we won't have values in caseless scripts
+ if (values[0].toUpperCase() !== values[0]) {
+ invalidValues.push(values[0].toUpperCase());
+ } else {
+ invalidValues.push(values[0].toLowerCase());
+ }
+ invalidValues.forEach(function (value) {
+ options = {};
+ options[property] = value;
+ addExtraOptions(options, value, testOptions);
+ error = undefined;
+ try {
+ obj = new Constructor(undefined, options);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ throw new Test262Error("Invalid option value " + value + " for property " + property + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ throw new Test262Error("Invalid option value " + value + " for property " + property + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+ }
+
+ // test that fallback value or another valid value is used if no options value is provided
+ if (!noReturn) {
+ options = {};
+ addExtraOptions(options, undefined, testOptions);
+ obj = new Constructor(undefined, options);
+ actual = obj.resolvedOptions()[property];
+ if (!(isOptional && actual === undefined)) {
+ if (fallback !== undefined) {
+ if (actual !== fallback) {
+ throw new Test262Error("Option fallback value " + fallback + " for property " + property +
+ " was not used; got " + actual + " instead.");
+ }
+ } else {
+ if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) {
+ throw new Test262Error("Invalid value " + actual + " returned for property " + property + ".");
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Properties of the RegExp constructor that may be affected by use of regular
+ * expressions, and the default values of these properties. Properties are from
+ * https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Deprecated_and_obsolete_features#RegExp_Properties
+ */
+var regExpProperties = ["$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",
+ "$_", "$*", "$&", "$+", "$`", "$'",
+ "input", "lastMatch", "lastParen", "leftContext", "rightContext"
+];
+
+var regExpPropertiesDefaultValues = (function () {
+ var values = Object.create(null);
+ (/(?:)/).test("");
+ regExpProperties.forEach(function (property) {
+ values[property] = RegExp[property];
+ });
+ return values;
+}());
+
+
+/**
+ * Tests that executing the provided function (which may use regular expressions
+ * in its implementation) does not create or modify unwanted properties on the
+ * RegExp constructor.
+ */
+function testForUnwantedRegExpChanges(testFunc) {
+ (/(?:)/).test("");
+ testFunc();
+ regExpProperties.forEach(function (property) {
+ if (RegExp[property] !== regExpPropertiesDefaultValues[property]) {
+ throw new Test262Error("RegExp has unexpected property " + property + " with value " +
+ RegExp[property] + ".");
+ }
+ });
+}
+
+
+/**
+ * Returns an array of all known calendars.
+ */
+function allCalendars() {
+ // source: CLDR file common/bcp47/number.xml; version CLDR 39.
+ // https://github.com/unicode-org/cldr/blob/master/common/bcp47/calendar.xml
+ return [
+ "buddhist",
+ "chinese",
+ "coptic",
+ "dangi",
+ "ethioaa",
+ "ethiopic",
+ "gregory",
+ "hebrew",
+ "indian",
+ "islamic",
+ "islamic-umalqura",
+ "islamic-tbla",
+ "islamic-civil",
+ "islamic-rgsa",
+ "iso8601",
+ "japanese",
+ "persian",
+ "roc",
+ ];
+}
+
+
+/**
+ * Returns an array of all known collations.
+ */
+function allCollations() {
+ // source: CLDR file common/bcp47/collation.xml; version CLDR 39.
+ // https://github.com/unicode-org/cldr/blob/master/common/bcp47/collation.xml
+ return [
+ "big5han",
+ "compat",
+ "dict",
+ "direct",
+ "ducet",
+ "emoji",
+ "eor",
+ "gb2312",
+ "phonebk",
+ "phonetic",
+ "pinyin",
+ "reformed",
+ "search",
+ "searchjl",
+ "standard",
+ "stroke",
+ "trad",
+ "unihan",
+ "zhuyin",
+ ];
+}
+
+
+/**
+ * Returns an array of all known numbering systems.
+ */
+function allNumberingSystems() {
+ // source: CLDR file common/bcp47/number.xml; version CLDR 40 & new in Unicode 14.0
+ // https://github.com/unicode-org/cldr/blob/master/common/bcp47/number.xml
+ return [
+ "adlm",
+ "ahom",
+ "arab",
+ "arabext",
+ "armn",
+ "armnlow",
+ "bali",
+ "beng",
+ "bhks",
+ "brah",
+ "cakm",
+ "cham",
+ "cyrl",
+ "deva",
+ "diak",
+ "ethi",
+ "finance",
+ "fullwide",
+ "geor",
+ "gong",
+ "gonm",
+ "grek",
+ "greklow",
+ "gujr",
+ "guru",
+ "hanidays",
+ "hanidec",
+ "hans",
+ "hansfin",
+ "hant",
+ "hantfin",
+ "hebr",
+ "hmng",
+ "hmnp",
+ "java",
+ "jpan",
+ "jpanfin",
+ "jpanyear",
+ "kali",
+ "kawi",
+ "khmr",
+ "knda",
+ "lana",
+ "lanatham",
+ "laoo",
+ "latn",
+ "lepc",
+ "limb",
+ "mathbold",
+ "mathdbl",
+ "mathmono",
+ "mathsanb",
+ "mathsans",
+ "mlym",
+ "modi",
+ "mong",
+ "mroo",
+ "mtei",
+ "mymr",
+ "mymrshan",
+ "mymrtlng",
+ "nagm",
+ "native",
+ "newa",
+ "nkoo",
+ "olck",
+ "orya",
+ "osma",
+ "rohg",
+ "roman",
+ "romanlow",
+ "saur",
+ "shrd",
+ "sind",
+ "sinh",
+ "sora",
+ "sund",
+ "takr",
+ "talu",
+ "taml",
+ "tamldec",
+ "tnsa",
+ "telu",
+ "thai",
+ "tirh",
+ "tibt",
+ "traditio",
+ "vaii",
+ "wara",
+ "wcho",
+ ];
+}
+
+
+/**
+ * Tests whether name is a valid BCP 47 numbering system name
+ * and not excluded from use in the ECMAScript Internationalization API.
+ * @param {string} name the name to be tested.
+ * @return {boolean} whether name is a valid BCP 47 numbering system name and
+ * allowed for use in the ECMAScript Internationalization API.
+ */
+
+function isValidNumberingSystem(name) {
+
+ var numberingSystems = allNumberingSystems();
+
+ var excluded = [
+ "finance",
+ "native",
+ "traditio"
+ ];
+
+
+ return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1;
+}
+
+
+/**
+ * Provides the digits of numbering systems with simple digit mappings,
+ * as specified in 11.3.2.
+ */
+
+var numberingSystemDigits = {
+ adlm: "𞥐𞥑𞥒𞥓𞥔𞥕𞥖𞥗𞥘𞥙",
+ ahom: "𑜰𑜱𑜲𑜳𑜴𑜵𑜶𑜷𑜸𑜹",
+ arab: "٠١٢٣٤٥٦٧٨٩",
+ arabext: "۰۱۲۳۴۵۶۷۸۹",
+ bali: "\u1B50\u1B51\u1B52\u1B53\u1B54\u1B55\u1B56\u1B57\u1B58\u1B59",
+ beng: "০১২৩৪৫৬৭৮৯",
+ bhks: "𑱐𑱑𑱒𑱓𑱔𑱕𑱖𑱗𑱘𑱙",
+ brah: "𑁦𑁧𑁨𑁩𑁪𑁫𑁬𑁭𑁮𑁯",
+ cakm: "𑄶𑄷𑄸𑄹𑄺𑄻𑄼𑄽𑄾𑄿",
+ cham: "꩐꩑꩒꩓꩔꩕꩖꩗꩘꩙",
+ deva: "०१२३४५६७८९",
+ diak: "𑥐𑥑𑥒𑥓𑥔𑥕𑥖𑥗𑥘𑥙",
+ fullwide: "0123456789",
+ gong: "𑶠𑶡𑶢𑶣𑶤𑶥𑶦𑶧𑶨𑶩",
+ gonm: "𑵐𑵑𑵒𑵓𑵔𑵕𑵖𑵗𑵘𑵙",
+ gujr: "૦૧૨૩૪૫૬૭૮૯",
+ guru: "੦੧੨੩੪੫੬੭੮੯",
+ hanidec: "〇一二三四五六七八九",
+ hmng: "𖭐𖭑𖭒𖭓𖭔𖭕𖭖𖭗𖭘𖭙",
+ hmnp: "𞅀𞅁𞅂𞅃𞅄𞅅𞅆𞅇𞅈𞅉",
+ java: "꧐꧑꧒꧓꧔꧕꧖꧗꧘꧙",
+ kali: "꤀꤁꤂꤃꤄꤅꤆꤇꤈꤉",
+ kawi: "\u{11F50}\u{11F51}\u{11F52}\u{11F53}\u{11F54}\u{11F55}\u{11F56}\u{11F57}\u{11F58}\u{11F59}",
+ khmr: "០១២៣៤៥៦៧៨៩",
+ knda: "೦೧೨೩೪೫೬೭೮೯",
+ lana: "᪀᪁᪂᪃᪄᪅᪆᪇᪈᪉",
+ lanatham: "᪐᪑᪒᪓᪔᪕᪖᪗᪘᪙",
+ laoo: "໐໑໒໓໔໕໖໗໘໙",
+ latn: "0123456789",
+ lepc: "᱀᱁᱂᱃᱄᱅᱆᱇᱈᱉",
+ limb: "\u1946\u1947\u1948\u1949\u194A\u194B\u194C\u194D\u194E\u194F",
+ nagm: "\u{1E4F0}\u{1E4F1}\u{1E4F2}\u{1E4F3}\u{1E4F4}\u{1E4F5}\u{1E4F6}\u{1E4F7}\u{1E4F8}\u{1E4F9}",
+ mathbold: "𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗",
+ mathdbl: "𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡",
+ mathmono: "𝟶𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿",
+ mathsanb: "𝟬𝟭𝟮𝟯𝟰𝟱𝟲𝟳𝟴𝟵",
+ mathsans: "𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫",
+ mlym: "൦൧൨൩൪൫൬൭൮൯",
+ modi: "𑙐𑙑𑙒𑙓𑙔𑙕𑙖𑙗𑙘𑙙",
+ mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙",
+ mroo: "𖩠𖩡𖩢𖩣𖩤𖩥𖩦𖩧𖩨𖩩",
+ mtei: "꯰꯱꯲꯳꯴꯵꯶꯷꯸꯹",
+ mymr: "၀၁၂၃၄၅၆၇၈၉",
+ mymrshan: "႐႑႒႓႔႕႖႗႘႙",
+ mymrtlng: "꧰꧱꧲꧳꧴꧵꧶꧷꧸꧹",
+ newa: "𑑐𑑑𑑒𑑓𑑔𑑕𑑖𑑗𑑘𑑙",
+ nkoo: "߀߁߂߃߄߅߆߇߈߉",
+ olck: "᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙",
+ orya: "୦୧୨୩୪୫୬୭୮୯",
+ osma: "𐒠𐒡𐒢𐒣𐒤𐒥𐒦𐒧𐒨𐒩",
+ rohg: "𐴰𐴱𐴲𐴳𐴴𐴵𐴶𐴷𐴸𐴹",
+ saur: "꣐꣑꣒꣓꣔꣕꣖꣗꣘꣙",
+ segment: "🯰🯱🯲🯳🯴🯵🯶🯷🯸🯹",
+ shrd: "𑇐𑇑𑇒𑇓𑇔𑇕𑇖𑇗𑇘𑇙",
+ sind: "𑋰𑋱𑋲𑋳𑋴𑋵𑋶𑋷𑋸𑋹",
+ sinh: "෦෧෨෩෪෫෬෭෮෯",
+ sora: "𑃰𑃱𑃲𑃳𑃴𑃵𑃶𑃷𑃸𑃹",
+ sund: "᮰᮱᮲᮳᮴᮵᮶᮷᮸᮹",
+ takr: "𑛀𑛁𑛂𑛃𑛄𑛅𑛆𑛇𑛈𑛉",
+ talu: "᧐᧑᧒᧓᧔᧕᧖᧗᧘᧙",
+ tamldec: "௦௧௨௩௪௫௬௭௮௯",
+ tnsa: "\u{16AC0}\u{16AC1}\u{16AC2}\u{16AC3}\u{16AC4}\u{16AC5}\u{16AC6}\u{16AC7}\u{16AC8}\u{16AC9}",
+ telu: "౦౧౨౩౪౫౬౭౮౯",
+ thai: "๐๑๒๓๔๕๖๗๘๙",
+ tibt: "༠༡༢༣༤༥༦༧༨༩",
+ tirh: "𑓐𑓑𑓒𑓓𑓔𑓕𑓖𑓗𑓘𑓙",
+ vaii: "꘠꘡꘢꘣꘤꘥꘦꘧꘨꘩",
+ wara: "𑣠𑣡𑣢𑣣𑣤𑣥𑣦𑣧𑣨𑣩",
+ wcho: "𞋰𞋱𞋲𞋳𞋴𞋵𞋶𞋷𞋸𞋹",
+};
+
+
+/**
+ * Returns an array of all simple, sanctioned unit identifiers.
+ */
+function allSimpleSanctionedUnits() {
+ // https://tc39.es/ecma402/#table-sanctioned-simple-unit-identifiers
+ return [
+ "acre",
+ "bit",
+ "byte",
+ "celsius",
+ "centimeter",
+ "day",
+ "degree",
+ "fahrenheit",
+ "fluid-ounce",
+ "foot",
+ "gallon",
+ "gigabit",
+ "gigabyte",
+ "gram",
+ "hectare",
+ "hour",
+ "inch",
+ "kilobit",
+ "kilobyte",
+ "kilogram",
+ "kilometer",
+ "liter",
+ "megabit",
+ "megabyte",
+ "meter",
+ "microsecond",
+ "mile",
+ "mile-scandinavian",
+ "milliliter",
+ "millimeter",
+ "millisecond",
+ "minute",
+ "month",
+ "nanosecond",
+ "ounce",
+ "percent",
+ "petabyte",
+ "pound",
+ "second",
+ "stone",
+ "terabit",
+ "terabyte",
+ "week",
+ "yard",
+ "year",
+ ];
+}
+
+
+/**
+ * Tests that number formatting is handled correctly. The function checks that the
+ * digit sequences in formatted output are as specified, converted to the
+ * selected numbering system, and embedded in consistent localized patterns.
+ * @param {Array} locales the locales to be tested.
+ * @param {Array} numberingSystems the numbering systems to be tested.
+ * @param {Object} options the options to pass to Intl.NumberFormat. Options
+ * must include {useGrouping: false}, and must cause 1.1 to be formatted
+ * pre- and post-decimal digits.
+ * @param {Object} testData maps input data (in ES5 9.3.1 format) to expected output strings
+ * in unlocalized format with Western digits.
+ */
+
+function testNumberFormat(locales, numberingSystems, options, testData) {
+ locales.forEach(function (locale) {
+ numberingSystems.forEach(function (numbering) {
+ var digits = numberingSystemDigits[numbering];
+ var format = new Intl.NumberFormat([locale + "-u-nu-" + numbering], options);
+
+ function getPatternParts(positive) {
+ var n = positive ? 1.1 : -1.1;
+ var formatted = format.format(n);
+ var oneoneRE = "([^" + digits + "]*)[" + digits + "]+([^" + digits + "]+)[" + digits + "]+([^" + digits + "]*)";
+ var match = formatted.match(new RegExp(oneoneRE));
+ if (match === null) {
+ throw new Test262Error("Unexpected formatted " + n + " for " +
+ format.resolvedOptions().locale + " and options " +
+ JSON.stringify(options) + ": " + formatted);
+ }
+ return match;
+ }
+
+ function toNumbering(raw) {
+ return raw.replace(/[0-9]/g, function (digit) {
+ return digits[digit.charCodeAt(0) - "0".charCodeAt(0)];
+ });
+ }
+
+ function buildExpected(raw, patternParts) {
+ var period = raw.indexOf(".");
+ if (period === -1) {
+ return patternParts[1] + toNumbering(raw) + patternParts[3];
+ } else {
+ return patternParts[1] +
+ toNumbering(raw.substring(0, period)) +
+ patternParts[2] +
+ toNumbering(raw.substring(period + 1)) +
+ patternParts[3];
+ }
+ }
+
+ if (format.resolvedOptions().numberingSystem === numbering) {
+ // figure out prefixes, infixes, suffixes for positive and negative values
+ var posPatternParts = getPatternParts(true);
+ var negPatternParts = getPatternParts(false);
+
+ Object.getOwnPropertyNames(testData).forEach(function (input) {
+ var rawExpected = testData[input];
+ var patternParts;
+ if (rawExpected[0] === "-") {
+ patternParts = negPatternParts;
+ rawExpected = rawExpected.substring(1);
+ } else {
+ patternParts = posPatternParts;
+ }
+ var expected = buildExpected(rawExpected, patternParts);
+ var actual = format.format(input);
+ if (actual !== expected) {
+ throw new Test262Error("Formatted value for " + input + ", " +
+ format.resolvedOptions().locale + " and options " +
+ JSON.stringify(options) + " is " + actual + "; expected " + expected + ".");
+ }
+ });
+ }
+ });
+ });
+}
+
+
+/**
+ * Return the components of date-time formats.
+ * @return {Array} an array with all date-time components.
+ */
+
+function getDateTimeComponents() {
+ return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"];
+}
+
+
+/**
+ * Return the valid values for the given date-time component, as specified
+ * by the table in section 12.1.1.
+ * @param {string} component a date-time component.
+ * @return {Array} an array with the valid values for the component.
+ */
+
+function getDateTimeComponentValues(component) {
+
+ var components = {
+ weekday: ["narrow", "short", "long"],
+ era: ["narrow", "short", "long"],
+ year: ["2-digit", "numeric"],
+ month: ["2-digit", "numeric", "narrow", "short", "long"],
+ day: ["2-digit", "numeric"],
+ hour: ["2-digit", "numeric"],
+ minute: ["2-digit", "numeric"],
+ second: ["2-digit", "numeric"],
+ timeZoneName: ["short", "long"]
+ };
+
+ var result = components[component];
+ if (result === undefined) {
+ throw new Test262Error("Internal error: No values defined for date-time component " + component + ".");
+ }
+ return result;
+}
+
+
+/**
+ * @description Tests whether timeZone is a String value representing a
+ * structurally valid and canonicalized time zone name, as defined in
+ * sections 6.4.1 and 6.4.2 of the ECMAScript Internationalization API
+ * Specification.
+ * @param {String} timeZone the string to be tested.
+ * @result {Boolean} whether the test succeeded.
+ */
+
+function isCanonicalizedStructurallyValidTimeZoneName(timeZone) {
+ /**
+ * Regular expression defining IANA Time Zone names.
+ *
+ * Spec: IANA Time Zone Database, Theory file
+ */
+ var fileNameComponent = "(?:[A-Za-z_]|\\.(?!\\.?(?:/|$)))[A-Za-z.\\-_]{0,13}";
+ var fileName = fileNameComponent + "(?:/" + fileNameComponent + ")*";
+ var etcName = "(?:Etc/)?GMT[+-]\\d{1,2}";
+ var systemVName = "SystemV/[A-Z]{3}\\d{1,2}(?:[A-Z]{3})?";
+ var legacyName = etcName + "|" + systemVName + "|CST6CDT|EST5EDT|MST7MDT|PST8PDT|NZ";
+ var zoneNamePattern = new RegExp("^(?:" + fileName + "|" + legacyName + ")$");
+
+ if (typeof timeZone !== "string") {
+ return false;
+ }
+ // 6.4.2 CanonicalizeTimeZoneName (timeZone), step 3
+ if (timeZone === "UTC") {
+ return true;
+ }
+ // 6.4.2 CanonicalizeTimeZoneName (timeZone), step 3
+ if (timeZone === "Etc/UTC" || timeZone === "Etc/GMT") {
+ return false;
+ }
+ return zoneNamePattern.test(timeZone);
+}
+
+
+/**
+ * @description Simplified PartitionDurationFormatPattern implementation which
+ * only supports the "en" locale.
+ * @param {Object} duration the duration record
+ * @param {String} style the duration format style
+ * @result {Array} an array with formatted duration parts
+ */
+
+function partitionDurationFormatPattern(duration, style = "short") {
+ const units = [
+ "years",
+ "months",
+ "weeks",
+ "days",
+ "hours",
+ "minutes",
+ "seconds",
+ "milliseconds",
+ "microseconds",
+ "nanoseconds",
+ ];
+
+ function durationToFractionalSeconds(duration) {
+ let {
+ seconds = 0,
+ milliseconds = 0,
+ microseconds = 0,
+ nanoseconds = 0,
+ } = duration;
+
+ // Directly return seconds when no sub-seconds are present.
+ if (milliseconds === 0 && microseconds === 0 && nanoseconds === 0) {
+ return seconds;
+ }
+
+ // Otherwise compute the overall amount of nanoseconds using BigInt to avoid
+ // loss of precision.
+ let ns_sec = BigInt(seconds) * 1_000_000_000n;
+ let ns_ms = BigInt(milliseconds) * 1_000_000n;
+ let ns_us = BigInt(microseconds) * 1_000n;
+ let ns = ns_sec + ns_ms + ns_us + BigInt(nanoseconds);
+
+ // Split the nanoseconds amount into seconds and sub-seconds.
+ let q = ns / 1_000_000_000n;
+ let r = ns % 1_000_000_000n;
+
+ // Pad sub-seconds, without any leading negative sign, to nine digits.
+ if (r < 0) {
+ r = -r;
+ }
+ r = String(r).padStart(9, "0");
+
+ // Return seconds with fractional part as a decimal string.
+ return `${q}.${r}`;
+ }
+
+ // Only "en" is supported.
+ const locale = "en";
+ const numberingSystem = "latn";
+ const timeSeparator = ":";
+
+ let result = [];
+ let separated = false;
+
+ for (let unit of units) {
+ // Absent units default to zero.
+ let value = duration[unit] ?? 0;
+
+ let display = "auto";
+ if (style === "digital") {
+ // Always display numeric units per GetDurationUnitOptions.
+ if (unit === "hours" || unit === "minutes" || unit === "seconds") {
+ display = "always";
+ }
+
+ // Numeric seconds and sub-seconds are combined into a single value.
+ if (unit === "seconds") {
+ value = durationToFractionalSeconds(duration);
+ }
+ }
+
+ // "auto" display omits zero units.
+ if (value !== 0 || display !== "auto") {
+ // Map the DurationFormat style to a NumberFormat style.
+ let unitStyle = style;
+ if (style === "digital") {
+ if (unit === "hours") {
+ unitStyle = "numeric";
+ } else if (unit === "minutes" || unit === "seconds") {
+ unitStyle = "2-digit";
+ } else {
+ unitStyle = "short";
+ }
+ }
+
+ // NumberFormat requires singular unit names.
+ let numberFormatUnit = unit.slice(0, -1);
+
+ // Compute the matching NumberFormat options.
+ let nfOpts;
+ if (unitStyle !== "numeric" && unitStyle !== "2-digit") {
+ // The value is formatted as a standalone unit.
+ nfOpts = {
+ numberingSystem,
+ style: "unit",
+ unit: numberFormatUnit,
+ unitDisplay: unitStyle,
+ };
+ } else {
+ let roundingMode = undefined;
+ let minimumFractionDigits = undefined;
+ let maximumFractionDigits = undefined;
+
+ // Numeric seconds include any sub-seconds.
+ if (style === "digital" && unit === "seconds") {
+ roundingMode = "trunc";
+ minimumFractionDigits = 0;
+ maximumFractionDigits = 9;
+ }
+
+ // The value is formatted as a numeric unit.
+ nfOpts = {
+ numberingSystem,
+ minimumIntegerDigits: (unitStyle === "2-digit" ? 2 : 1),
+ roundingMode,
+ minimumFractionDigits,
+ maximumFractionDigits,
+ };
+ }
+
+ let nf = new Intl.NumberFormat(locale, nfOpts);
+ let formatted = nf.formatToParts(value);
+
+ // Add |numberFormatUnit| to the formatted number.
+ let list = [];
+ for (let {value, type} of formatted) {
+ list.push({type, value, unit: numberFormatUnit});
+ }
+
+ if (!separated) {
+ // Prepend the separator before the next numeric unit.
+ if (unitStyle === "2-digit" || unitStyle === "numeric") {
+ separated = true;
+ }
+
+ // Append the formatted number to |result|.
+ result.push(list);
+ } else {
+ let last = result[result.length - 1];
+
+ // Prepend the time separator before the formatted number.
+ last.push({
+ type: "literal",
+ value: timeSeparator,
+ });
+
+ // Concatenate |last| and the formatted number.
+ last.push(...list);
+ }
+ } else {
+ separated = false;
+ }
+
+ // No further units possible after "seconds" when style is "digital".
+ if (style === "digital" && unit === "seconds") {
+ break;
+ }
+ }
+
+ let lf = new Intl.ListFormat(locale, {
+ type: "unit",
+ style: (style !== "digital" ? style : "short"),
+ });
+
+ // Collect all formatted units into a list of strings.
+ let strings = [];
+ for (let parts of result) {
+ let string = "";
+ for (let {value} of parts) {
+ string += value;
+ }
+ strings.push(string);
+ }
+
+ // Format the list of strings and compute the overall result.
+ let flattened = [];
+ for (let {type, value} of lf.formatToParts(strings)) {
+ if (type === "element") {
+ flattened.push(...result.shift());
+ } else {
+ flattened.push({type, value});
+ }
+ }
+ return flattened;
+}
+
+
+/**
+ * @description Return the formatted string from partitionDurationFormatPattern.
+ * @param {Object} duration the duration record
+ * @param {String} style the duration format style
+ * @result {String} a string containing the formatted duration
+ */
+
+function formatDurationFormatPattern(duration, style) {
+ return partitionDurationFormatPattern(duration, style).reduce((acc, e) => acc + e.value, "");
+}