diff --git a/features.txt b/features.txt index cfe2853a6c..7b3c74a5fe 100644 --- a/features.txt +++ b/features.txt @@ -77,6 +77,10 @@ numeric-separator-literal String.prototype.matchAll Symbol.matchAll +# Intl.Locale +# https://github.com/tc39/proposal-intl-locale +Intl.Locale + # Standard language features # # Language features that have been included in a published version of the diff --git a/test/intl402/Locale/constructor-newtarget.js b/test/intl402/Locale/constructor-newtarget.js new file mode 100644 index 0000000000..a7246d0cbf --- /dev/null +++ b/test/intl402/Locale/constructor-newtarget.js @@ -0,0 +1,15 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Verifies the NewTarget check for Intl.Locale. +info: | + Intl.Locale( tag [, options] ) + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Intl.Locale] +---*/ + +assert.throws(TypeError, () => Intl.Locale()); +assert.throws(TypeError, () => Intl.Locale("en")); diff --git a/test/intl402/Locale/constructor-options.js b/test/intl402/Locale/constructor-options.js new file mode 100644 index 0000000000..32e7a8443d --- /dev/null +++ b/test/intl402/Locale/constructor-options.js @@ -0,0 +1,258 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks error cases for the options argument to the Locale + constructor. +info: | + Intl.Locale( tag [, options] ) + 10. If options is undefined, then + 11. Else + a. Let options be ? ToObject(options). + 12. Set tag to ? ApplyOptionsToTag(tag, options). + 14. Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined). + 15. If calendar is not undefined, then + a. If calendar does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception. + 16. Set opt.[[ca]] to calendar. + + ApplyOptionsToTag( tag, options ) + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + 3. Let language be ? GetOption(options, "language", "string", undefined, undefined). + 4. If language is not undefined, then + a. If language does not match the language production, throw a RangeError exception. + 5. Let script be ? GetOption(options, "script", "string", undefined, undefined). + 6. If script is not undefined, then + a. If script does not match the script production, throw a RangeError exception. + 7. Let region be ? GetOption(options, "region", "string", undefined, undefined). + 8. If region is not undefined, then + a. If region does not match the region production, throw a RangeError exception. + 9. If tag matches the langtag production, then + a. If language is not undefined, then + i. Set tag to tag with the substring corresponding to the language production replaced by the string language. + b. If script is not undefined, then + i. If tag does not contain a script production, then + 1. Set tag to the concatenation of the language production of tag, "-", script, and the rest of tag. + ii. Else, + 1. Set tag to tag with the substring corresponding to the script production replaced by the string script. + c. If region is not undefined, then + i. If tag does not contain a region production, then + 1. Set tag to the concatenation of the language production of tag, the substring corresponding to the "-" script production if present, "-", region, and the rest of tag. + ii. Else, + 1. Set tag to tag with the substring corresponding to the region production replaced by the string region. + 10. Return CanonicalizeLanguageTag(tag). +includes: [testIntl.js, compareArray.js] +features: [Intl.Locale] +---*/ + +// Intl.Locale step 11.a. +assert.throws(TypeError, function() { new Intl.Locale("en", null) }) + + +// ApplyOptionsToTag step 2. +for (const invalidTag of getInvalidLanguageTags()) { + assert.throws(RangeError, function() { + new Intl.Locale(invalidTag) + }, "Language tag: " + invalidTag); +} + + +// ApplyOptionsToTag step 3, 9.a.i. +const validLanguageOptions = [ + [undefined, "en"], + [null, "null"], + ["zh-cmn", "cmn"], + ["ZH-CMN", "cmn"], + ["abcd", "abcd"], + ["abcde", "abcde"], + ["abcdef", "abcdef"], + ["abcdefg", "abcdefg"], + ["abcdefgh", "abcdefgh"], + [{ toString() { return "de" } }, "de"], +]; +for (const [option, expected] of validLanguageOptions) { + assert.sameValue(new Intl.Locale("en", { + language: option, + }).toString(), expected); +} + + +// ApplyOptionsToTag step 4.a. +/* + language = 2*3ALPHA ; shortest ISO 639 code + ["-" extlang] ; sometimes followed by + ; extended language subtags + / 4ALPHA ; or reserved for future use + / 5*8ALPHA ; or registered language subtag + + extlang = 3ALPHA ; selected ISO 639 codes + *2("-" 3ALPHA) ; permanently reserved +*/ +const invalidLanguageOptions = [ + "", + "a", + "ab7", + "notalanguage", + "undefined", + + // Value contains more than just the 'language' production. + "fr-Latn", + "fr-FR", + "sa-vaidika", + "fr-a-asdf", + "fr-x-private", + + // Irregular grandfathered language tag. + "i-klingon", + + // Regular grandfathered language tag. + "zh-Hant", + + // Reserved with extended language subtag + "abcd-US", + "abcde-US", + "abcdef-US", + "abcdefg-US", + "abcdefgh-US", + + 7, +]; +for (const invalidLanguageOption of invalidLanguageOptions) { + assert.throws(RangeError, () => new Intl.Locale("en", {language: invalidLanguageOption})); +} + + +// ApplyOptionsToTag step 5, 9.b. +const validScriptOptions = [ + [null, "en-Null"], + ["bali", "en-Bali"], + ["Bali", "en-Bali"], + ["bALI", "en-BALI"], // TODO REVIEW: is this the correct case regularization? + [{ toString() { return "Brai" } }, "en-Brai"], +]; +for (const [option, expected] of validScriptOptions) { + assert.sameValue(new Intl.Locale("en", { + script: option, + }).toString(), expected); + assert.sameValue(new Intl.Locale("en-Cyrl", { + script: option, + }).toString(), expected); +} + + +// ApplyOptionsToTag step 6.a. +/* + script = 4ALPHA ; ISO 15924 code +*/ +const invalidScriptOptions = [ + "", + "a", + "ab", + "abc", + "abc7", + "notascript", + "undefined", + "Bal\u0130", + "Bal\u0131", + + // Value contains more than just the 'script' production. + "ary-Arab", + "Latn-SA", + "Latn-vaidika", + "Latn-a-asdf", + "Latn-x-private", + + 7, +]; +for (const invalidScriptOption of invalidScriptOptions) { + assert.throws(RangeError, () => new Intl.Locale("en", {script: invalidScriptOption})); +} + + +// ApplyOptionsToTag step 7, 9.c. +const validRegionOptions = [ + ["FR", "en-FR"], + ["554", "en-554"], + [554, "en-554"], +]; +for (const [option, expected] of validRegionOptions) { + assert.sameValue(new Intl.Locale("en", { + region: option, + }).toString(), expected); + assert.sameValue(new Intl.Locale("en-US", { + region: option, + }).toString(), expected); +} + + +// ApplyOptionsToTag step 8.a. +/* + region = 2ALPHA ; ISO 3166-1 code + / 3DIGIT ; UN M.49 code +*/ +const invalidRegionOptions = [ + "", + "a", + "abc", + "a7", + + // Value cannot be parsed as a 'region' production. + "notaregion", + + // Value contains more than just the 'region' production. + "SA-vaidika", + "SA-a-asdf", + "SA-x-private", + + // Value contains more than just the 'script' production. + "ary-Arab", + "Latn-SA", + "Latn-vaidika", + "Latn-a-asdf", + "Latn-x-private", + + 7, +]; +for (const invalidRegionOption of invalidRegionOptions) { + assert.throws(RangeError, () => new Intl.Locale("en", {region: invalidRegionOption})); +} + + +// Intl.Locale step 14. +const validCalendarOptions = [ + ["abc", "en-u-ca-abc"], + ["abcd", "en-u-ca-abcd"], + ["abcde", "en-u-ca-abcde"], + ["abcdef", "en-u-ca-abcdef"], + ["abcdefg", "en-u-ca-abcdefg"], + ["abcdefgh", "en-u-ca-abcdefgh"], + ["12345678", "en-u-ca-12345678"], + ["1234abcd", "en-u-ca-1234abcd"], + ["1234abcd-abc123", "en-u-ca-1234abcd-abc123"], +]; +for (const [option, expected] of validCalendarOptions) { + assert.sameValue(new Intl.Locale("en", { + calendar: option, + }).toString(), expected); + assert.sameValue(new Intl.Locale("en-u-ca-gregory", { + calendar: option, + }).toString(), expected); +} + + +// Intl.Locale step 15. +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + calendar = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidCalendarOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", +]; +for (const invalidCalendarOption of invalidCalendarOptions) { + assert.throws(RangeError, () => new Intl.Locale("en", {calendar: invalidCalendarOption})); +} diff --git a/test/intl402/Locale/instance-properties.js b/test/intl402/Locale/instance-properties.js new file mode 100644 index 0000000000..8ed25e297e --- /dev/null +++ b/test/intl402/Locale/instance-properties.js @@ -0,0 +1,16 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Verifies the properties of a Locale instance. +info: | + Intl.Locale( tag [, options] ) + 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget, %LocalePrototype%, internalSlotsList). +features: [Intl.Locale] +---*/ + +const value = new Intl.Locale("en"); +assert.sameValue(Object.getPrototypeOf(value), Intl.Locale.prototype); +assert.sameValue(Object.isExtensible(value), true); diff --git a/test/intl402/Locale/invalid-tag-throws-boolean.js b/test/intl402/Locale/invalid-tag-throws-boolean.js new file mode 100644 index 0000000000..1d9f317343 --- /dev/null +++ b/test/intl402/Locale/invalid-tag-throws-boolean.js @@ -0,0 +1,21 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Verifies the type check on the tag argument to Intl.Locale. +info: | + Intl.Locale( tag [, options] ) + 7. If Type(tag) is not String or Object, throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const boolean_values = [ + true, + false, +]; + +for (const boolean_value of boolean_values) { + assert.throws(TypeError, () => new Intl.Locale(boolean_value)); +} diff --git a/test/intl402/Locale/invalid-tag-throws-null.js b/test/intl402/Locale/invalid-tag-throws-null.js new file mode 100644 index 0000000000..c86de2242e --- /dev/null +++ b/test/intl402/Locale/invalid-tag-throws-null.js @@ -0,0 +1,14 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Verifies the type check on the tag argument to Intl.Locale. +info: | + Intl.Locale( tag [, options] ) + 7. If Type(tag) is not String or Object, throw a TypeError exception. +features: [Intl.Locale] +---*/ + +assert.throws(TypeError, () => new Intl.Locale(null)); diff --git a/test/intl402/Locale/invalid-tag-throws-number.js b/test/intl402/Locale/invalid-tag-throws-number.js new file mode 100644 index 0000000000..62c35edf21 --- /dev/null +++ b/test/intl402/Locale/invalid-tag-throws-number.js @@ -0,0 +1,20 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Verifies the type check on the tag argument to Intl.Locale. +info: | + Intl.Locale( tag [, options] ) + 7. If Type(tag) is not String or Object, throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const invalid_type_values = [ + 0, 1.5, Infinity, -Infinity, NaN, +]; + +for (const invalid_type_value of invalid_type_values) { + assert.throws(TypeError, () => new Intl.Locale(invalid_type_value)); +} diff --git a/test/intl402/Locale/invalid-tag-throws-symbol.js b/test/intl402/Locale/invalid-tag-throws-symbol.js new file mode 100644 index 0000000000..45ed1b6391 --- /dev/null +++ b/test/intl402/Locale/invalid-tag-throws-symbol.js @@ -0,0 +1,15 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Verifies the type check on the tag argument to Intl.Locale. +info: | + Intl.Locale( tag [, options] ) + 7. If Type(tag) is not String or Object, throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const symbol = Symbol(); +assert.throws(TypeError, () => new Intl.Locale(symbol)); diff --git a/test/intl402/Locale/invalid-tag-throws-undefined.js b/test/intl402/Locale/invalid-tag-throws-undefined.js new file mode 100644 index 0000000000..f4685833bd --- /dev/null +++ b/test/intl402/Locale/invalid-tag-throws-undefined.js @@ -0,0 +1,15 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Verifies the type check on the tag argument to Intl.Locale. +info: | + Intl.Locale( tag [, options] ) + 7. If Type(tag) is not String or Object, throw a TypeError exception. +features: [Intl.Locale] +---*/ + +assert.throws(TypeError, () => new Intl.Locale()); +assert.throws(TypeError, () => new Intl.Locale(undefined)); diff --git a/test/intl402/Locale/length.js b/test/intl402/Locale/length.js new file mode 100644 index 0000000000..c3bd3dd935 --- /dev/null +++ b/test/intl402/Locale/length.js @@ -0,0 +1,20 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks the "length" property of the Locale constructor. +info: | + Unless specified otherwise in this document, the objects, functions, and constructors described in this standard are subject to the generic requirements and restrictions specified for standard built-in ECMAScript objects in the ECMAScript 2019 Language Specification, 10th edition, clause 17, or successor. + The Locale constructor is a standard built-in property of the Intl object. + Every built-in function object, including constructors, has a length property whose value is an integer. Unless otherwise specified, this value is equal to the largest number of named arguments shown in the subclause headings for the function description. Optional parameters (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form «...name») are not included in the default argument count. + Unless otherwise specified, the length property of a built-in function object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale, "length"); +assert.sameValue(propdesc.writable, false); +assert.sameValue(propdesc.enumerable, false); +assert.sameValue(propdesc.configurable, true); +assert.sameValue(propdesc.value, 1); diff --git a/test/intl402/Locale/name.js b/test/intl402/Locale/name.js new file mode 100644 index 0000000000..562a9253db --- /dev/null +++ b/test/intl402/Locale/name.js @@ -0,0 +1,19 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks the "name" property of the Locale constructor. +info: | + Unless specified otherwise in this document, the objects, functions, and constructors described in this standard are subject to the generic requirements and restrictions specified for standard built-in ECMAScript objects in the ECMAScript 2019 Language Specification, 10th edition, clause 17, or successor. + Every built-in function object, including constructors, that is not identified as an anonymous function has a name property whose value is a String. Unless otherwise specified, this value is the name that is given to the function in this specification. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale, "name"); +assert.sameValue(propdesc.writable, false); +assert.sameValue(propdesc.enumerable, false); +assert.sameValue(propdesc.configurable, true); +assert.sameValue(propdesc.value, "Locale"); diff --git a/test/intl402/Locale/prop-desc.js b/test/intl402/Locale/prop-desc.js new file mode 100644 index 0000000000..5a086e66fc --- /dev/null +++ b/test/intl402/Locale/prop-desc.js @@ -0,0 +1,22 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks the properties of the Locale constructor. +info: | + Every other data property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. + Unless specified otherwise in this document, the objects, functions, and constructors described in this standard are subject to the generic requirements and restrictions specified for standard built-in ECMAScript objects in the ECMAScript 2019 Language Specification, 10th edition, clause 17, or successor. + The Locale constructor is a standard built-in property of the Intl object. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl, "Locale"); +assert.sameValue(propdesc.writable, true); +assert.sameValue(propdesc.enumerable, false); +assert.sameValue(propdesc.configurable, true); +assert.sameValue(propdesc.value, Intl.Locale); + +assert.sameValue(typeof Intl.Locale, "function"); +assert.sameValue(Object.getPrototypeOf(Intl.Locale), Function.prototype); diff --git a/test/intl402/Locale/prototype/constructor.js b/test/intl402/Locale/prototype/constructor.js new file mode 100644 index 0000000000..036bccbda7 --- /dev/null +++ b/test/intl402/Locale/prototype/constructor.js @@ -0,0 +1,23 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks the "constructor" property of the Locale prototype object. +info: | + Intl.Locale.prototype.constructor + + The initial value of Intl.Locale.prototype.constructor is %Locale%. + + Unless specified otherwise in this document, the objects, functions, and constructors described in this standard are subject to the generic requirements and restrictions specified for standard built-in ECMAScript objects in the ECMAScript 2019 Language Specification, 10th edition, clause 17, or successor. + + Every other data property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "constructor"); +assert.sameValue(propdesc.writable, true); +assert.sameValue(propdesc.enumerable, false); +assert.sameValue(propdesc.configurable, true); +assert.sameValue(propdesc.value, Intl.Locale); diff --git a/test/intl402/Locale/prototype/maximize-propdesc.js b/test/intl402/Locale/prototype/maximize-propdesc.js new file mode 100644 index 0000000000..6108115415 --- /dev/null +++ b/test/intl402/Locale/prototype/maximize-propdesc.js @@ -0,0 +1,21 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks the "maximize" property of the Locale prototype object. +info: | + Intl.Locale.prototype.maximize () + + Unless specified otherwise in this document, the objects, functions, and constructors described in this standard are subject to the generic requirements and restrictions specified for standard built-in ECMAScript objects in the ECMAScript 2019 Language Specification, 10th edition, clause 17, or successor. + + Every other data property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "maximize"); +assert.sameValue(propdesc.writable, true); +assert.sameValue(propdesc.enumerable, false); +assert.sameValue(propdesc.configurable, true); +assert.sameValue(typeof propdesc.value, "function"); diff --git a/test/intl402/Locale/prototype/prop-desc.js b/test/intl402/Locale/prototype/prop-desc.js new file mode 100644 index 0000000000..fc464eecee --- /dev/null +++ b/test/intl402/Locale/prototype/prop-desc.js @@ -0,0 +1,22 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks the "prototype" property of the Locale constructor. +info: | + Intl.Locale.prototype + + The value of Intl.Locale.prototype is %LocalePrototype%. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale, "prototype"); +assert.sameValue(propdesc.writable, false); +assert.sameValue(propdesc.enumerable, false); +assert.sameValue(propdesc.configurable, false); +assert.sameValue(typeof propdesc.value, "object"); +assert.notSameValue(propdesc.value, null); diff --git a/test/intl402/Locale/prototype/toStringTag.js b/test/intl402/Locale/prototype/toStringTag.js new file mode 100644 index 0000000000..8828d2a69c --- /dev/null +++ b/test/intl402/Locale/prototype/toStringTag.js @@ -0,0 +1,21 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: pending +description: > + Checks the @@toStringTag property of the Locale prototype object. +info: | + Intl.Locale.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.Locale". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Intl.Locale, Symbol.toStringTag] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, Symbol.toStringTag); +assert.sameValue(propdesc.writable, false); +assert.sameValue(propdesc.enumerable, false); +assert.sameValue(propdesc.configurable, true); +assert.sameValue(propdesc.value, "Intl.Locale");