// 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:| Thisfilecontainssharedfunctionsforthetestsintheconformancetest suitefortheECMAScriptInternationalizationAPI. author:NorbertLindenberg defines: -testWithIntlConstructors -taintDataProperty -taintMethod -taintProperties -taintArray -getLocaleSupportInfo -getInvalidLanguageTags -isCanonicalizedStructurallyValidLanguageTag -getInvalidLocaleArguments -testOption -testForUnwantedRegExpChanges -allCalendars -allCollations -allNumberingSystems -isValidNumberingSystem -numberingSystemDigits -allSimpleSanctionedUnits -testNumberFormat -getDateTimeComponents -getDateTimeComponentValues -isCanonicalizedStructurallyValidTimeZoneName -partitionDurationFormatPattern -formatDurationFormatPattern
---*/ /**
*/
/** *@descriptionCallstheprovidedfunctionforeveryserviceconstructorin *theIntlobject. *@param{Function}fthefunctiontocallforeachserviceconstructorin *theIntlobject. *@param{Function}Constructortheconstructorobjecttotestwith.
*/ 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;
}
});
/** *Getslocalesupportinfoforthegivenconstructorobject,whichmustbeone *ofIntlconstructors. *@param{object}Constructortheconstructorforwhichtogetlocalesupportinfo *@param{object}optionstheoptionswhilecallingtheconstructor *@return{object}localesupportinfowiththefollowingproperties: *supported:arrayoffullysupportedlanguagetags *byFallback:arrayoflanguagetagsthataresupportedthroughfallbacks *unsupported:arrayofunsupportedlanguagetags
*/ 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);
} elseif (request.indexOf(result) === 0) {
byFallback.push(request);
} else {
unsupported.push(request);
}
}
/** *ReturnsanarrayofstringsforwhichIsStructurallyValidLanguageTag()returnsfalse
*/ 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."
);
}
/** *Mappingsfromcompletetagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __tagMappings = { // property names must be in lower case; values in canonical form
/** *Mappingsfromlanguagesubtagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __languageMappings = { // property names and values must be in canonical case
/** *Mappingsfromregionsubtagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __regionMappings = { // property names and values must be in canonical case
/** *Complexmappingsfromlanguagesubtagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __complexLanguageMappings = { // property names and values must be in canonical case
/** *Complexmappingsfromregionsubtagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __complexRegionMappings = { // property names and values must be in canonical case
/** *Mappingsfromvariantsubtagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __variantMappings = { // property names and values must be in canonical case
/** *MappingsfromUnicodeextensionsubtagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __unicodeMappings = { // property names and values must be in canonical case
/** *MappingsfromUnicodeextensionsubtagstopreferredvalues. * *Spec:http://unicode.org/reports/tr35/#Identifiers *Version:CLDR,version36.1
*/ var __transformMappings = { // property names and values must be in canonical case
/** *Canonicalizesthegivenwell-formedBCP47languagetag,includingregularizedcaseofsubtags. * *Spec:ECMAScriptInternationalizationAPISpecification,draft,6.2.3. *Spec:RFC5646,section4.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;
} elseif (subtag.length === 2 || subtag.length === 3) {
region = subtag.toUpperCase();
} elseif (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];
} elseif (__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];
} elseif (__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;
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];
}
}
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
];
function addExtraOptions(options, value, testOptions) { if (testOptions !== undefined && testOptions.extra !== undefined) { var extra; if (value !== undefined && testOptions.extra[value] !== undefined) {
extra = testOptions.extra[value];
} elseif (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);
} elseif (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)) { thrownew Test262Error("Option property " + property + " is returned, but shouldn't be.");
}
} else {
actual = obj.resolvedOptions()[property]; if (isILD) { if (actual !== undefined && values.indexOf(actual) === -1) { thrownew Test262Error("Invalid value " + actual + " returned for property " + property + ".");
}
} else { if (type === "boolean") {
expected = Boolean(value);
} elseif (type === "string") {
expected = String(value);
} if (actual !== expected && !(isOptional && actual === undefined)) { thrownew 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) { thrownew Test262Error("Invalid option value " + value + " for property " + property + " was not rejected.");
} elseif (error.name !== "RangeError") { thrownew 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) { thrownew Test262Error("Option fallback value " + fallback + " for property " + property + " was not used; got " + actual + " instead.");
}
} else { if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) { thrownew Test262Error("Invalid value " + actual + " returned for property " + property + ".");
}
}
}
}
}
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) { thrownew 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) { thrownew Test262Error("Formatted value for " + input + ", " +
format.resolvedOptions().locale + " and options " +
JSON.stringify(options) + " is " + actual + "; expected " + expected + ".");
}
});
}
});
});
}
var result = components[component]; if (result === undefined) { thrownew Test262Error("Internal error: No values defined for date-time component " + component + ".");
} return result;
}
// Only "en" is supported. const locale = "en"; const numberingSystem = "latn"; const timeSeparator = ":";
let result = [];
let needSeparator = false;
let displayNegativeSign = true;
for (let unit of units) { // Absent units default to zero.
let value = duration[unit] ?? 0;
let style = options[unit];
let display = options[unit + "Display"];
// NumberFormat requires singular unit names.
let numberFormatUnit = unit.slice(0, -1);
// Compute the matching NumberFormat options.
let nfOpts = Object.create(null);
// Numeric seconds and sub-seconds are combined into a single value.
let done = false; if (unit === "seconds" || unit === "milliseconds" || unit === "microseconds") {
let nextStyle = options[units[units.indexOf(unit) + 1]]; if (nextStyle === "numeric") { if (unit === "seconds") {
value = durationToFractional(duration, 9);
} elseif (unit === "milliseconds") {
value = durationToFractional(duration, 6);
} else {
value = durationToFractional(duration, 3);
}
// Display zero numeric minutes when seconds will be displayed.
let displayRequired = false; if (unit === "minutes" && needSeparator) {
displayRequired = options.secondsDisplay === "always" ||
(duration.seconds ?? 0) !== 0 ||
(duration.milliseconds ?? 0) !== 0 ||
(duration.microseconds ?? 0) !== 0 ||
(duration.nanoseconds ?? 0) !== 0;
}
// "auto" display omits zero units. if (value !== 0 || display !== "auto" || displayRequired) { // Display only the first negative value. if (displayNegativeSign) {
displayNegativeSign = false;
// Set to negative zero to ensure the sign is displayed. if (value === 0) {
let negative = units.some(unit => (duration[unit] ?? 0) < 0); if (negative) {
value = -0;
}
}
} else {
nfOpts.signDisplay = "never";
}
nfOpts.numberingSystem = options.numberingSystem;
// If the value is formatted as a 2-digit numeric value. if (style === "2-digit") {
nfOpts.minimumIntegerDigits = 2;
}
// If the value is formatted as a standalone unit. if (style !== "numeric" && style !== "2-digit") {
nfOpts.style = "unit";
nfOpts.unit = numberFormatUnit;
nfOpts.unitDisplay = style;
} else {
nfOpts.useGrouping = false;
}
let nf = new Intl.NumberFormat(locale, nfOpts);
let list; if (!needSeparator) {
list = [];
} else {
list = result[result.length - 1];
// Prepend the time separator before the formatted number.
list.push({
type: "literal",
value: timeSeparator,
});
}
// Format the numeric value.
let parts = nf.formatToParts(value);
// Add |numberFormatUnit| to the formatted number. for (let {value, type} of parts) {
list.push({type, value, unit: numberFormatUnit});
}
if (!needSeparator) { // Prepend the separator before the next numeric unit. if (style === "2-digit" || style === "numeric") {
needSeparator = true;
}
// Append the formatted number to |result|.
result.push(list);
}
}
if (done) { break;
}
}
let listStyle = options.style; if (listStyle === "digital") {
listStyle = "short";
}
let lf = new Intl.ListFormat(locale, {
type: "unit",
style: listStyle,
});
// 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;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.