diff options
Diffstat (limited to 'js/src/tests/test262/intl402')
1120 files changed, 40381 insertions, 0 deletions
diff --git a/js/src/tests/test262/intl402/Array/browser.js b/js/src/tests/test262/intl402/Array/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Array/browser.js diff --git a/js/src/tests/test262/intl402/Array/prototype/browser.js b/js/src/tests/test262/intl402/Array/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Array/prototype/browser.js diff --git a/js/src/tests/test262/intl402/Array/prototype/shell.js b/js/src/tests/test262/intl402/Array/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Array/prototype/shell.js diff --git a/js/src/tests/test262/intl402/Array/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Array/prototype/toLocaleString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Array/prototype/toLocaleString/browser.js diff --git a/js/src/tests/test262/intl402/Array/prototype/toLocaleString/calls-toLocaleString-number-elements.js b/js/src/tests/test262/intl402/Array/prototype/toLocaleString/calls-toLocaleString-number-elements.js new file mode 100644 index 0000000000..bd1a389a64 --- /dev/null +++ b/js/src/tests/test262/intl402/Array/prototype/toLocaleString/calls-toLocaleString-number-elements.js @@ -0,0 +1,19 @@ +// Copyright (C) 2018 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-array.prototype.tolocalestring +description: > + Ensure "toLocaleString" is called with locale and options on number elements. +---*/ + +var n = 0; + +var locale = "th-u-nu-thai"; +var options = { + minimumFractionDigits: 3 +}; + +assert.sameValue([n].toLocaleString(locale, options), n.toLocaleString(locale, options)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Array/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Array/prototype/toLocaleString/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Array/prototype/toLocaleString/shell.js diff --git a/js/src/tests/test262/intl402/Array/shell.js b/js/src/tests/test262/intl402/Array/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Array/shell.js diff --git a/js/src/tests/test262/intl402/BigInt/browser.js b/js/src/tests/test262/intl402/BigInt/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/browser.js diff --git a/js/src/tests/test262/intl402/BigInt/prototype/browser.js b/js/src/tests/test262/intl402/BigInt/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/browser.js diff --git a/js/src/tests/test262/intl402/BigInt/prototype/shell.js b/js/src/tests/test262/intl402/BigInt/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/shell.js diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/browser.js diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/builtin.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/builtin.js new file mode 100644 index 0000000000..c3c87d4b85 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/builtin.js @@ -0,0 +1,31 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: > + Tests that BigInt.prototype.toLocaleString meets the requirements + for built-in objects defined by the introduction of chapter 17 of + the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct, BigInt] +---*/ + +assert.sameValue(Object.prototype.toString.call(BigInt.prototype.toLocaleString), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(BigInt.prototype.toLocaleString), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(BigInt.prototype.toLocaleString), Function.prototype); + +assert.sameValue(BigInt.prototype.toLocaleString.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(BigInt.prototype.toLocaleString), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/de-DE.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/de-DE.js new file mode 100644 index 0000000000..b92250d0c2 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/de-DE.js @@ -0,0 +1,25 @@ +// Copyright (C) 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: Checks basic behavior for BigInt.prototype.toLocaleString. +locale: [de-DE] +features: [BigInt] +---*/ + +const tests = [ + [0n, undefined, "0"], + [-0n, undefined, "0"], + [88776655n, { "maximumSignificantDigits": 4 }, "88.780.000"], + [88776655n, { "maximumSignificantDigits": 4, "style": "percent" }, "8.878.000.000\u00a0%"], + [88776655n, { "minimumFractionDigits": 3 }, "88.776.655,000"], + [90071992547409910n, undefined, "90.071.992.547.409.910"], +]; + +for (const [bigint, options, expected] of tests) { + const result = bigint.toLocaleString("de-DE", options); + assert.sameValue(result, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/default-options-object-prototype.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/default-options-object-prototype.js new file mode 100644 index 0000000000..893e074082 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/default-options-object-prototype.js @@ -0,0 +1,22 @@ +// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Monkey-patching Object.prototype does not change the default + options for NumberFormat as a null prototype is used. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 1. If _options_ is *undefined*, then + 1. Let _options_ be ObjectCreate(*null*). +locale: [en-US] +features: [BigInt] +---*/ + +Object.prototype.useGrouping = false; +assert.sameValue(12345n.toLocaleString("en-US"), "12,345"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/en-US.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/en-US.js new file mode 100644 index 0000000000..96a0824ba9 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/en-US.js @@ -0,0 +1,25 @@ +// Copyright (C) 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: Checks basic behavior for BigInt.prototype.toLocaleString. +locale: [en-US] +features: [BigInt] +---*/ + +const tests = [ + [0n, undefined, "0"], + [-0n, undefined, "0"], + [88776655n, { "maximumSignificantDigits": 4 }, "88,780,000"], + [88776655n, { "maximumSignificantDigits": 4, "style": "percent" }, "8,878,000,000%"], + [88776655n, { "minimumFractionDigits": 3 }, "88,776,655.000"], + [90071992547409910n, undefined, "90,071,992,547,409,910"], +]; + +for (const [bigint, options, expected] of tests) { + const result = bigint.toLocaleString("en-US", options); + assert.sameValue(result, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/length.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/length.js new file mode 100644 index 0000000000..6653858f1b --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/length.js @@ -0,0 +1,36 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: > + BigInt.prototype.toLocaleString.length is 0. +info: | + BigInt.prototype.toLocaleString ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +features: [BigInt] +---*/ + +verifyProperty(BigInt.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/name.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/name.js new file mode 100644 index 0000000000..cab1cf03f4 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/name.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: > + BigInt.prototype.toLocaleString.name is toLocaleString. +info: | + BigInt.prototype.toLocaleString ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + Every built-in function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. For functions that are specified as properties of objects, + the name value is the property name string used to access the function. + + Unless otherwise specified, the name property of a built-in function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. + +includes: [propertyHelper.js] +features: [BigInt] +---*/ + +verifyProperty(BigInt.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/prop-desc.js new file mode 100644 index 0000000000..2b2c64d7d7 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,32 @@ +// Copyright (C) 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: Checks the "toLocaleString" property of the BigInt prototype object. +info: | + BigInt.prototype.toLocaleString ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +features: [BigInt] +---*/ + +assert.sameValue( + typeof BigInt.prototype.toLocaleString, + "function", + "typeof BigInt.prototype.toLocaleString is function" +); + +verifyProperty(BigInt.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/returns-same-results-as-NumberFormat.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/returns-same-results-as-NumberFormat.js new file mode 100644 index 0000000000..5083fe05f5 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/returns-same-results-as-NumberFormat.js @@ -0,0 +1,49 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: > + Tests that BigInt.prototype.toLocaleString produces the same + results as Intl.BigIntFormat. +features: [BigInt] +---*/ + +var inputs = [ + 0n, + -0n, + 1n, + -1n, + 123n, + -123n, + 12345n, + -12345n, + 12344501000000000000000000000000000n, + -12344501000000000000000000000000000n, +]; +var localesInputs = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]]; +var optionsInputs = [ + undefined, + {style: "percent"}, + {style: "currency", currency: "EUR", currencyDisplay: "symbol"}, + {style: "currency", currency: "IQD", currencyDisplay: "symbol"}, + {style: "currency", currency: "KMF", currencyDisplay: "symbol"}, + {style: "currency", currency: "CLF", currencyDisplay: "symbol"}, + {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3} +]; + +for (const locales of localesInputs) { + for (const options of optionsInputs) { + const optionsString = options ? JSON.stringify(options) : String(options); + const referenceNumberFormat = new Intl.NumberFormat(locales, options); + for (const input of inputs) { + const referenceFormatted = referenceNumberFormat.format(input); + const formatted = input.toLocaleString(locales, options); + assert.sameValue(formatted, referenceFormatted, + `(Testing with locales ${locales}; options ${optionsString}.)`); + } + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/taint-Intl-NumberFormat.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/taint-Intl-NumberFormat.js new file mode 100644 index 0000000000..f918e5537c --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/taint-Intl-NumberFormat.js @@ -0,0 +1,17 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: > + Tests that Number.prototype.toLocaleString uses the standard + built-in Intl.NumberFormat constructor. +includes: [testIntl.js] +features: [BigInt] +---*/ + +taintDataProperty(Intl, "NumberFormat"); +0n.toLocaleString(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/this-value-invalid.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/this-value-invalid.js new file mode 100644 index 0000000000..cfc9053033 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/this-value-invalid.js @@ -0,0 +1,31 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: Tests that toLocaleString handles "thisBigIntValue" correctly. +features: [BigInt] +---*/ + +var invalidValues = [ + undefined, + null, + false, + "5", + Symbol(), + 5, + -1234567.89, + NaN, + -Infinity, + {valueOf: function () { return 5; }}, + {valueOf: function () { return 5n; }}, +]; + +for (const value of invalidValues) { + assert.throws(TypeError, function() { + BigInt.prototype.toLocaleString.call(value); + }, `BigInt.prototype.toLocaleString did not throw with this = ${String(value)}.`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/throws-same-exceptions-as-NumberFormat.js b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/throws-same-exceptions-as-NumberFormat.js new file mode 100644 index 0000000000..f4cb784959 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/prototype/toLocaleString/throws-same-exceptions-as-NumberFormat.js @@ -0,0 +1,50 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-bigint.prototype.tolocalestring +description: > + Tests that BigInt.prototype.toLocaleString throws the same + exceptions as Intl.NumberFormat. +features: [BigInt] +---*/ + +var localesInputs = [null, [NaN], ["i"], ["de_DE"]]; +var optionsInputs = [ + {localeMatcher: null}, + {style: "invalid"}, + {style: "currency"}, + {style: "currency", currency: "ßP"}, + {maximumSignificantDigits: -Infinity} +]; + +for (const locales of localesInputs) { + var referenceError, error; + try { + var format = new Intl.NumberFormat(locales); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.NumberFormat for locales " + locales + "."); + + assert.throws(referenceError.constructor, function() { + var result = 0n.toLocaleString(locales); + }, "BigInt.prototype.toLocaleString didn't throw exception for locales " + locales + "."); +} + +for (const options of optionsInputs) { + var referenceError, error; + try { + var format = new Intl.NumberFormat([], options); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.NumberFormat for options " + JSON.stringify(options) + "."); + + assert.throws(referenceError.constructor, function() { + var result = 0n.toLocaleString([], options); + }, "BigInt.prototype.toLocaleString didn't throw exception for options " + JSON.stringify(options) + "."); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/BigInt/shell.js b/js/src/tests/test262/intl402/BigInt/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/BigInt/shell.js diff --git a/js/src/tests/test262/intl402/Collator/browser.js b/js/src/tests/test262/intl402/Collator/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/browser.js diff --git a/js/src/tests/test262/intl402/Collator/builtin.js b/js/src/tests/test262/intl402/Collator/builtin.js new file mode 100644 index 0000000000..ea9bf9465f --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/builtin.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.1_L15 +description: > + Tests that Intl.Collator meets the requirements for built-in + objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.Collator), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.Collator), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.Collator), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/constructor-options-throwing-getters.js b/js/src/tests/test262/intl402/Collator/constructor-options-throwing-getters.js new file mode 100644 index 0000000000..ed2993524c --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/constructor-options-throwing-getters.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializecollator +description: Checks the propagation of exceptions from the options for the Collator constructor. +---*/ + +function CustomError() {} + +const options = [ + "usage", + "localeMatcher", + "collation", + "numeric", + "caseFirst", + "sensitivity", + "ignorePunctuation", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.Collator("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/default-options-object-prototype.js b/js/src/tests/test262/intl402/Collator/default-options-object-prototype.js new file mode 100644 index 0000000000..7b699fe36a --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/default-options-object-prototype.js @@ -0,0 +1,22 @@ +// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializecollator +description: > + Monkey-patching Object.prototype does not change the default + options for Collator as a null prototype is used. +info: | + InitializeCollator ( collator, locales, options ) + + 1. If _options_ is *undefined*, then + 1. Let _options_ be ObjectCreate(*null*). +---*/ + +let defaultSensitivity = new Intl.Collator("en").resolvedOptions().sensitivity; + +Object.prototype.sensitivity = "base"; +let collator = new Intl.Collator("en"); +assert.sameValue(collator.resolvedOptions().sensitivity, defaultSensitivity); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/ignore-invalid-unicode-ext-values.js b/js/src/tests/test262/intl402/Collator/ignore-invalid-unicode-ext-values.js new file mode 100644 index 0000000000..0e36be1160 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/ignore-invalid-unicode-ext-values.js @@ -0,0 +1,48 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.2.3_b +description: > + Tests that Intl.Collator does not accept Unicode locale extension + keys and values that are not allowed. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +var testArray = [ + "hello", "你好", "こんにちは", + "pêche", "peché", "1", "9", "10", + "ụ\u031B", "u\u031B\u0323", "ư\u0323", "u\u0323\u031B", + "Å", "Å", "A\u030A" +]; + +var defaultCollator = new Intl.Collator(); +var defaultOptions = defaultCollator.resolvedOptions(); +var defaultOptionsJSON = JSON.stringify(defaultOptions); +var defaultLocale = defaultOptions.locale; +var defaultSortedArray = testArray.slice(0).sort(defaultCollator.compare); + +var keyValues = { + "co": ["standard", "search", "invalid"], + "ka": ["noignore", "shifted", "invalid"], + "kb": ["true", "false", "invalid"], + "kc": ["true", "false", "invalid"], + "kh": ["true", "false", "invalid"], + "kk": ["true", "false", "invalid"], + "kr": ["latn-hira-hani", "hani-hira-latn", "invalid"], + "ks": ["level1", "level2", "level3", "level4", "identic", "invalid"], + "vt": ["1234-5678-9abc-edf0", "invalid"] +}; + +Object.getOwnPropertyNames(keyValues).forEach(function (key) { + keyValues[key].forEach(function (value) { + var collator = new Intl.Collator([defaultLocale + "-u-" + key + "-" + value]); + var options = collator.resolvedOptions(); + assert.sameValue(options.locale, defaultLocale, "Locale " + options.locale + " is affected by key " + key + "; value " + value + "."); + assert.sameValue(JSON.stringify(options), defaultOptionsJSON, "Resolved options " + JSON.stringify(options) + " are affected by key " + key + "; value " + value + "."); + assert.compareArray(testArray.sort(collator.compare), defaultSortedArray); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/instance-proto-and-extensible.js b/js/src/tests/test262/intl402/Collator/instance-proto-and-extensible.js new file mode 100644 index 0000000000..ba37de24f4 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/instance-proto-and-extensible.js @@ -0,0 +1,19 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.3 +description: > + Tests that objects constructed by Intl.Collator have the specified + internal properties. +author: Norbert Lindenberg +---*/ + +var obj = new Intl.Collator(); + +var actualPrototype = Object.getPrototypeOf(obj); +assert.sameValue(actualPrototype, Intl.Collator.prototype, "Prototype of object constructed by Intl.Collator isn't Intl.Collator.prototype."); + +assert(Object.isExtensible(obj), "Object constructed by Intl.Collator must be extensible."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/legacy-regexp-statics-not-modified.js b/js/src/tests/test262/intl402/Collator/legacy-regexp-statics-not-modified.js new file mode 100644 index 0000000000..9d1b16d6e5 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/legacy-regexp-statics-not-modified.js @@ -0,0 +1,17 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_a +description: > + Tests that constructing a Collator doesn't create or modify + unwanted properties on the RegExp constructor. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testForUnwantedRegExpChanges(function () { + new Intl.Collator("de-DE-u-co-phonebk"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/length.js b/js/src/tests/test262/intl402/Collator/length.js new file mode 100644 index 0000000000..335bcb2b96 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator +description: > + Intl.Collator.length is 0. +info: | + Intl.Collator ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.Collator.length, 0); + +verifyNotEnumerable(Intl.Collator, "length"); +verifyNotWritable(Intl.Collator, "length"); +verifyConfigurable(Intl.Collator, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/missing-unicode-ext-value-defaults-to-true.js b/js/src/tests/test262/intl402/Collator/missing-unicode-ext-value-defaults-to-true.js new file mode 100644 index 0000000000..29be350876 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/missing-unicode-ext-value-defaults-to-true.js @@ -0,0 +1,27 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.5_11_g_ii_2 +description: > + Tests that missing Unicode extension values default to true for + boolean keys. +author: Norbert Lindenberg +---*/ + +var extensions = ["-u-co-phonebk-kn", "-u-kn-co-phonebk", "-u-co-phonebk-kn-true", "-u-kn-true-co-phonebk"]; +extensions.forEach(function (extension) { + var defaultLocale = new Intl.Collator().resolvedOptions().locale; + var collator = new Intl.Collator([defaultLocale + extension], {usage: "sort"}); + var locale = collator.resolvedOptions().locale; + var numeric = collator.resolvedOptions().numeric; + if (numeric !== undefined) { + assert.sameValue(numeric, true, "Default value for \"kn\" should be true, but is " + numeric + "."); + assert.sameValue(locale.indexOf("-kn-false"), -1, "\"kn-false\" is returned in locale, but shouldn't be."); + assert.sameValue(locale.indexOf("-kn-true"), -1, "\"kn-true\" is returned in locale, but shouldn't be."); + assert.sameValue(locale.indexOf("-kn") >= 0, true, "\"kn\" should be returned in locale."); + } +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/name.js b/js/src/tests/test262/intl402/Collator/name.js new file mode 100644 index 0000000000..36dd6f5885 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Collator +description: > + Intl.Collator.name is "Collator". +info: | + 10.1.2 Intl.Collator ([ locales [ , options ]]) + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.Collator.name, "Collator"); + +verifyNotEnumerable(Intl.Collator, "name"); +verifyNotWritable(Intl.Collator, "name"); +verifyConfigurable(Intl.Collator, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/numeric-and-caseFirst.js b/js/src/tests/test262/intl402/Collator/numeric-and-caseFirst.js new file mode 100644 index 0000000000..6953fe1b08 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/numeric-and-caseFirst.js @@ -0,0 +1,58 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_19_c +description: > + Tests that the options numeric and caseFirst can be set through + either the locale or the options. +author: Norbert Lindenberg +---*/ + +var options = [ + {key: "kn", property: "numeric", type: "boolean", values: [true, false]}, + {key: "kf", property: "caseFirst", type: "string", values: ["upper", "lower", "false"]} +]; + +options.forEach(function (option) { + var defaultLocale = new Intl.Collator().resolvedOptions().locale; + var collator, opt, result; + + // find out which values are supported for a property in the default locale + var supportedValues = []; + option.values.forEach(function (value) { + opt = {}; + opt[option.property] = value; + collator = new Intl.Collator([defaultLocale], opt); + result = collator.resolvedOptions()[option.property]; + if (result !== undefined && supportedValues.indexOf(result) === -1) { + supportedValues.push(result); + } + }); + + // verify that the supported values can also be set through the locale + supportedValues.forEach(function (value) { + collator = new Intl.Collator([defaultLocale + "-u-" + option.key + "-" + value]); + result = collator.resolvedOptions()[option.property]; + assert.sameValue(result, value, "Property " + option.property + " couldn't be set through locale extension key " + option.key + "."); + }); + + // verify that the options setting overrides the locale setting + supportedValues.forEach(function (value) { + var otherValue; + option.values.forEach(function (possibleValue) { + if (possibleValue !== value) { + otherValue = possibleValue; + } + }); + if (otherValue !== undefined) { + opt = {}; + opt[option.property] = value; + collator = new Intl.Collator([defaultLocale + "-u-" + option.key + "-" + otherValue], opt); + result = collator.resolvedOptions()[option.property]; + assert.sameValue(result, value, "Options value for property " + option.property + " doesn't override locale extension key " + option.key + "."); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prop-desc.js b/js/src/tests/test262/intl402/Collator/prop-desc.js new file mode 100644 index 0000000000..a7240fbdd1 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator-intro +description: > + "Collator" property of Intl. +info: | + Intl.Collator (...) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl, "Collator"); +verifyWritable(Intl, "Collator"); +verifyConfigurable(Intl, "Collator"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/Collator/proto-from-ctor-realm.js new file mode 100644 index 0000000000..473b816dad --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/proto-from-ctor-realm.js @@ -0,0 +1,60 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.Collator ( [ locales [ , options ] ] ) + + 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget. + ... + 5. Let collator be ? OrdinaryCreateFromConstructor(newTarget, "%CollatorPrototype%", internalSlotsList). + 6. Return ? InitializeCollator(collator, locales, options). + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var col; + +newTarget.prototype = undefined; +col = Reflect.construct(Intl.Collator, [], newTarget); +assert.sameValue(Object.getPrototypeOf(col), other.Intl.Collator.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +col = Reflect.construct(Intl.Collator, [], newTarget); +assert.sameValue(Object.getPrototypeOf(col), other.Intl.Collator.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = true; +col = Reflect.construct(Intl.Collator, [], newTarget); +assert.sameValue(Object.getPrototypeOf(col), other.Intl.Collator.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = ''; +col = Reflect.construct(Intl.Collator, [], newTarget); +assert.sameValue(Object.getPrototypeOf(col), other.Intl.Collator.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +col = Reflect.construct(Intl.Collator, [], newTarget); +assert.sameValue(Object.getPrototypeOf(col), other.Intl.Collator.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = 1; +col = Reflect.construct(Intl.Collator, [], newTarget); +assert.sameValue(Object.getPrototypeOf(col), other.Intl.Collator.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/browser.js b/js/src/tests/test262/intl402/Collator/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/browser.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/builtin.js b/js/src/tests/test262/intl402/Collator/prototype/builtin.js new file mode 100644 index 0000000000..d43c58095d --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/builtin.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.3_L15 +description: > + Tests that Intl.Collator.prototype meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +---*/ + +assert(Object.isExtensible(Intl.Collator.prototype), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.Collator.prototype), Object.prototype, + "Built-in prototype objects must have Object.prototype as their prototype."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/bound-to-collator-instance.js b/js/src/tests/test262/intl402/Collator/prototype/compare/bound-to-collator-instance.js new file mode 100644 index 0000000000..a5d3716700 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/bound-to-collator-instance.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.3.2_1_c +description: Tests that compare function is bound to its Intl.Collator. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +var strings = ["d", "O", "od", "oe", "of", "ö", "o\u0308", "X", "y", "Z", "Z.", "𠮷野家", "吉野家", "!A", "A", "b", "C"]; +var locales = [undefined, ["de"], ["de-u-co-phonebk"], ["en"], ["ja"], ["sv"]]; +var options = [ + undefined, + {usage: "search"}, + {sensitivity: "base", ignorePunctuation: true} +]; + +locales.forEach(function (locales) { + options.forEach(function (options) { + var collatorObj = new Intl.Collator(locales, options); + var compareFunc = collatorObj.compare; + var referenceSorted = strings.slice(); + referenceSorted.sort(function (a, b) { return collatorObj.compare(a, b); }); + var sorted = strings; + sorted.sort(compareFunc); + assert.compareArray(sorted, referenceSorted, + "(Testing with locales " + locales + "; options " + + (options ? JSON.stringify(options) : options) + ".)"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/browser.js b/js/src/tests/test262/intl402/Collator/prototype/compare/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/browser.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/builtin.js b/js/src/tests/test262/intl402/Collator/prototype/compare/builtin.js new file mode 100644 index 0000000000..11ccc40a7b --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/builtin.js @@ -0,0 +1,32 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.3.2_L15 +description: > + Tests that the getter for Intl.Collator.prototype.compare meets + the requirements for built-in objects defined by the introduction + of chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +var compareFn = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare").get; + +assert.sameValue(Object.prototype.toString.call(compareFn), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(compareFn), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(compareFn), Function.prototype); + +assert.sameValue(compareFn.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(compareFn), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/canonically-equivalent-strings.js b/js/src/tests/test262/intl402/Collator/prototype/compare/canonically-equivalent-strings.js new file mode 100644 index 0000000000..a0994462b7 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/canonically-equivalent-strings.js @@ -0,0 +1,69 @@ +// Copyright 2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.3.2_CS_a +description: > + Tests that the function returned by + Intl.Collator.prototype.compare returns 0 when comparing Strings + that are considered canonically equivalent by the Unicode + standard. +author: Norbert Lindenberg +---*/ + +var collator = new Intl.Collator(); +var pairs = [ + // example from Unicode 5.0, section 3.7, definition D70 + ["o\u0308", "ö"], + // examples from Unicode 5.0, chapter 3.11 + ["ä\u0323", "a\u0323\u0308"], + ["a\u0308\u0323", "a\u0323\u0308"], + ["ạ\u0308", "a\u0323\u0308"], + ["ä\u0306", "a\u0308\u0306"], + ["ă\u0308", "a\u0306\u0308"], + // example from Unicode 5.0, chapter 3.12 + ["\u1111\u1171\u11B6", "퓛"], + // examples from UTS 10, Unicode Collation Algorithm + ["Å", "Å"], + ["Å", "A\u030A"], + ["x\u031B\u0323", "x\u0323\u031B"], + ["ự", "ụ\u031B"], + ["ự", "u\u031B\u0323"], + ["ự", "ư\u0323"], + ["ự", "u\u0323\u031B"], + // examples from UAX 15, Unicode Normalization Forms + ["Ç", "C\u0327"], + ["q\u0307\u0323", "q\u0323\u0307"], + ["가", "\u1100\u1161"], + ["Å", "A\u030A"], + ["Ω", "Ω"], + ["Å", "A\u030A"], + ["ô", "o\u0302"], + ["ṩ", "s\u0323\u0307"], + ["ḋ\u0323", "d\u0323\u0307"], + ["ḋ\u0323", "ḍ\u0307"], + ["q\u0307\u0323", "q\u0323\u0307"], + // examples involving supplementary characters from UCD NormalizationTest.txt + ["\uD834\uDD5E", "\uD834\uDD57\uD834\uDD65"], + ["\uD87E\uDC2B", "北"] + +]; +var i; +for (i = 0; i < pairs.length; i++) { + var pair = pairs[i]; + assert.sameValue(collator.compare(pair[0], pair[1]), 0, "Collator.compare considers " + pair[0] + " (" + toU(pair[0]) + ") ≠ " + pair[1] + " (" + toU(pair[1]) + ")."); +} + +function toU(s) { + var result = ""; + var escape = "\\u0000"; + var i; + for (i = 0; i < s.length; i++) { + var hex = s.charCodeAt(i).toString(16); + result += escape.substring(0, escape.length - hex.length) + hex; + } + return result; +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-builtin.js b/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-builtin.js new file mode 100644 index 0000000000..3b6ec70b35 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-builtin.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.3.2_1_a_L15 +description: > + Tests that the function returned by + Intl.Collator.prototype.compare meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +var compareFn = new Intl.Collator().compare; + +assert.sameValue(Object.prototype.toString.call(compareFn), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(compareFn), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(compareFn), Function.prototype); + +assert.sameValue(compareFn.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(compareFn), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-length.js b/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-length.js new file mode 100644 index 0000000000..ca9764bbb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype.compare +description: > + The length of the bound Collator compare function is 2. +info: | + get Intl.Collator.prototype.compare + + ... + 4. If collator.[[BoundCompare]] is undefined, then + a. Let F be a new built-in function object as defined in 10.3.4. + b. Let bc be BoundFunctionCreate(F, collator, « »). + c. Perform ! DefinePropertyOrThrow(bc, "length", PropertyDescriptor {[[Value]]: 2, + [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}). + ... + +includes: [propertyHelper.js] +---*/ + +var compareFn = new Intl.Collator().compare; + +assert.sameValue(compareFn.length, 2); + +verifyNotEnumerable(compareFn, "length"); +verifyNotWritable(compareFn, "length"); +verifyConfigurable(compareFn, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-name.js b/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-name.js new file mode 100644 index 0000000000..234ef6ad27 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/compare-function-name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Collator.prototype.compare +description: > + The bound Collator compare function is an anonymous function. +info: | + 10.3.3 get Intl.Collator.prototype.compare + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +---*/ + +var compareFn = new Intl.Collator().compare; + +verifyProperty(compareFn, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/length.js b/js/src/tests/test262/intl402/Collator/prototype/compare/length.js new file mode 100644 index 0000000000..e4774e2eae --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/length.js @@ -0,0 +1,35 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype.compare +description: > + get Intl.Collator.prototype.compare.length is 0. +info: | + get Intl.Collator.prototype.compare + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare"); + +assert.sameValue(desc.get.length, 0); + +verifyNotEnumerable(desc.get, "length"); +verifyNotWritable(desc.get, "length"); +verifyConfigurable(desc.get, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/name.js b/js/src/tests/test262/intl402/Collator/prototype/compare/name.js new file mode 100644 index 0000000000..8fe0e1dd84 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/name.js @@ -0,0 +1,30 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Collator.prototype.compare +description: > + get Intl.Collator.prototype.compare.name is "get compare". +info: | + 10.3.3 get Intl.Collator.prototype.compare + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare"); + +assert.sameValue(desc.get.name, "get compare"); + +verifyNotEnumerable(desc.get, "name"); +verifyNotWritable(desc.get, "name"); +verifyConfigurable(desc.get, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-basic.js b/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-basic.js new file mode 100644 index 0000000000..8243ddfd44 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-basic.js @@ -0,0 +1,24 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.3.2_CS_b_NN +description: > + Tests that the compare function isn't entirely unreasonable. This + test is not normative. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +// this test should be valid at least for the following locales +var locales = ["de", "en", "es", "fr", "it"]; +locales = Intl.Collator.supportedLocalesOf(locales, {localeMatcher: "lookup"}); +locales.forEach(function (locale) { + var collator = new Intl.Collator([locale], {sensitivity: "variant", localeMatcher: "lookup"}); + var a = ["L", "X", "C", "k", "Z", "H", "d", "m", "w", "A", "i", "f", "y", "E", "N", "V", "g", "J", "b"]; + a.sort(collator.compare); + var expected = ["A", "b", "C", "d", "E", "f", "g", "H", "i", "J", "k", "L", "m", "N", "V", "w", "X", "y", "Z"]; + assert.compareArray(a, expected); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-phonebook.js b/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-phonebook.js new file mode 100644 index 0000000000..47d330eba2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-phonebook.js @@ -0,0 +1,24 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.3.2_CS_c_NN +description: > + Tests that the compare function supports phonebook sorting if it + says it does. This test is not normative. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +// this test should be valid at least for the following locales +var locales = ["de-DE-u-co-phonebk", "de-u-co-phonebk"]; +var collator = new Intl.Collator(locales, {localeMatcher: "lookup"}); +if (locales.indexOf(collator.resolvedOptions().locale) !== -1) { + var a = ["A", "b", "Af", "Ab", "od", "off", "Ä", "ö"]; + a.sort(collator.compare); + var expected = ["A", "Ab", "Ä", "Af", "b", "od", "ö", "off"]; + assert.compareArray(a, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-sensitivity.js b/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-sensitivity.js new file mode 100644 index 0000000000..8c5e70ba87 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/non-normative-sensitivity.js @@ -0,0 +1,36 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.3.2_CS_d_NN +description: > + Tests that the compare function supports different sensitivity + settings. This test is not normative. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +// this test should be valid at least for the following locales +var locales = ["de", "en", "es", "it"]; +locales = Intl.Collator.supportedLocalesOf(locales, {localeMatcher: "lookup"}); +locales.forEach(function (locale) { + var target = "Aa"; + var input = ["Aa", "bA", "E", "b", "aA", "fC", "áÁ", "Aã"]; + var expected = { + "base": ["Aa", "aA", "áÁ", "Aã"], + "accent": ["Aa", "aA"], + "case": ["Aa", "Aã"], + "variant": ["Aa"] + }; + Object.getOwnPropertyNames(expected).forEach(function (sensitivity) { + var collator = new Intl.Collator([locale], {usage: "search", + sensitivity: sensitivity, localeMatcher: "lookup"}); + var matches = input.filter(function (v) { + return collator.compare(v, target) === 0; + }); + assert.compareArray(matches, expected[sensitivity]); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/prop-desc.js b/js/src/tests/test262/intl402/Collator/prototype/compare/prop-desc.js new file mode 100644 index 0000000000..7ec97afd4c --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/prop-desc.js @@ -0,0 +1,37 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype.resolvedoptions +description: > + "compare" property of Intl.Collator.prototype. +info: | + get Intl.Collator.prototype.compare + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + Every accessor property described in clauses 18 through 26 and in Annex B.2 has the + attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. + If only a get accessor function is described, the set accessor function is the default + value, undefined. If only a set accessor is described the get accessor is the default + value, undefined. + +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare"); + +assert.sameValue(desc.set, undefined); +assert.sameValue(typeof desc.get, "function"); + +verifyNotEnumerable(Intl.Collator.prototype, "compare"); +verifyConfigurable(Intl.Collator.prototype, "compare"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/compare/shell.js b/js/src/tests/test262/intl402/Collator/prototype/compare/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/compare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Collator/prototype/constructor/browser.js b/js/src/tests/test262/intl402/Collator/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/Collator/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..ee4cee4d9b --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/constructor/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype.constructor +description: > + "constructor" property of Intl.Collator.prototype. +info: | + Intl.Collator.prototype.constructor + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.Collator.prototype, "constructor"); +verifyWritable(Intl.Collator.prototype, "constructor"); +verifyConfigurable(Intl.Collator.prototype, "constructor"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/constructor/shell.js b/js/src/tests/test262/intl402/Collator/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/constructor/value.js b/js/src/tests/test262/intl402/Collator/prototype/constructor/value.js new file mode 100644 index 0000000000..37cb53b0c5 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/constructor/value.js @@ -0,0 +1,13 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.3.1 +description: > + Tests that Intl.Collator.prototype.constructor is the + Intl.Collator. +---*/ + +assert.sameValue(Intl.Collator.prototype.constructor, Intl.Collator, "Intl.Collator.prototype.constructor is not the same as Intl.Collator"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/prop-desc.js b/js/src/tests/test262/intl402/Collator/prototype/prop-desc.js new file mode 100644 index 0000000000..52e6fec6b3 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/prop-desc.js @@ -0,0 +1,17 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.2.1 +description: Tests that Intl.Collator.prototype has the required attributes. +author: Norbert Lindenberg +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.Collator, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/basic.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/basic.js new file mode 100644 index 0000000000..7f6f5ba604 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/basic.js @@ -0,0 +1,70 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.3.3 +description: > + Tests that the object returned by + Intl.Collator.prototype.resolvedOptions has the right properties. +author: Norbert Lindenberg +includes: [testIntl.js, propertyHelper.js] +---*/ + +var actual = new Intl.Collator().resolvedOptions(); + +var actual2 = new Intl.Collator().resolvedOptions(); +assert.notSameValue(actual2, actual, "resolvedOptions returned the same object twice."); + +// source: CLDR file common/bcp47/collation.xml; version CLDR 32. +var collations = [ + "default", // added + "big5han", + "compat", + "dict", + "direct", + "ducet", + "emoji", + "eor", + "gb2312", + "phonebk", + "phonetic", + "pinyin", + "reformed", + // "search", // excluded + "searchjl", + // "standard", // excluded + "stroke", + "trad", + "unihan", + "zhuyin", +]; + +// this assumes the default values where the specification provides them +assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale), + "Invalid locale: " + actual.locale); +assert.sameValue(actual.usage, "sort"); +assert.sameValue(actual.sensitivity, "variant"); +assert.sameValue(actual.ignorePunctuation, false); +assert.notSameValue(collations.indexOf(actual.collation), -1, + "Invalid collation: " + actual.collation); + +var dataPropertyDesc = { writable: true, enumerable: true, configurable: true }; +verifyProperty(actual, "locale", dataPropertyDesc); +verifyProperty(actual, "usage", dataPropertyDesc); +verifyProperty(actual, "sensitivity", dataPropertyDesc); +verifyProperty(actual, "ignorePunctuation", dataPropertyDesc); +verifyProperty(actual, "collation", dataPropertyDesc); + +// "numeric" is an optional property. +if (actual.hasOwnProperty("numeric")) { + assert.notSameValue([true, false].indexOf(actual.numeric), -1); + verifyProperty(actual, "numeric", dataPropertyDesc); +} + +// "caseFirst" is an optional property. +if (actual.hasOwnProperty("caseFirst")) { + assert.notSameValue(["upper", "lower", "false"].indexOf(actual.caseFirst), -1); + verifyProperty(actual, "caseFirst", dataPropertyDesc); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/builtin.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/builtin.js new file mode 100644 index 0000000000..6fef5829f6 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.3.3_L15 +description: > + Tests that Intl.Collator.prototype.resolvedOptions meets the + requirements for built-in objects defined by the introduction of + chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.Collator.prototype.resolvedOptions), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.Collator.prototype.resolvedOptions), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.Collator.prototype.resolvedOptions), Function.prototype); + +assert.sameValue(Intl.Collator.prototype.resolvedOptions.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.Collator.prototype.resolvedOptions), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..a0ec05d05e --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype.resolvedoptions +description: > + Intl.Collator.prototype.resolvedOptions.length is 0. +info: | + Intl.Collator.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.Collator.prototype.resolvedOptions.length, 0); + +verifyNotEnumerable(Intl.Collator.prototype.resolvedOptions, "length"); +verifyNotWritable(Intl.Collator.prototype.resolvedOptions, "length"); +verifyConfigurable(Intl.Collator.prototype.resolvedOptions, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..46b7fde718 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Collator.prototype.resolvedOptions +description: > + Intl.Collator.prototype.resolvedOptions.name is "resolvedOptions". +info: | + 10.3.5 Intl.Collator.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.Collator.prototype.resolvedOptions.name, "resolvedOptions"); + +verifyNotEnumerable(Intl.Collator.prototype.resolvedOptions, "name"); +verifyNotWritable(Intl.Collator.prototype.resolvedOptions, "name"); +verifyConfigurable(Intl.Collator.prototype.resolvedOptions, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/order.js new file mode 100644 index 0000000000..7e63a9739d --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/order.js @@ -0,0 +1,33 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [compareArray.js] +---*/ + +const options = new Intl.Collator([], { + "numeric": true, + "caseFirst": "upper", +}).resolvedOptions(); + +const expected = [ + "locale", + "usage", + "sensitivity", + "ignorePunctuation", + "collation", +]; + +if ("numeric" in options) { + expected.push("numeric"); +} + +if ("caseFirst" in options) { + expected.push("caseFirst"); +} + +assert.compareArray(Object.getOwnPropertyNames(options), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..418bf6ec88 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype.resolvedoptions +description: > + "resolvedOptions" property of Intl.Collator.prototype. +info: | + Intl.Collator.prototype.resolvedOptions () + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.Collator.prototype, "resolvedOptions"); +verifyWritable(Intl.Collator.prototype, "resolvedOptions"); +verifyConfigurable(Intl.Collator.prototype, "resolvedOptions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/resolvedOptions/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Collator/prototype/shell.js b/js/src/tests/test262/intl402/Collator/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/shell.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/this-value-collator-prototype.js b/js/src/tests/test262/intl402/Collator/prototype/this-value-collator-prototype.js new file mode 100644 index 0000000000..0ccb9a5f52 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/this-value-collator-prototype.js @@ -0,0 +1,16 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-properties-of-the-intl-collator-prototype-object +description: > + Tests that Intl.Collator.prototype is not an object that has been + initialized as an Intl.Collator. +---*/ + +// test by calling a function that should fail as "this" is not an object +// initialized as an Intl.Collator +assert.throws(TypeError, () => Intl.Collator.prototype.compare("aаあ아", "aаあ아"), + "Intl.Collator.prototype is not an object that has been initialized as an Intl.Collator."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/this-value-not-collator.js b/js/src/tests/test262/intl402/Collator/prototype/this-value-not-collator.js new file mode 100644 index 0000000000..dd75665f46 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/this-value-not-collator.js @@ -0,0 +1,28 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.3_b +description: > + Tests that Intl.Collator.prototype functions throw a TypeError if + called on a non-object value or an object that hasn't been + initialized as a Collator. +author: Norbert Lindenberg +---*/ + +var functions = { + "compare getter": Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare").get, + resolvedOptions: Intl.Collator.prototype.resolvedOptions +}; +var invalidTargets = [undefined, null, true, 0, "Collator", [], {}]; + +Object.getOwnPropertyNames(functions).forEach(function (functionName) { + var f = functions[functionName]; + invalidTargets.forEach(function (target) { + assert.throws(TypeError, function() { + f.call(target); + }, "Calling " + functionName + " on " + target + " was not rejected."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString-changed-tag.js b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString-changed-tag.js new file mode 100644 index 0000000000..84dcbda908 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString-changed-tag.js @@ -0,0 +1,30 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype-@@tostringtag +description: > + Object.prototype.toString utilizes Intl.Collator.prototype[@@toStringTag]. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". + + Intl.Collator.prototype [ @@toStringTag ] + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.toStringTag] +---*/ + +Object.defineProperty(Intl.Collator.prototype, Symbol.toStringTag, { + value: "test262", +}); + +assert.sameValue(Object.prototype.toString.call(Intl.Collator.prototype), "[object test262]"); +assert.sameValue(Object.prototype.toString.call(new Intl.Collator()), "[object test262]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString-removed-tag.js b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString-removed-tag.js new file mode 100644 index 0000000000..16074d110f --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString-removed-tag.js @@ -0,0 +1,24 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype-@@tostringtag +description: > + Object.prototype.toString doesn't special-case neither Intl.Collator instances nor its prototype. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". +features: [Symbol.toStringTag] +---*/ + +delete Intl.Collator.prototype[Symbol.toStringTag]; + +assert.sameValue(Object.prototype.toString.call(Intl.Collator.prototype), "[object Object]"); +assert.sameValue(Object.prototype.toString.call(new Intl.Collator()), "[object Object]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString.js new file mode 100644 index 0000000000..ad6395fee9 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toString.js @@ -0,0 +1,26 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype-@@tostringtag +description: > + Object.prototype.toString utilizes Intl.Collator.prototype[@@toStringTag]. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". + + Intl.Collator.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl.Collator". +features: [Symbol.toStringTag] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.Collator.prototype), "[object Intl.Collator]"); +assert.sameValue(Object.prototype.toString.call(new Intl.Collator()), "[object Intl.Collator]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toStringTag.js new file mode 100644 index 0000000000..1f4942b46f --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/prototype/toStringTag/toStringTag.js @@ -0,0 +1,25 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.prototype-@@tostringtag +description: > + Property descriptor of Intl.Collator.prototype[@@toStringTag]. +info: | + Intl.Collator.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl.Collator". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.toStringTag] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.Collator.prototype, Symbol.toStringTag, { + value: "Intl.Collator", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/shell.js b/js/src/tests/test262/intl402/Collator/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/shell.js diff --git a/js/src/tests/test262/intl402/Collator/subclassing.js b/js/src/tests/test262/intl402/Collator/subclassing.js new file mode 100644 index 0000000000..e6d499983d --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/subclassing.js @@ -0,0 +1,30 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.2_a +description: Tests that Intl.Collator can be subclassed. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +// get a collator and have it sort an array for comparison with the subclass +var locales = ["tlh", "id", "en"]; +var a = ["A", "C", "E", "B", "D", "F"]; +var referenceCollator = new Intl.Collator(locales); +var referenceSorted = a.slice().sort(referenceCollator.compare); + +class MyCollator extends Intl.Collator { + constructor(locales, options) { + super(locales, options); + // could initialize MyCollator properties + } + // could add methods to MyCollator.prototype +} + +var collator = new MyCollator(locales); +a.sort(collator.compare); +assert.compareArray(a, referenceSorted); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/basic.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/basic.js new file mode 100644 index 0000000000..4ec8ea705a --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/basic.js @@ -0,0 +1,24 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.2.2_a +description: > + Tests that Intl.Collator has a supportedLocalesOf property, and + it works as planned. +---*/ + +var defaultLocale = new Intl.Collator().resolvedOptions().locale; +var notSupported = 'zxx'; // "no linguistic content" +var requestedLocales = [defaultLocale, notSupported]; + +var supportedLocales; + +assert(Intl.Collator.hasOwnProperty('supportedLocalesOf'), "Intl.Collator doesn't have a supportedLocalesOf property."); + +supportedLocales = Intl.Collator.supportedLocalesOf(requestedLocales); +assert.sameValue(supportedLocales.length, 1, 'The length of supported locales list is not 1.'); + +assert.sameValue(supportedLocales[0], defaultLocale, 'The default locale is not returned in the supported list.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/browser.js diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/builtin.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/builtin.js new file mode 100644 index 0000000000..ab5f0f3e3f --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.2.2_L15 +description: > + Tests that Intl.Collator.supportedLocalesOf meets the + requirements for built-in objects defined by the introduction of + chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.Collator.supportedLocalesOf), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.Collator.supportedLocalesOf), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.Collator.supportedLocalesOf), Function.prototype); + +assert.sameValue(Intl.Collator.supportedLocalesOf.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.Collator.supportedLocalesOf), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/length.js new file mode 100644 index 0000000000..086ed709d5 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.supportedlocalesof +description: > + Intl.Collator.supportedLocalesOf.length is 1. +info: | + Intl.Collator.supportedLocalesOf ( locales [ , options ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.Collator.supportedLocalesOf.length, 1); + +verifyNotEnumerable(Intl.Collator.supportedLocalesOf, "length"); +verifyNotWritable(Intl.Collator.supportedLocalesOf, "length"); +verifyConfigurable(Intl.Collator.supportedLocalesOf, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/name.js new file mode 100644 index 0000000000..471d0e9a6a --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Collator.supportedLocalesOf +description: > + Intl.Collator.supportedLocalesOf.name is "supportedLocalesOf". +info: | + 10.2.2 Intl.Collator.supportedLocalesOf (locales [ , options ]) + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.Collator.supportedLocalesOf.name, "supportedLocalesOf"); + +verifyNotEnumerable(Intl.Collator.supportedLocalesOf, "name"); +verifyNotWritable(Intl.Collator.supportedLocalesOf, "name"); +verifyConfigurable(Intl.Collator.supportedLocalesOf, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/prop-desc.js new file mode 100644 index 0000000000..e47eb2fd80 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.collator.supportedlocalesof +description: > + "supportedLocalesOf" property of Intl.Collator. +info: | + Intl.Collator.supportedLocalesOf ( locales [ , options ] ) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.Collator, "supportedLocalesOf"); +verifyWritable(Intl.Collator, "supportedLocalesOf"); +verifyConfigurable(Intl.Collator, "supportedLocalesOf"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Collator/supportedLocalesOf/taint-Object-prototype.js b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/taint-Object-prototype.js new file mode 100644 index 0000000000..7e3018883f --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/supportedLocalesOf/taint-Object-prototype.js @@ -0,0 +1,16 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 10.2.2_b +description: > + Tests that Intl.Collator.supportedLocalesOf doesn't access + arguments that it's not given. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintDataProperty(Object.prototype, "1"); +new Intl.Collator("und"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/taint-Object-prototype.js b/js/src/tests/test262/intl402/Collator/taint-Object-prototype.js new file mode 100644 index 0000000000..6832cb717d --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/taint-Object-prototype.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_10 +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintProperties(["localeMatcher", "kn", "kf"]); + +var locale = new Intl.Collator(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; +assert(isCanonicalizedStructurallyValidLanguageTag(locale), "Collator returns invalid locale " + locale + "."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/test-option-ignorePunctuation.js b/js/src/tests/test262/intl402/Collator/test-option-ignorePunctuation.js new file mode 100644 index 0000000000..0ffdbb1fd0 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/test-option-ignorePunctuation.js @@ -0,0 +1,14 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_23 +description: Tests that the option ignorePunctuation is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +// the fallback is variant only for usage === sort, but that happens to be the fallback for usage +testOption(Intl.Collator, "ignorePunctuation", "boolean", undefined, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/test-option-localeMatcher.js b/js/src/tests/test262/intl402/Collator/test-option-localeMatcher.js new file mode 100644 index 0000000000..76492a09de --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/test-option-localeMatcher.js @@ -0,0 +1,13 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_11 +description: Tests that the option localeMatcher is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.Collator, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/test-option-numeric-and-caseFirst.js b/js/src/tests/test262/intl402/Collator/test-option-numeric-and-caseFirst.js new file mode 100644 index 0000000000..186c1b8410 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/test-option-numeric-and-caseFirst.js @@ -0,0 +1,16 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_13 +description: > + Tests that the options numeric and caseFirst are processed + correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.Collator, "numeric", "boolean", undefined, undefined, {isOptional: true}); +testOption(Intl.Collator, "caseFirst", "string", ["upper", "lower", "false"], undefined, {isOptional: true}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/test-option-sensitivity.js b/js/src/tests/test262/intl402/Collator/test-option-sensitivity.js new file mode 100644 index 0000000000..382a6a84c4 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/test-option-sensitivity.js @@ -0,0 +1,14 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_20 +description: Tests that the option sensitivity is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +// the fallback is variant only for usage === sort, but that happens to be the fallback for usage +testOption(Intl.Collator, "sensitivity", "string", ["base", "accent", "case", "variant"], "variant"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/test-option-usage.js b/js/src/tests/test262/intl402/Collator/test-option-usage.js new file mode 100644 index 0000000000..d504c081e7 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/test-option-usage.js @@ -0,0 +1,13 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_6 +description: Tests that the option usage is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.Collator, "usage", "string", ["sort", "search"], "sort"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/this-value-ignored.js b/js/src/tests/test262/intl402/Collator/this-value-ignored.js new file mode 100644 index 0000000000..36286fbd66 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/this-value-ignored.js @@ -0,0 +1,32 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_1 +description: Tests that the this-value is ignored in Collator. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var obj, newObj; + + // variant 1: use constructor in a "new" expression + obj = new Constructor(); + newObj = Intl.Collator.call(obj); + assert.notSameValue(obj, newObj, "Collator object created with \"new\" was not ignored as this-value."); + + // variant 2: use constructor as a function + if (Constructor !== Intl.Collator && + Constructor !== Intl.NumberFormat && + Constructor !== Intl.DateTimeFormat) + { + // Newer Intl constructors are not callable as a function. + return; + } + obj = Constructor(); + newObj = Intl.Collator.call(obj); + assert.notSameValue(obj, newObj, "Collator object created with constructor as function was not ignored as this-value."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/unicode-ext-seq-in-private-tag.js b/js/src/tests/test262/intl402/Collator/unicode-ext-seq-in-private-tag.js new file mode 100644 index 0000000000..2eb7546079 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/unicode-ext-seq-in-private-tag.js @@ -0,0 +1,29 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializecollator +description: > + Unicode extension sequence-like parts are ignored in private-use tags. +info: | + 10.1.1 InitializeCollator ( collator, locales, options ) + ... + 15. For each element key of relevantExtensionKeys in List order, do + a. If key is "co", then + i. Let value be r.[[co]]. + ii. If value is null, let value be "default". + iii. Set collator.[[Collation]] to value. + ... + + 10.3.5 Intl.Collator.prototype.resolvedOptions () + The function returns a new object whose properties and attributes are set as if constructed + by an object literal assigning to each of the following properties the value of the + corresponding internal slot of this Collator object (see 10.4): ... +---*/ + +var c = new Intl.Collator("de-x-u-co-phonebk"); +var resolved = c.resolvedOptions(); + +assert.sameValue(resolved.collation, "default"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/unicode-ext-seq-with-attribute.js b/js/src/tests/test262/intl402/Collator/unicode-ext-seq-with-attribute.js new file mode 100644 index 0000000000..6b03babc6e --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/unicode-ext-seq-with-attribute.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializecollator +description: > + Attributes in Unicode extension subtags should be ignored. +info: | + 10.1.1 InitializeCollator ( collator, locales, options ) + ... + 15. For each element key of relevantExtensionKeys in List order, do + a. If key is "co", then + i. Let value be r.[[co]]. + ii. If value is null, let value be "default". + iii. Set collator.[[Collation]] to value. + ... + + 10.3.5 Intl.Collator.prototype.resolvedOptions () + The function returns a new object whose properties and attributes are set as if constructed + by an object literal assigning to each of the following properties the value of the + corresponding internal slot of this Collator object (see 10.4): ... +---*/ + +var colExpected = new Intl.Collator("de-u-attrval-co-phonebk"); +var colActual = new Intl.Collator("de-u-co-phonebk"); + +var resolvedExpected = colExpected.resolvedOptions(); +var resolvedActual = colActual.resolvedOptions(); + +assert.sameValue(resolvedActual.locale, resolvedExpected.locale); +assert.sameValue(resolvedActual.collation, resolvedExpected.collation); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/unicode-ext-value-collation.js b/js/src/tests/test262/intl402/Collator/unicode-ext-value-collation.js new file mode 100644 index 0000000000..c09eefec32 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/unicode-ext-value-collation.js @@ -0,0 +1,40 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 10.1.1_19_b +description: Tests the special handling of the "co" key in Intl.Collator. +author: Norbert Lindenberg +---*/ + +function checkCollation(extensionCoValue, usageValue, expectedCollations, expectedUsage) { + var requestLocale = extensionCoValue !== undefined ? "de-DE-u-co-" + extensionCoValue : "de-DE"; + var options = usageValue !== undefined ? { usage: usageValue } : undefined; + var collator = new Intl.Collator([requestLocale], options); + + var collation = collator.resolvedOptions().collation; + assert.notSameValue(expectedCollations.indexOf(collation), -1, (extensionCoValue === undefined ? "Default collation" : "Collation for \"" + extensionCoValue) + "\" should be " + expectedCollations.join(" or ") + ", but is " + collation + "."); + + var usage = collator.resolvedOptions().usage; + assert.sameValue(usage, expectedUsage, (usageValue === undefined ? "Default usage" : "Usage") + " mismatch."); +} + +checkCollation(undefined, undefined, ["default"], "sort"); + +checkCollation("phonebk", undefined, ["phonebk", "default"], "sort"); + +checkCollation("invalid", undefined, ["default"], "sort"); + +checkCollation("standard", undefined, ["default"], "sort"); + +checkCollation("standard", "search", ["default"], "search"); + +checkCollation("standard", "sort", ["default"], "sort"); + +checkCollation("search", undefined, ["default"], "sort"); + +checkCollation("search", "search", ["default"], "search"); + +checkCollation("search", "sort", ["default"], "sort"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Collator/usage-de.js b/js/src/tests/test262/intl402/Collator/usage-de.js new file mode 100644 index 0000000000..e0b01f5db6 --- /dev/null +++ b/js/src/tests/test262/intl402/Collator/usage-de.js @@ -0,0 +1,18 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializecollator +description: Checks the behavior of search and sort in German. +includes: [compareArray.js] +locale: [de] +---*/ + +assert.compareArray(["AE", "\u00C4"].sort(new Intl.Collator("de", {usage: "sort"}).compare), + ["\u00C4", "AE"], + "sort"); +assert.compareArray(["AE", "\u00C4"].sort(new Intl.Collator("de", {usage: "search"}).compare), + ["AE", "\u00C4"], + "search"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/browser.js b/js/src/tests/test262/intl402/Date/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/browser.js diff --git a/js/src/tests/test262/intl402/Date/prototype/browser.js b/js/src/tests/test262/intl402/Date/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/browser.js diff --git a/js/src/tests/test262/intl402/Date/prototype/returns-same-results-as-DateTimeFormat.js b/js/src/tests/test262/intl402/Date/prototype/returns-same-results-as-DateTimeFormat.js new file mode 100644 index 0000000000..0148c1c527 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/returns-same-results-as-DateTimeFormat.js @@ -0,0 +1,57 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.3.0_7 +description: > + Tests that Date.prototype.toLocaleString & Co. produces the same + results as Intl.DateTimeFormat. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +var functions = { + toLocaleString: [Date.prototype.toLocaleString, + {year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}], + toLocaleDateString: [Date.prototype.toLocaleDateString, + {year: "numeric", month: "numeric", day: "numeric"}], + toLocaleTimeString: [Date.prototype.toLocaleTimeString, + {hour: "numeric", minute: "numeric", second: "numeric"}] +}; +var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))]; +var locales = [undefined, ["de"], ["th-u-ca-gregory-nu-thai"], ["en"], ["ja-u-ca-japanese"], ["ar-u-ca-islamicc-nu-arab"]]; +var options = [ + undefined, + {hour12: false}, + {month: "long", day: "numeric", hour: "2-digit", minute: "2-digit"} +]; + +Object.getOwnPropertyNames(functions).forEach(function (p) { + var f = functions[p][0]; + var defaults = functions[p][1]; + locales.forEach(function (locales) { + options.forEach(function (options) { + var constructorOptions = options; + if (options === undefined) { + constructorOptions = defaults; + } else if (options.day === undefined) { + // for simplicity, our options above have either both date and time or neither + constructorOptions = Object.create(defaults); + for (var prop in options) { + if (options.hasOwnProperty(prop)) { + constructorOptions[prop] = options[prop]; + } + } + } + var referenceDateTimeFormat = new Intl.DateTimeFormat(locales, constructorOptions); + var referenceFormatted = dates.map(referenceDateTimeFormat.format); + + var formatted = dates.map(function (a) { return f.call(a, locales, options); }); + assert.compareArray(formatted, referenceFormatted, + "(Testing with locales " + locales + "; options " + + (options ? JSON.stringify(options) : options) + ".)"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/shell.js b/js/src/tests/test262/intl402/Date/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/shell.js diff --git a/js/src/tests/test262/intl402/Date/prototype/taint-Intl-DateTimeFormat.js b/js/src/tests/test262/intl402/Date/prototype/taint-Intl-DateTimeFormat.js new file mode 100644 index 0000000000..78775974bf --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/taint-Intl-DateTimeFormat.js @@ -0,0 +1,18 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.3.0_6_2 +description: > + Tests that Date.prototype.toLocaleString & Co. use the standard + built-in Intl.DateTimeFormat constructor. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintDataProperty(Intl, "DateTimeFormat"); +new Date().toLocaleString(); +new Date().toLocaleDateString(); +new Date().toLocaleTimeString(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/this-value-invalid-date.js b/js/src/tests/test262/intl402/Date/prototype/this-value-invalid-date.js new file mode 100644 index 0000000000..4b5c4b4ed9 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/this-value-invalid-date.js @@ -0,0 +1,27 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.3.0_2 +description: > + Tests that Date.prototype.toLocaleString & Co. handle non-finite + values correctly. +author: Norbert Lindenberg +---*/ + +var functions = { + toLocaleString: Date.prototype.toLocaleString, + toLocaleDateString: Date.prototype.toLocaleDateString, + toLocaleTimeString: Date.prototype.toLocaleTimeString +}; +var invalidValues = [NaN, Infinity, -Infinity]; + +Object.getOwnPropertyNames(functions).forEach(function (p) { + var f = functions[p]; + invalidValues.forEach(function (value) { + var result = f.call(new Date(value)); + assert.sameValue(result, "Invalid Date", "Date.prototype." + p + " did not return \"Invalid Date\" for " + value); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/this-value-non-date.js b/js/src/tests/test262/intl402/Date/prototype/this-value-non-date.js new file mode 100644 index 0000000000..51f1197f0a --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/this-value-non-date.js @@ -0,0 +1,28 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.3.0_1 +description: > + Tests that Date.prototype.toLocaleString & Co. handle "this time + value" correctly. +author: Norbert Lindenberg +---*/ + +var functions = { + toLocaleString: Date.prototype.toLocaleString, + toLocaleDateString: Date.prototype.toLocaleDateString, + toLocaleTimeString: Date.prototype.toLocaleTimeString +}; +var invalidValues = [undefined, null, 5, "5", false, {valueOf: function () { return 5; }}]; + +Object.getOwnPropertyNames(functions).forEach(function (p) { + var f = functions[p]; + invalidValues.forEach(function (value) { + assert.throws(TypeError, function() { + var result = f.call(value); + }, "Date.prototype." + p + " did not reject this = " + value + "."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/throws-same-exceptions-as-DateTimeFormat.js b/js/src/tests/test262/intl402/Date/prototype/throws-same-exceptions-as-DateTimeFormat.js new file mode 100644 index 0000000000..17371d2a85 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/throws-same-exceptions-as-DateTimeFormat.js @@ -0,0 +1,56 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.3.0_6_1 +description: > + Tests that Date.prototype.toLocaleString & Co. throws the same + exceptions as Intl.DateTimeFormat. +author: Norbert Lindenberg +---*/ + +var functions = { + toLocaleString: Date.prototype.toLocaleString, + toLocaleDateString: Date.prototype.toLocaleDateString, + toLocaleTimeString: Date.prototype.toLocaleTimeString +}; +var locales = [null, [NaN], ["i"], ["de_DE"]]; +var options = [ + {localeMatcher: null}, + {timeZone: "invalid"}, + {hour: "long"}, + {formatMatcher: "invalid"} +]; + +Object.getOwnPropertyNames(functions).forEach(function (p) { + var f = functions[p]; + locales.forEach(function (locales) { + var referenceError, error; + try { + var format = new Intl.DateTimeFormat(locales); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.DateTimeFormat for locales " + locales + "."); + + assert.throws(referenceError.constructor, function() { + var result = f.call(new Date(), locales); + }, "Date.prototype." + p + " didn't throw exception for locales " + locales + "."); + }); + + options.forEach(function (options) { + var referenceError, error; + try { + var format = new Intl.DateTimeFormat([], options); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.DateTimeFormat for options " + JSON.stringify(options) + "."); + + assert.throws(referenceError.constructor, function() { + var result = f.call(new Date(), [], options); + }, "Date.prototype." + p + " didn't throw exception for options " + JSON.stringify(options) + "."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/browser.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/browser.js diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/builtin.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/builtin.js new file mode 100644 index 0000000000..850f64fab5 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.3.2_L15 +description: > + Tests that Date.prototype.toLocaleDateString meets the + requirements for built-in objects defined by the introduction of + chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Date.prototype.toLocaleDateString), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Date.prototype.toLocaleDateString), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Date.prototype.toLocaleDateString), Function.prototype); + +assert.sameValue(Date.prototype.toLocaleDateString.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Date.prototype.toLocaleDateString), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/length.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/length.js new file mode 100644 index 0000000000..80614fb881 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-date.prototype.tolocaledatestring +description: > + Date.prototype.toLocaleDateString.length is 0. +info: | + Date.prototype.toLocaleDateString ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Date.prototype.toLocaleDateString.length, 0); + +verifyNotEnumerable(Date.prototype.toLocaleDateString, "length"); +verifyNotWritable(Date.prototype.toLocaleDateString, "length"); +verifyConfigurable(Date.prototype.toLocaleDateString, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/shell.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleDateString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/browser.js diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleString/builtin.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/builtin.js new file mode 100644 index 0000000000..7db6c9b8df --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.3.1_L15 +description: > + Tests that Date.prototype.toLocaleString meets the requirements + for built-in objects defined by the introduction of chapter 17 of + the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Date.prototype.toLocaleString), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Date.prototype.toLocaleString), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Date.prototype.toLocaleString), Function.prototype); + +assert.sameValue(Date.prototype.toLocaleString.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Date.prototype.toLocaleString), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleString/default-options-object-prototype.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/default-options-object-prototype.js new file mode 100644 index 0000000000..28654c8173 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/default-options-object-prototype.js @@ -0,0 +1,21 @@ +// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-todatetimeoptions +description: > + Monkey-patching Object.prototype does not change the default + options for DateTimeFormat as a null prototype is used. +info: | + ToDateTimeOptions ( options, required, defaults ) + + 1. If options is undefined, let options be null; otherwise let options be ? ToObject(options). + 1. Let options be ObjectCreate(options). +---*/ + +if (new Intl.DateTimeFormat("en").resolvedOptions().locale === "en") { + Object.prototype.year = "2-digit"; + assert.notSameValue(new Date().toLocaleString("en").length, 2); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleString/length.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/length.js new file mode 100644 index 0000000000..405aaf824c --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-date.prototype.tolocalestring +description: > + Date.prototype.toLocaleString.length is 0. +info: | + Date.prototype.toLocaleString ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Date.prototype.toLocaleString.length, 0); + +verifyNotEnumerable(Date.prototype.toLocaleString, "length"); +verifyNotWritable(Date.prototype.toLocaleString, "length"); +verifyConfigurable(Date.prototype.toLocaleString, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/browser.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/browser.js diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/builtin.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/builtin.js new file mode 100644 index 0000000000..e82ac0017e --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.3.3_L15 +description: > + Tests that Date.prototype.toLocaleTimeString meets the + requirements for built-in objects defined by the introduction of + chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Date.prototype.toLocaleTimeString), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Date.prototype.toLocaleTimeString), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Date.prototype.toLocaleTimeString), Function.prototype); + +assert.sameValue(Date.prototype.toLocaleTimeString.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Date.prototype.toLocaleTimeString), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/length.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/length.js new file mode 100644 index 0000000000..16f92ccf49 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-date.prototype.tolocaletimestring +description: > + Date.prototype.toLocaleTimeString.length is 0. +info: | + Date.prototype.toLocaleTimeString ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Date.prototype.toLocaleTimeString.length, 0); + +verifyNotEnumerable(Date.prototype.toLocaleTimeString, "length"); +verifyNotWritable(Date.prototype.toLocaleTimeString, "length"); +verifyConfigurable(Date.prototype.toLocaleTimeString, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/shell.js b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/prototype/toLocaleTimeString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Date/shell.js b/js/src/tests/test262/intl402/Date/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Date/shell.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/builtin.js new file mode 100644 index 0000000000..abffae0582 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/builtin.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.1_L15 +description: > + Tests that Intl.DateTimeFormat meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.DateTimeFormat), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.DateTimeFormat), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.DateTimeFormat), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/casing-numbering-system-calendar-options.js b/js/src/tests/test262/intl402/DateTimeFormat/casing-numbering-system-calendar-options.js new file mode 100644 index 0000000000..0435ec2bae --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/casing-numbering-system-calendar-options.js @@ -0,0 +1,45 @@ +// Copyright 2020 Google Inc, Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Tests that the options numberingSystem and calendar are mapped + to lower case properly. +author: Caio Lima +---*/ + +let defaultLocale = new Intl.DateTimeFormat().resolvedOptions().locale; + +let supportedNumberingSystems = ["latn", "arab"].filter(nu => + new Intl.DateTimeFormat(defaultLocale + "-u-nu-" + nu) + .resolvedOptions().numberingSystem === nu +); + +if (supportedNumberingSystems.includes("latn")) { + let dateTimeFormat = new Intl.DateTimeFormat(defaultLocale + "-u-nu-lATn"); + assert.sameValue(dateTimeFormat.resolvedOptions().numberingSystem, "latn", "Numbering system option should be in lower case"); +} + +if (supportedNumberingSystems.includes("arab")) { + let dateTimeFormat = new Intl.DateTimeFormat(defaultLocale + "-u-nu-Arab"); + assert.sameValue(dateTimeFormat.resolvedOptions().numberingSystem, "arab", "Numbering system option should be in lower case"); +} + +let supportedCalendars = ["gregory", "chinese"].filter(ca => + new Intl.DateTimeFormat(defaultLocale + "-u-ca-" + ca) + .resolvedOptions().calendar === ca +); + +if (supportedCalendars.includes("gregory")) { + let dateTimeFormat = new Intl.DateTimeFormat(defaultLocale + "-u-ca-Gregory"); + assert.sameValue(dateTimeFormat.resolvedOptions().calendar, "gregory", "Calendar option should be in lower case"); +} + +if (supportedCalendars.includes("chinese")) { + let dateTimeFormat = new Intl.DateTimeFormat(defaultLocale + "-u-ca-CHINESE"); + assert.sameValue(dateTimeFormat.resolvedOptions().calendar, "chinese", "Calendar option should be in lower case"); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-calendar-numberingSystem-order.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-calendar-numberingSystem-order.js new file mode 100644 index 0000000000..d08b114c75 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-calendar-numberingSystem-order.js @@ -0,0 +1,51 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks the order of getting "calendar" and "numberingSystem" options in the + DateTimeFormat is between "localeMatcher" and "hour12" options. +info: | + 4. Let _matcher_ be ? GetOption(_options_, `"localeMatcher"`, `"string"`, « `"lookup"`, `"best fit"` », `"best fit"`). + ... + 6. Let _calendar_ be ? GetOption(_options_, `"calendar"`, `"string"`, *undefined*, *undefined*). + ... + 9. Let _numberingSystem_ be ? GetOption(_options_, `"numberingSystem"`, `"string"`, *undefined*, *undefined*). + ... + 12. Let _hour12_ be ? GetOption(_options_, `"hour12"`, `"boolean"`, *undefined*, *undefined*). +includes: [compareArray.js] +---*/ + +const actual = []; + +const options = { + get localeMatcher() { + actual.push("localeMatcher"); + return undefined; + }, + get calendar() { + actual.push("calendar"); + return undefined; + }, + get numberingSystem() { + actual.push("numberingSystem"); + return undefined; + }, + get hour12() { + actual.push("hour12"); + return undefined; + }, +}; + +const expected = [ + "localeMatcher", + "calendar", + "numberingSystem", + "hour12" +]; + +let df = new Intl.DateTimeFormat(undefined, options); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-default-value.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-default-value.js new file mode 100644 index 0000000000..961bcfec96 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-default-value.js @@ -0,0 +1,25 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Tests that the constructor for Intl.DateTimeFormat uses appropriate default + values for its arguments (locales and options). +---*/ + +const actual = new Intl.DateTimeFormat().resolvedOptions(); +const expected = new Intl.DateTimeFormat( + [], + Object.create(null) +).resolvedOptions(); + +assert.sameValue(actual.locale, expected.locale); +assert.sameValue(actual.calendar, expected.calendar); +assert.sameValue(actual.day, expected.day); +assert.sameValue(actual.month, expected.month); +assert.sameValue(actual.year, expected.year); +assert.sameValue(actual.numberingSystem, expected.numberingSystem); +assert.sameValue(actual.timeZone, expected.timeZone); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-calendar-invalid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-calendar-invalid.js new file mode 100644 index 0000000000..5ecfd4a6a1 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-calendar-invalid.js @@ -0,0 +1,42 @@ +// Copyright 2020 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks error cases for the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... + 7. If calendar is not undefined, then + a. If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. +---*/ + +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + numberingSystem = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidCalendarOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", + "!invalid!", + "-gregory-", + "gregory-", + "gregory--", + "gregory-nu", + "gregory-nu-", + "gregory-nu-latn", + "gregoryé", + "gregory역법", +]; +for (const calendar of invalidCalendarOptions) { + assert.throws(RangeError, function() { + new Intl.DateTimeFormat('en', {calendar}); + }, `new Intl.DateTimeFormat("en", {calendar: "${calendar}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dateStyle-invalid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dateStyle-invalid.js new file mode 100644 index 0000000000..740bcec24f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dateStyle-invalid.js @@ -0,0 +1,31 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks error cases for the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... + 28. Let dateStyle be ? GetOption(options, "dateStyle", "string", « "full", "long", "medium", "short" », undefined). +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + + +const invalidOptions = [ + "", + "FULL", + " long", + "short ", + "narrow", + "numeric", +]; +for (const dateStyle of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.DateTimeFormat("en", { dateStyle }); + }, `new Intl.DateTimeFormat("en", { dateStyle: "${dateStyle}" }) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dateStyle-valid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dateStyle-valid.js new file mode 100644 index 0000000000..7de1322dcc --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dateStyle-valid.js @@ -0,0 +1,39 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks handling of the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... + 28. Let dateStyle be ? GetOption(options, "dateStyle", "string", « "full", "long", "medium", "short" », undefined). + 29. If dateStyle is not undefined, set dateTimeFormat.[[DateStyle]] to dateStyle. +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + + +const validOptions = [ + [undefined, undefined], + ["full", "full"], + ["long", "long"], + ["medium", "medium"], + ["short", "short"], + [{ toString() { return "full"; } }, "full"], + [{ valueOf() { return "long"; }, toString: undefined }, "long"], +]; +for (const [dateStyle, expected] of validOptions) { + const dtf = new Intl.DateTimeFormat("en", { dateStyle }); + const options = dtf.resolvedOptions(); + assert.sameValue(options.dateStyle, expected); + const propdesc = Object.getOwnPropertyDescriptor(options, "dateStyle"); + if (expected === undefined) { + assert.sameValue(propdesc, undefined); + } else { + assert.sameValue(propdesc.value, expected); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dayPeriod-invalid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dayPeriod-invalid.js new file mode 100644 index 0000000000..abc9acb7e5 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dayPeriod-invalid.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks error cases for the options argument to the DateTimeFormat constructor. +info: | + [[DayPeriod]] `"dayPeriod"` `"narrow"`, `"short"`, `"long"` + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +const invalidOptions = [ + "", + "LONG", + " long", + "short ", + "full", + "numeric", +]; +for (const dayPeriod of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.DateTimeFormat("en", { dayPeriod }); + }, `new Intl.DateTimeFormat("en", { dayPeriod: "${dayPeriod}" }) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dayPeriod-valid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dayPeriod-valid.js new file mode 100644 index 0000000000..07da90bc5c --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-dayPeriod-valid.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks handling of the options argument to the DateTimeFormat constructor. +info: | + [[DayPeriod]] `"dayPeriod"` `"narrow"`, `"short"`, `"long"` + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +const validOptions = [ + [undefined, undefined], + ["long", "long"], + ["short", "short"], + ["narrow", "narrow"], + [{ toString() { return "narrow"; } }, "narrow"], + [{ valueOf() { return "long"; }, toString: undefined }, "long"], +]; +for (const [dayPeriod, expected] of validOptions) { + const dtf = new Intl.DateTimeFormat("en", { dayPeriod }); + const options = dtf.resolvedOptions(); + assert.sameValue(options.dayPeriod, expected); + const propdesc = Object.getOwnPropertyDescriptor(options, "dayPeriod"); + if (expected === undefined) { + assert.sameValue(propdesc, undefined); + } else { + assert.sameValue(propdesc.value, expected); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-fractionalSecondDigits-invalid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-fractionalSecondDigits-invalid.js new file mode 100644 index 0000000000..91d017880b --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-fractionalSecondDigits-invalid.js @@ -0,0 +1,37 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks error cases for the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + 23. Let _opt_.[[FractionalSecondDigits]] be ? GetNumberOption(_options_, `"fractionalSecondDigits"`, 0, 3, 0). + + ... +features: [Intl.DateTimeFormat-fractionalSecondDigits] +---*/ + + +const invalidOptions = [ + "LONG", + " long", + "short ", + "full", + "numeric", + -1, + 4, + "4", + "-1", + -0.00001, + 3.000001, +]; +for (const fractionalSecondDigits of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.DateTimeFormat("en", { fractionalSecondDigits }); + }, + `new Intl.DateTimeFormat("en", { fractionalSecondDigits: "${fractionalSecondDigits}" }) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-fractionalSecondDigits-valid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-fractionalSecondDigits-valid.js new file mode 100644 index 0000000000..be82eca19b --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-fractionalSecondDigits-valid.js @@ -0,0 +1,40 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks handling of the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + 23. Let _opt_.[[FractionalSecondDigits]] be ? GetNumberOption(_options_, `"fractionalSecondDigits"`, 0, 3, 0). +features: [Intl.DateTimeFormat-fractionalSecondDigits] +---*/ + + +const validOptions = [ + [undefined, undefined], + [1, 1], + ["1", 1], + [2, 2], + ["2", 2], + [3, 3], + ["3", 3], + [2.9, 2], + ["2.9", 2], + [1.00001, 1], + [{ toString() { return "3"; } }, 3], +]; +for (const [fractionalSecondDigits, expected] of validOptions) { + const dtf = new Intl.DateTimeFormat("en", { fractionalSecondDigits }); + const options = dtf.resolvedOptions(); + assert.sameValue(options.fractionalSecondDigits, expected); + const propdesc = Object.getOwnPropertyDescriptor(options, "fractionalSecondDigits"); + if (expected === undefined) { + assert.sameValue(propdesc, undefined); + } else { + assert.sameValue(propdesc.value, expected); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-numberingSystem-invalid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-numberingSystem-invalid.js new file mode 100644 index 0000000000..c77053a209 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-numberingSystem-invalid.js @@ -0,0 +1,42 @@ +// Copyright 2020 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks error cases for the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... + 10. If numberingSystem is not undefined, then + a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. +---*/ + +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + numberingSystem = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidNumberingSystemOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", + "!invalid!", + "-latn-", + "latn-", + "latn--", + "latn-ca", + "latn-ca-", + "latn-ca-gregory", + "latné", + "latn编号", +]; +for (const numberingSystem of invalidNumberingSystemOptions) { + assert.throws(RangeError, function() { + new Intl.DateTimeFormat('en', {numberingSystem}); + }, `new Intl.DateTimeFormat("en", {numberingSystem: "${numberingSystem}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-dayPeriod.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-dayPeriod.js new file mode 100644 index 0000000000..4620f1964a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-dayPeriod.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Googe Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the order of getting options of 'dayPeriod' for the DateTimeFormat constructor. +info: | + ToDateTimeOptions ( options, required, defaults ) + 4. If required is "date" or "any", then + a. For each of the property names "weekday", "year", "month", "day", "dayPeriod" do + 5. If required is "time" or "any", then + a. For each of the property names "hour", "minute", "second", do +includes: [compareArray.js] +features: [Intl.DateTimeFormat-dayPeriod] + +---*/ + +// Just need to ensure dayPeriod are get between day and hour. +const expected = [ + // ToDateTimeOptions step 4. + "day", "dayPeriod", + // ToDateTimeOptions step 5. + "hour", + // InitializeDateTimeFormat step 22. + "day", + "dayPeriod", + "hour" +]; + +const actual = []; + +const options = { + get day() { + actual.push("day"); + return "numeric"; + }, + get dayPeriod() { + actual.push("dayPeriod"); + return "long"; + }, + get hour() { + actual.push("hour"); + return "numeric"; + }, +}; + +new Intl.DateTimeFormat("en", options); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-fractionalSecondDigits.js new file mode 100644 index 0000000000..1daaba4107 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-fractionalSecondDigits.js @@ -0,0 +1,69 @@ +// Copyright 2019 Googe Inc. All rights reserved. +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the order of getting options of 'fractionalSecondDigits' for the DateTimeFormat constructor. +info: | + ToDateTimeOptions ( options, required, defaults ) + 5. If required is "time" or "any", then + a. For each of the property names "hour", "minute", "second", "fractionalSecondDigits", do + + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + 2. Let options be ? ToDateTimeOptions(options, "any", "date"). + 4. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + 22. For each row of Table 5, except the header row, do + a. Let value be ? GetOption(options, prop, "string", « the strings given in the Values column of the row », undefined). + 23. Let _opt_.[[FractionalSecondDigits]] be ? GetNumberOption(_options_, `"fractionalSecondDigits"`, 0, 3, 0). + 26. Let matcher be ? GetOption(options, "formatMatcher", "string", « "basic", "best fit" », "best fit"). +includes: [compareArray.js] +features: [Intl.DateTimeFormat-fractionalSecondDigits] +---*/ + +// Just need to ensure fractionalSecondDigits are get +// between second and localeMatcher the first time and +// between timeZoneName and formatMatcher the second time. +const expected = [ + // InitializeDateTimeFormat step 2. + // ToDateTimeOptions step 5. + "second", "fractionalSecondDigits", + // InitializeDateTimeFormat step 4. + "localeMatcher", + // InitializeDateTimeFormat step 22. + "second", + "fractionalSecondDigits", + "timeZoneName", + // InitializeDateTimeFormat step 26. + "formatMatcher", +]; + +const actual = []; + +const options = { + get second() { + actual.push("second"); + return "numeric"; + }, + get fractionalSecondDigits() { + actual.push("fractionalSecondDigits"); + return undefined; + }, + get localeMatcher() { + actual.push("localeMatcher"); + return undefined; + }, + get timeZoneName() { + actual.push("timeZoneName"); + return undefined; + }, + get formatMatcher() { + actual.push("formatMatcher"); + return undefined; + }, +}; + +new Intl.DateTimeFormat("en", options); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-timedate-style.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-timedate-style.js new file mode 100644 index 0000000000..c074860b8f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order-timedate-style.js @@ -0,0 +1,136 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the order of getting options for the DateTimeFormat constructor. +includes: [compareArray.js] +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + +// To be merged into constructor-options-order.js when the feature is removed. + +const expected = [ + // ToDateTimeOptions step 4. + "weekday", "year", "month", "day", + // ToDateTimeOptions step 5. + "hour", "minute", "second", + // ToDateTimeOptions step 6. + "dateStyle", + // ToDateTimeOptions step 7. + "timeStyle", + + // InitializeDateTimeFormat step 4. + "localeMatcher", + // InitializeDateTimeFormat step 6. + "hour12", + // InitializeDateTimeFormat step 7. + "hourCycle", + // InitializeDateTimeFormat step 23. + "timeZone", + // InitializeDateTimeFormat step 28. + "weekday", + "era", + "year", + "month", + "day", + "hour", + "minute", + "second", + "timeZoneName", + "formatMatcher", + // InitializeDateTimeFormat step 32. + "dateStyle", + // InitializeDateTimeFormat step 33. + "timeStyle", +]; + +const actual = []; + +const options = { + get dateStyle() { + actual.push("dateStyle"); + return undefined; + }, + + get day() { + actual.push("day"); + return "numeric"; + }, + + get era() { + actual.push("era"); + return "long"; + }, + + get formatMatcher() { + actual.push("formatMatcher"); + return "best fit"; + }, + + get hour() { + actual.push("hour"); + return "numeric"; + }, + + get hour12() { + actual.push("hour12"); + return true; + }, + + get hourCycle() { + actual.push("hourCycle"); + return "h24"; + }, + + get localeMatcher() { + actual.push("localeMatcher"); + return "best fit"; + }, + + get minute() { + actual.push("minute"); + return "numeric"; + }, + + get month() { + actual.push("month"); + return "numeric"; + }, + + get second() { + actual.push("second"); + return "numeric"; + }, + + get timeStyle() { + actual.push("timeStyle"); + return undefined; + }, + + get timeZone() { + actual.push("timeZone"); + return "UTC"; + }, + + get timeZoneName() { + actual.push("timeZoneName"); + return "long"; + }, + + get weekday() { + actual.push("weekday"); + return "long"; + }, + + get year() { + actual.push("year"); + return "numeric"; + }, +}; + +new Intl.DateTimeFormat("en", options); + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order.js new file mode 100644 index 0000000000..25dade65e0 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-order.js @@ -0,0 +1,116 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the order of getting options for the DateTimeFormat constructor. +includes: [compareArray.js] +---*/ + +const expected = [ + // ToDateTimeOptions step 4. + "weekday", "year", "month", "day", + // ToDateTimeOptions step 5. + "hour", "minute", "second", + + // InitializeDateTimeFormat step 4. + "localeMatcher", + // InitializeDateTimeFormat step 6. + "hour12", + // InitializeDateTimeFormat step 7. + "hourCycle", + // InitializeDateTimeFormat step 17. + "timeZone", + // InitializeDateTimeFormat step 22. + "weekday", + "era", + "year", + "month", + "day", + "hour", + "minute", + "second", + "timeZoneName", + // InitializeDateTimeFormat step 25. + "formatMatcher", +]; + +const actual = []; + +const options = { + get day() { + actual.push("day"); + return "numeric"; + }, + + get era() { + actual.push("era"); + return "long"; + }, + + get formatMatcher() { + actual.push("formatMatcher"); + return "best fit"; + }, + + get hour() { + actual.push("hour"); + return "numeric"; + }, + + get hour12() { + actual.push("hour12"); + return true; + }, + + get hourCycle() { + actual.push("hourCycle"); + return "h24"; + }, + + get localeMatcher() { + actual.push("localeMatcher"); + return "best fit"; + }, + + get minute() { + actual.push("minute"); + return "numeric"; + }, + + get month() { + actual.push("month"); + return "numeric"; + }, + + get second() { + actual.push("second"); + return "numeric"; + }, + + get timeZone() { + actual.push("timeZone"); + return "UTC"; + }, + + get timeZoneName() { + actual.push("timeZoneName"); + return "long"; + }, + + get weekday() { + actual.push("weekday"); + return "long"; + }, + + get year() { + actual.push("year"); + return "numeric"; + }, +}; + +new Intl.DateTimeFormat("en", options); + +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-dayPeriod.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-dayPeriod.js new file mode 100644 index 0000000000..099438ae65 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-dayPeriod.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the propagation of exceptions from the options for the DateTimeFormat constructor. +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +function CustomError() {} + +const options = [ + "dayPeriod", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.DateTimeFormat("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-fractionalSecondDigits.js new file mode 100644 index 0000000000..f438e8df97 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-fractionalSecondDigits.js @@ -0,0 +1,26 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the propagation of exceptions from the options for the DateTimeFormat constructor. +features: [Intl.DateTimeFormat-fractionalSecondDigits] +---*/ + +function CustomError() {} + +const options = [ + "fractionalSecondDigits", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.DateTimeFormat("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-timedate-style.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-timedate-style.js new file mode 100644 index 0000000000..448acfa175 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters-timedate-style.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the propagation of exceptions from the options for the DateTimeFormat constructor. +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + +// To be merged into constructor-options-throwing-getters.js when the feature is removed. + +function CustomError() {} + +const options = [ + // InitializeDateTimeFormat step 28 + "dateStyle", + // InitializeDateTimeFormat step 30 + "timeStyle", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.DateTimeFormat("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters.js new file mode 100644 index 0000000000..c7faeabb74 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-throwing-getters.js @@ -0,0 +1,33 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks the propagation of exceptions from the options for the DateTimeFormat constructor. +---*/ + +function CustomError() {} + +const options = [ + "weekday", "year", "month", "day", + "hour", "minute", "second", + "localeMatcher", + "hour12", + "hourCycle", + "timeZone", + "era", + "timeZoneName", + "formatMatcher", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.DateTimeFormat("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-timeStyle-invalid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-timeStyle-invalid.js new file mode 100644 index 0000000000..6979587966 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-timeStyle-invalid.js @@ -0,0 +1,31 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks error cases for the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... + 30. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined). +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + + +const invalidOptions = [ + "", + "FULL", + " long", + "short ", + "narrow", + "numeric", +]; +for (const timeStyle of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.DateTimeFormat("en", { timeStyle }); + }, `new Intl.DateTimeFormat("en", { timeStyle: "${timeStyle}" }) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-timeStyle-valid.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-timeStyle-valid.js new file mode 100644 index 0000000000..cc8665fe44 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-timeStyle-valid.js @@ -0,0 +1,38 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks handling of the options argument to the DateTimeFormat constructor. +info: | + InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + + ... + 30. Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined). + 31. If timeStyle is not undefined, set dateTimeFormat.[[TimeStyle]] to timeStyle. +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + +const validOptions = [ + [undefined, undefined], + ["full", "full"], + ["long", "long"], + ["medium", "medium"], + ["short", "short"], + [{ toString() { return "full"; } }, "full"], + [{ valueOf() { return "long"; }, toString: undefined }, "long"], +]; +for (const [timeStyle, expected] of validOptions) { + const dtf = new Intl.DateTimeFormat("en", { timeStyle }); + const options = dtf.resolvedOptions(); + assert.sameValue(options.timeStyle, expected); + const propdesc = Object.getOwnPropertyDescriptor(options, "timeStyle"); + if (expected === undefined) { + assert.sameValue(propdesc, undefined); + } else { + assert.sameValue(propdesc.value, expected); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-toobject.js b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-toobject.js new file mode 100644 index 0000000000..bde3e584d2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/constructor-options-toobject.js @@ -0,0 +1,44 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Tests that Intl.DateTimeFormat contructor converts the options argument + to an object using `ToObject` (7.1.13). +info: | + 12.1.2 ToDateTimeOptions + + 1. If options is undefined, let options be null; otherwise let options be ? + ToObject(options). +---*/ + +const toObjectResults = [ + [true, new Boolean(true)], + [42, new Number(42)], + ['foo', new String('foo')], + [{}, {}], + [Symbol(), Object(Symbol())] +]; + +// Test if ToObject is used to convert primitives to Objects. +toObjectResults.forEach(pair => { + const [value, result] = pair; + + const actual = new Intl.DateTimeFormat(['en-US'], value).resolvedOptions(); + const expected = new Intl.DateTimeFormat(['en-US'], result).resolvedOptions(); + + assert.sameValue(actual.locale, expected.locale); + assert.sameValue(actual.calendar, expected.calendar); + assert.sameValue(actual.day, expected.day); + assert.sameValue(actual.month, expected.month); + assert.sameValue(actual.year, expected.year); + assert.sameValue(actual.numberingSystem, expected.numberingSystem); + assert.sameValue(actual.timeZone, expected.timeZone); +}); + +// ToObject throws a TypeError for undefined and null, but it's not called +// when options is undefined. +assert.throws(TypeError, () => new Intl.DateTimeFormat(['en-US'], null)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/date-time-options.js b/js/src/tests/test262/intl402/DateTimeFormat/date-time-options.js new file mode 100644 index 0000000000..bfe57ade97 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/date-time-options.js @@ -0,0 +1,106 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_TDTO +description: > + Tests that the set of options for the date and time components is + processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var locales = [[], ["zh-Hans-CN"], ["hi-IN"], ["en-US"], ["id-ID"]]; +var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))]; + +function testWithDateTimeFormat(options, expected) { + locales.forEach(function (locales) { + var format = new Intl.DateTimeFormat(locales, options); + var resolvedOptions = format.resolvedOptions(); + getDateTimeComponents().forEach(function (component) { + if (resolvedOptions.hasOwnProperty(component)) { + assert(expected.hasOwnProperty(component), + "Unrequested component " + component + + " added to expected subset " + JSON.stringify(expected) + + "; locales " + locales + ", options " + + (options ? JSON.stringify(options) : options) + "."); + } else { + assert.sameValue(expected.hasOwnProperty(component), false, + "Missing component " + component + + " from expected subset " + JSON.stringify(expected) + + "; locales " + locales + ", options " + + (options ? JSON.stringify(options) : options) + "."); + } + }); + }); +} + +function testWithToLocale(f, options, expected) { + // expected can be either one subset or an array of possible subsets + if (expected.length === undefined) { + expected = [expected]; + } + locales.forEach(function (locales) { + dates.forEach(function (date) { + var formatted = Date.prototype[f].call(date, locales, options); + var expectedStrings = []; + expected.forEach(function (expected) { + var referenceFormat = new Intl.DateTimeFormat(locales, expected); + expectedStrings.push(referenceFormat.format(date)); + }); + assert.notSameValue(expectedStrings.indexOf(formatted), -1, + "Function " + f + " did not return expected string for locales " + + locales + ", options " + (options? JSON.stringify(options) : options) + + "; expected " + + (expectedStrings.length === 1 ? expectedStrings[0] : "one of " + expectedStrings) + + ", got " + formatted + "."); + }); + }); +} + +// any/date: steps 5a, 6a, 7a +testWithDateTimeFormat(undefined, {year: "numeric", month: "numeric", day: "numeric"}); + +// any/date: steps 5a, 6a +testWithDateTimeFormat({year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"}); + +// any/date: steps 5a, 6a +testWithDateTimeFormat({hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"}); + +// any/all: steps 5a, 6a, 7a, 8a +testWithToLocale("toLocaleString", undefined, [ + // the first one is not guaranteed to be supported; the second one is + {year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}, + {weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"} +]); + +// any/all: steps 5a, 6a +testWithToLocale("toLocaleString", {year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"}); + +// any/all: steps 5a, 6a +testWithToLocale("toLocaleString", {hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"}); + +// date/date: steps 5a, 7a +testWithToLocale("toLocaleDateString", undefined, {year: "numeric", month: "numeric", day: "numeric"}); + +// date/date: steps 5a +testWithToLocale("toLocaleDateString", {year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"}); + +// date/date: steps 5a, 7a +testWithToLocale("toLocaleDateString", {hour: "numeric", minute: "numeric", second: "numeric"}, [ + // the first one is not guaranteed to be supported; the second one is + {year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}, + {weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"} +]); + +// time/time: steps 6a, 8a +testWithToLocale("toLocaleTimeString", undefined, {hour: "numeric", minute: "numeric", second: "numeric"}); + +// time/time: steps 6a, 8a +testWithToLocale("toLocaleTimeString", {weekday: "short", year: "numeric", month: "numeric", day: "numeric"}, + {weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}); + +// time/time: steps 6a +testWithToLocale("toLocaleTimeString", {hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/default-options-object-prototype.js b/js/src/tests/test262/intl402/DateTimeFormat/default-options-object-prototype.js new file mode 100644 index 0000000000..854e5ff3f1 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/default-options-object-prototype.js @@ -0,0 +1,22 @@ +// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-todatetimeoptions +description: > + Monkey-patching Object.prototype does not change the default + options for DateTimeFormat as a null prototype is used. +info: | + ToDateTimeOptions ( options, required, defaults ) + + 1. If options is undefined, let options be null; otherwise let options be ? ToObject(options). + 1. Let options be ObjectCreate(options). +---*/ + +let defaultYear = new Intl.DateTimeFormat("en").resolvedOptions().year; + +Object.prototype.year = "2-digit"; +let formatter = new Intl.DateTimeFormat("en"); +assert.sameValue(formatter.resolvedOptions().year, defaultYear); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/ignore-invalid-unicode-ext-values.js b/js/src/tests/test262/intl402/DateTimeFormat/ignore-invalid-unicode-ext-values.js new file mode 100644 index 0000000000..34c9829741 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/ignore-invalid-unicode-ext-values.js @@ -0,0 +1,39 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.2.3_b +description: > + Tests that Intl.DateTimeFormat does not accept Unicode locale + extension keys and values that are not allowed. +author: Norbert Lindenberg +---*/ + +var locales = ["ja-JP", "zh-Hans-CN", "zh-Hant-TW"]; +var input = new Date(Date.parse("1989-11-09T17:57:00Z")); + +locales.forEach(function (locale) { + var defaultDateTimeFormat = new Intl.DateTimeFormat([locale]); + var defaultOptions = defaultDateTimeFormat.resolvedOptions(); + var defaultOptionsJSON = JSON.stringify(defaultOptions); + var defaultLocale = defaultOptions.locale; + var defaultFormatted = defaultDateTimeFormat.format(input); + + var keyValues = { + "cu": ["USD", "EUR", "JPY", "CNY", "TWD", "invalid"], // DateTimeFormat internally uses NumberFormat + "nu": ["native", "traditio", "finance", "invalid"], + "tz": ["usnavajo", "utcw01", "aumel", "uslax", "usnyc", "deber", "invalid"] + }; + + Object.getOwnPropertyNames(keyValues).forEach(function (key) { + keyValues[key].forEach(function (value) { + var dateTimeFormat = new Intl.DateTimeFormat([locale + "-u-" + key + "-" + value]); + var options = dateTimeFormat.resolvedOptions(); + assert.sameValue(options.locale, defaultLocale, "Locale " + options.locale + " is affected by key " + key + "; value " + value + "."); + assert.sameValue(JSON.stringify(options), defaultOptionsJSON, "Resolved options " + JSON.stringify(options) + " are affected by key " + key + "; value " + value + "."); + assert.sameValue(dateTimeFormat.format(input), defaultFormatted, "Formatted value " + dateTimeFormat.format(input) + " is affected by key " + key + "; value " + value + "."); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/instance-proto-and-extensible.js b/js/src/tests/test262/intl402/DateTimeFormat/instance-proto-and-extensible.js new file mode 100644 index 0000000000..34e6873529 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/instance-proto-and-extensible.js @@ -0,0 +1,19 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.3 +description: > + Tests that objects constructed by Intl.DateTimeFormat have the + specified internal properties. +author: Norbert Lindenberg +---*/ + +var obj = new Intl.DateTimeFormat(); + +var actualPrototype = Object.getPrototypeOf(obj); +assert.sameValue(actualPrototype, Intl.DateTimeFormat.prototype, "Prototype of object constructed by Intl.DateTimeFormat isn't Intl.DateTimeFormat.prototype."); + +assert(Object.isExtensible(obj), "Object constructed by Intl.DateTimeFormat must be extensible."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/intl-legacy-constructed-symbol-on-unwrap.js b/js/src/tests/test262/intl402/DateTimeFormat/intl-legacy-constructed-symbol-on-unwrap.js new file mode 100644 index 0000000000..61b9452d9a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/intl-legacy-constructed-symbol-on-unwrap.js @@ -0,0 +1,34 @@ +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-unwrapdatetimeformat +description: > + Tests that [[FallbackSymbol]]'s [[Description]] is "IntlLegacyConstructedSymbol" if normative optional is implemented. +author: Yusuke Suzuki +features: [intl-normative-optional] +---*/ + +let object = new Intl.DateTimeFormat(); +let newObject = Intl.DateTimeFormat.call(object); +let symbol = null; +let error = null; +try { + let proxy = new Proxy(newObject, { + get(target, property) { + symbol = property; + return target[property]; + } + }); + Intl.DateTimeFormat.prototype.resolvedOptions.call(proxy); +} catch (e) { + // If normative optional is not implemented, an error will be thrown. + error = e; + assert(error instanceof TypeError); +} +if (error === null) { + assert.sameValue(typeof symbol, "symbol"); + assert.sameValue(symbol.description, "IntlLegacyConstructedSymbol"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/intl-legacy-constructed-symbol.js b/js/src/tests/test262/intl402/DateTimeFormat/intl-legacy-constructed-symbol.js new file mode 100644 index 0000000000..6ca345b44e --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/intl-legacy-constructed-symbol.js @@ -0,0 +1,20 @@ +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat +description: > + Tests that [[FallbackSymbol]]'s [[Description]] is "IntlLegacyConstructedSymbol" if normative optional is implemented. +author: Yusuke Suzuki +features: [intl-normative-optional] +---*/ + +let object = new Intl.DateTimeFormat(); +let newObject = Intl.DateTimeFormat.call(object); +let symbols = Object.getOwnPropertySymbols(newObject); +if (symbols.length !== 0) { + assert.sameValue(symbols.length, 1); + assert.sameValue(symbols[0].description, "IntlLegacyConstructedSymbol"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/legacy-regexp-statics-not-modified.js b/js/src/tests/test262/intl402/DateTimeFormat/legacy-regexp-statics-not-modified.js new file mode 100644 index 0000000000..6d44737ef4 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/legacy-regexp-statics-not-modified.js @@ -0,0 +1,21 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_a +description: > + Tests that constructing a DateTimeFormat doesn't create or modify + unwanted properties on the RegExp constructor. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testForUnwantedRegExpChanges(function () { + new Intl.DateTimeFormat("de-DE-u-ca-gregory"); +}); + +testForUnwantedRegExpChanges(function () { + new Intl.DateTimeFormat("de-DE-u-ca-gregory", {timeZone: "UTC"}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/length.js b/js/src/tests/test262/intl402/DateTimeFormat/length.js new file mode 100644 index 0000000000..39331d3787 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat +description: > + Intl.DateTimeFormat.length is 0. +info: | + Intl.DateTimeFormat ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.length, 0); + +verifyNotEnumerable(Intl.DateTimeFormat, "length"); +verifyNotWritable(Intl.DateTimeFormat, "length"); +verifyConfigurable(Intl.DateTimeFormat, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/name.js b/js/src/tests/test262/intl402/DateTimeFormat/name.js new file mode 100644 index 0000000000..434fd31ef3 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat +description: > + Intl.DateTimeFormat.name is "DateTimeFormat". +info: | + 12.2.1 Intl.DateTimeFormat ([ locales [ , options ]]) + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.name, "DateTimeFormat"); + +verifyNotEnumerable(Intl.DateTimeFormat, "name"); +verifyNotWritable(Intl.DateTimeFormat, "name"); +verifyConfigurable(Intl.DateTimeFormat, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/numbering-system-calendar-options.js b/js/src/tests/test262/intl402/DateTimeFormat/numbering-system-calendar-options.js new file mode 100644 index 0000000000..b7cd7a3241 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/numbering-system-calendar-options.js @@ -0,0 +1,69 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Tests that the options numberingSystem and calendar can be set through + either the locale or the options. +author: Norbert Lindenberg, Daniel Ehrenberg +---*/ + +let defaultLocale = new Intl.DateTimeFormat().resolvedOptions().locale; + +let supportedNumberingSystems = ["latn", "arab"].filter(nu => + new Intl.DateTimeFormat(defaultLocale + "-u-nu-" + nu) + .resolvedOptions().numberingSystem === nu +); + +let supportedCalendars = ["gregory", "chinese"].filter(ca => + new Intl.DateTimeFormat(defaultLocale + "-u-ca-" + ca) + .resolvedOptions().calendar === ca +); + +let options = [ + {key: "nu", property: "numberingSystem", type: "string", values: supportedNumberingSystems}, + {key: "ca", property: "calendar", type: "string", values: supportedCalendars} +]; + +options.forEach(function (option) { + let dateTimeFormat, opt, result; + + // find out which values are supported for a property in the default locale + let supportedValues = []; + option.values.forEach(function (value) { + opt = {}; + opt[option.property] = value; + dateTimeFormat = new Intl.DateTimeFormat([defaultLocale], opt); + result = dateTimeFormat.resolvedOptions()[option.property]; + if (result !== undefined && supportedValues.indexOf(result) === -1) { + supportedValues.push(result); + } + }); + + // verify that the supported values can also be set through the locale + supportedValues.forEach(function (value) { + dateTimeFormat = new Intl.DateTimeFormat([defaultLocale + "-u-" + option.key + "-" + value]); + result = dateTimeFormat.resolvedOptions()[option.property]; + assert.sameValue(result, value, "Property " + option.property + " couldn't be set through locale extension key " + option.key + "."); + }); + + // verify that the options setting overrides the locale setting + supportedValues.forEach(function (value) { + let otherValue; + option.values.forEach(function (possibleValue) { + if (possibleValue !== value) { + otherValue = possibleValue; + } + }); + if (otherValue !== undefined) { + opt = {}; + opt[option.property] = value; + dateTimeFormat = new Intl.DateTimeFormat([defaultLocale + "-u-" + option.key + "-" + otherValue], opt); + result = dateTimeFormat.resolvedOptions()[option.property]; + assert.sameValue(result, value, "Options value for property " + option.property + " doesn't override locale extension key " + option.key + "."); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/prop-desc.js new file mode 100644 index 0000000000..7b236b882f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat-intro +description: > + "DateTimeFormat" property of Intl. +info: | + Intl.DateTimeFormat (...) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl, "DateTimeFormat"); +verifyWritable(Intl, "DateTimeFormat"); +verifyConfigurable(Intl, "DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/DateTimeFormat/proto-from-ctor-realm.js new file mode 100644 index 0000000000..118fadf545 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/proto-from-ctor-realm.js @@ -0,0 +1,60 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.DateTimeFormat ( [ locales [ , options ] ] ) + + 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget. + 2. Let dateTimeFormat be ? OrdinaryCreateFromConstructor(newTarget, "%DateTimeFormatPrototype%", « ... »). + ... + 6. Return dateTimeFormat. + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var dtf; + +newTarget.prototype = undefined; +dtf = Reflect.construct(Intl.DateTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(dtf), other.Intl.DateTimeFormat.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +dtf = Reflect.construct(Intl.DateTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(dtf), other.Intl.DateTimeFormat.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = false; +dtf = Reflect.construct(Intl.DateTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(dtf), other.Intl.DateTimeFormat.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = 'str'; +dtf = Reflect.construct(Intl.DateTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(dtf), other.Intl.DateTimeFormat.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +dtf = Reflect.construct(Intl.DateTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(dtf), other.Intl.DateTimeFormat.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = 1; +dtf = Reflect.construct(Intl.DateTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(dtf), other.Intl.DateTimeFormat.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/builtin.js new file mode 100644 index 0000000000..dd849faaef --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/builtin.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.3_L15 +description: > + Tests that Intl.DateTimeFormat.prototype meets the requirements + for built-in objects defined by the introduction of chapter 17 of + the ECMAScript Language Specification. +author: Norbert Lindenberg +---*/ + +assert(Object.isExtensible(Intl.DateTimeFormat.prototype), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.DateTimeFormat.prototype), Object.prototype, + "Built-in prototype objects must have Object.prototype as their prototype."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..13826e9fa1 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.constructor +description: > + "constructor" property of Intl.DateTimeFormat.prototype. +info: | + Intl.DateTimeFormat.prototype.constructor + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.DateTimeFormat.prototype, "constructor"); +verifyWritable(Intl.DateTimeFormat.prototype, "constructor"); +verifyConfigurable(Intl.DateTimeFormat.prototype, "constructor"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/value.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/value.js new file mode 100644 index 0000000000..5092db0768 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/constructor/value.js @@ -0,0 +1,14 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.3.1 +description: > + Tests that Intl.DateTimeFormat.prototype.constructor is the + Intl.DateTimeFormat. +author: Roozbeh Pournader +---*/ + +assert.sameValue(Intl.DateTimeFormat.prototype.constructor, Intl.DateTimeFormat, "Intl.DateTimeFormat.prototype.constructor is not the same as Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/bound-to-datetimeformat-instance.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/bound-to-datetimeformat-instance.js new file mode 100644 index 0000000000..485a7c0720 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/bound-to-datetimeformat-instance.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.3.2_1_c +description: Tests that format function is bound to its Intl.DateTimeFormat. +author: Norbert Lindenberg +---*/ + +var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))]; +var locales = [undefined, ["de"], ["th-u-ca-gregory-nu-thai"], ["en"], ["ja-u-ca-japanese"], ["ar-u-ca-islamicc-nu-arab"]]; +var options = [ + undefined, + {hour12: false}, + {month: "long", day: "numeric", hour: "2-digit", minute: "2-digit"} +]; + +locales.forEach(function (locales) { + options.forEach(function (options) { + var formatObj = new Intl.DateTimeFormat(locales, options); + var formatFunc = formatObj.format; + dates.forEach(function (date) { + var referenceFormatted = formatObj.format(date); + var formatted = formatFunc(date); + assert.sameValue(referenceFormatted, formatted, "format function produces different result than format method for locales " + locales + "; options: " + (options ? JSON.stringify(options) : options) + "."); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/builtin.js new file mode 100644 index 0000000000..c4870b0b57 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/builtin.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.3.2_L15 +description: > + Tests that the getter for Intl.DateTimeFormat.prototype.format + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language + Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +var formatFn = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get; + +assert.sameValue(Object.prototype.toString.call(formatFn), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatFn), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatFn), Function.prototype); + +assert.sameValue(formatFn.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatFn), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/date-constructor-not-called.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/date-constructor-not-called.js new file mode 100644 index 0000000000..f13f9425ce --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/date-constructor-not-called.js @@ -0,0 +1,38 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: | + The Date constructor is not called to convert the input value. +info: > + 12.1.5 DateTime Format Functions + + ... + 3. If date is not provided or is undefined, then + ... + 4. Else, + a. Let x be ? ToNumber(date). + 5. Return FormatDateTime(dtf, x). + + 12.1.6 PartitionDateTimePattern ( dateTimeFormat, x ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. ... +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var dateTimeString = "2017-11-10T14:09:00.000Z"; + +// |dateTimeString| is valid ISO-8601 style date/time string. +assert.notSameValue(new Date(dateTimeString), NaN); + +// Ensure string input values are not converted to time values by calling the +// Date constructor. +assert.throws(RangeError, function() { + dtf.format(dateTimeString); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-long-en.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-long-en.js new file mode 100644 index 0000000000..3af6285060 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-long-en.js @@ -0,0 +1,96 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of dayPeriod, long format. +features: [Intl.DateTimeFormat-dayPeriod] +locale: [en-US] +---*/ + +const d0000 = new Date(2017, 11, 12, 0, 0, 0, 0); +const d0100 = new Date(2017, 11, 12, 1, 0, 0, 0); +const d0200 = new Date(2017, 11, 12, 2, 0, 0, 0); +const d0300 = new Date(2017, 11, 12, 3, 0, 0, 0); +const d0400 = new Date(2017, 11, 12, 4, 0, 0, 0); +const d0500 = new Date(2017, 11, 12, 5, 0, 0, 0); +const d0600 = new Date(2017, 11, 12, 6, 0, 0, 0); +const d0700 = new Date(2017, 11, 12, 7, 0, 0, 0); +const d0800 = new Date(2017, 11, 12, 8, 0, 0, 0); +const d0900 = new Date(2017, 11, 12, 9, 0, 0, 0); +const d1000 = new Date(2017, 11, 12, 10, 0, 0, 0); +const d1100 = new Date(2017, 11, 12, 11, 0, 0, 0); +const d1200 = new Date(2017, 11, 12, 12, 0, 0, 0); +const d1300 = new Date(2017, 11, 12, 13, 0, 0, 0); +const d1400 = new Date(2017, 11, 12, 14, 0, 0, 0); +const d1500 = new Date(2017, 11, 12, 15, 0, 0, 0); +const d1600 = new Date(2017, 11, 12, 16, 0, 0, 0); +const d1700 = new Date(2017, 11, 12, 17, 0, 0, 0); +const d1800 = new Date(2017, 11, 12, 18, 0, 0, 0); +const d1900 = new Date(2017, 11, 12, 19, 0, 0, 0); +const d2000 = new Date(2017, 11, 12, 20, 0, 0, 0); +const d2100 = new Date(2017, 11, 12, 21, 0, 0, 0); +const d2200 = new Date(2017, 11, 12, 22, 0, 0, 0); +const d2300 = new Date(2017, 11, 12, 23, 0, 0, 0); + +const long = new Intl.DateTimeFormat('en', { + dayPeriod: 'long' +}); + +assert.sameValue(long.format(d0000), 'at night', '00:00, long format'); +assert.sameValue(long.format(d0100), 'at night', '01:00, long format'); +assert.sameValue(long.format(d0200), 'at night', '02:00, long format'); +assert.sameValue(long.format(d0300), 'at night', '03:00, long format'); +assert.sameValue(long.format(d0400), 'at night', '04:00, long format'); +assert.sameValue(long.format(d0500), 'at night', '05:00, long format'); +assert.sameValue(long.format(d0600), 'in the morning', '06:00, long format'); +assert.sameValue(long.format(d0700), 'in the morning', '07:00, long format'); +assert.sameValue(long.format(d0800), 'in the morning', '08:00, long format'); +assert.sameValue(long.format(d0900), 'in the morning', '09:00, long format'); +assert.sameValue(long.format(d1000), 'in the morning', '10:00, long format'); +assert.sameValue(long.format(d1100), 'in the morning', '11:00, long format'); +assert.sameValue(long.format(d1200), 'noon', '12:00, long format'); +assert.sameValue(long.format(d1300), 'in the afternoon', '13:00, long format'); +assert.sameValue(long.format(d1400), 'in the afternoon', '14:00, long format'); +assert.sameValue(long.format(d1500), 'in the afternoon', '15:00, long format'); +assert.sameValue(long.format(d1600), 'in the afternoon', '16:00, long format'); +assert.sameValue(long.format(d1700), 'in the afternoon', '17:00, long format'); +assert.sameValue(long.format(d1800), 'in the evening', '18:00, long format'); +assert.sameValue(long.format(d1900), 'in the evening', '19:00, long format'); +assert.sameValue(long.format(d2000), 'in the evening', '20:00, long format'); +assert.sameValue(long.format(d2100), 'at night', '21:00, long format'); +assert.sameValue(long.format(d2200), 'at night', '22:00, long format'); +assert.sameValue(long.format(d2300), 'at night', '23:00, long format'); + +const longNumeric = new Intl.DateTimeFormat('en', { + dayPeriod: 'long', + hour: 'numeric' +}); + +assert.sameValue(longNumeric.format(d0000), '12 at night', '00:00, long-numeric'); +assert.sameValue(longNumeric.format(d0100), '1 at night', '01:00, long-numeric'); +assert.sameValue(longNumeric.format(d0200), '2 at night', '02:00, long-numeric'); +assert.sameValue(longNumeric.format(d0300), '3 at night', '03:00, long-numeric'); +assert.sameValue(longNumeric.format(d0400), '4 at night', '04:00, long-numeric'); +assert.sameValue(longNumeric.format(d0500), '5 at night', '05:00, long-numeric'); +assert.sameValue(longNumeric.format(d0600), '6 in the morning', '06:00, long-numeric'); +assert.sameValue(longNumeric.format(d0700), '7 in the morning', '07:00, long-numeric'); +assert.sameValue(longNumeric.format(d0800), '8 in the morning', '08:00, long-numeric'); +assert.sameValue(longNumeric.format(d0900), '9 in the morning', '09:00, long-numeric'); +assert.sameValue(longNumeric.format(d1000), '10 in the morning', '10:00, long-numeric'); +assert.sameValue(longNumeric.format(d1100), '11 in the morning', '11:00, long-numeric'); +assert.sameValue(longNumeric.format(d1200), '12 noon', '12:00, long-numeric'); +assert.sameValue(longNumeric.format(d1300), '1 in the afternoon', '13:00, long-numeric'); +assert.sameValue(longNumeric.format(d1400), '2 in the afternoon', '14:00, long-numeric'); +assert.sameValue(longNumeric.format(d1500), '3 in the afternoon', '15:00, long-numeric'); +assert.sameValue(longNumeric.format(d1600), '4 in the afternoon', '16:00, long-numeric'); +assert.sameValue(longNumeric.format(d1700), '5 in the afternoon', '17:00, long-numeric'); +assert.sameValue(longNumeric.format(d1800), '6 in the evening', '18:00, long-numeric'); +assert.sameValue(longNumeric.format(d1900), '7 in the evening', '19:00, long-numeric'); +assert.sameValue(longNumeric.format(d2000), '8 in the evening', '20:00, long-numeric'); +assert.sameValue(longNumeric.format(d2100), '9 at night', '21:00, long-numeric'); +assert.sameValue(longNumeric.format(d2200), '10 at night', '22:00, long-numeric'); +assert.sameValue(longNumeric.format(d2300), '11 at night', '23:00, long-numeric'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-narrow-en.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-narrow-en.js new file mode 100644 index 0000000000..9ab465db89 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-narrow-en.js @@ -0,0 +1,96 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of dayPeriod, narrow format. +features: [Intl.DateTimeFormat-dayPeriod] +locale: [en-US] +---*/ + +const d0000 = new Date(2017, 11, 12, 0, 0, 0, 0); +const d0100 = new Date(2017, 11, 12, 1, 0, 0, 0); +const d0200 = new Date(2017, 11, 12, 2, 0, 0, 0); +const d0300 = new Date(2017, 11, 12, 3, 0, 0, 0); +const d0400 = new Date(2017, 11, 12, 4, 0, 0, 0); +const d0500 = new Date(2017, 11, 12, 5, 0, 0, 0); +const d0600 = new Date(2017, 11, 12, 6, 0, 0, 0); +const d0700 = new Date(2017, 11, 12, 7, 0, 0, 0); +const d0800 = new Date(2017, 11, 12, 8, 0, 0, 0); +const d0900 = new Date(2017, 11, 12, 9, 0, 0, 0); +const d1000 = new Date(2017, 11, 12, 10, 0, 0, 0); +const d1100 = new Date(2017, 11, 12, 11, 0, 0, 0); +const d1200 = new Date(2017, 11, 12, 12, 0, 0, 0); +const d1300 = new Date(2017, 11, 12, 13, 0, 0, 0); +const d1400 = new Date(2017, 11, 12, 14, 0, 0, 0); +const d1500 = new Date(2017, 11, 12, 15, 0, 0, 0); +const d1600 = new Date(2017, 11, 12, 16, 0, 0, 0); +const d1700 = new Date(2017, 11, 12, 17, 0, 0, 0); +const d1800 = new Date(2017, 11, 12, 18, 0, 0, 0); +const d1900 = new Date(2017, 11, 12, 19, 0, 0, 0); +const d2000 = new Date(2017, 11, 12, 20, 0, 0, 0); +const d2100 = new Date(2017, 11, 12, 21, 0, 0, 0); +const d2200 = new Date(2017, 11, 12, 22, 0, 0, 0); +const d2300 = new Date(2017, 11, 12, 23, 0, 0, 0); + +const narrow = new Intl.DateTimeFormat('en', { + dayPeriod: 'narrow' +}); + +assert.sameValue(narrow.format(d0000), 'at night', '00:00, narrow format'); +assert.sameValue(narrow.format(d0100), 'at night', '01:00, narrow format'); +assert.sameValue(narrow.format(d0200), 'at night', '02:00, narrow format'); +assert.sameValue(narrow.format(d0300), 'at night', '03:00, narrow format'); +assert.sameValue(narrow.format(d0400), 'at night', '04:00, narrow format'); +assert.sameValue(narrow.format(d0500), 'at night', '05:00, narrow format'); +assert.sameValue(narrow.format(d0600), 'in the morning', '06:00, narrow format'); +assert.sameValue(narrow.format(d0700), 'in the morning', '07:00, narrow format'); +assert.sameValue(narrow.format(d0800), 'in the morning', '08:00, narrow format'); +assert.sameValue(narrow.format(d0900), 'in the morning', '09:00, narrow format'); +assert.sameValue(narrow.format(d1000), 'in the morning', '10:00, narrow format'); +assert.sameValue(narrow.format(d1100), 'in the morning', '11:00, narrow format'); +assert.sameValue(narrow.format(d1200), 'n', '12:00, narrow format'); +assert.sameValue(narrow.format(d1300), 'in the afternoon', '13:00, narrow format'); +assert.sameValue(narrow.format(d1400), 'in the afternoon', '14:00, narrow format'); +assert.sameValue(narrow.format(d1500), 'in the afternoon', '15:00, narrow format'); +assert.sameValue(narrow.format(d1600), 'in the afternoon', '16:00, narrow format'); +assert.sameValue(narrow.format(d1700), 'in the afternoon', '17:00, narrow format'); +assert.sameValue(narrow.format(d1800), 'in the evening', '18:00, narrow format'); +assert.sameValue(narrow.format(d1900), 'in the evening', '19:00, narrow format'); +assert.sameValue(narrow.format(d2000), 'in the evening', '20:00, narrow format'); +assert.sameValue(narrow.format(d2100), 'at night', '21:00, narrow format'); +assert.sameValue(narrow.format(d2200), 'at night', '22:00, narrow format'); +assert.sameValue(narrow.format(d2300), 'at night', '23:00, narrow format'); + +const narrowNumeric = new Intl.DateTimeFormat('en', { + dayPeriod: 'narrow', + hour: 'numeric' +}); + +assert.sameValue(narrowNumeric.format(d0000), '12 at night', '00:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0100), '1 at night', '01:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0200), '2 at night', '02:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0300), '3 at night', '03:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0400), '4 at night', '04:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0500), '5 at night', '05:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0600), '6 in the morning', '06:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0700), '7 in the morning', '07:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0800), '8 in the morning', '08:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d0900), '9 in the morning', '09:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1000), '10 in the morning', '10:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1100), '11 in the morning', '11:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1200), '12 n', '12:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1300), '1 in the afternoon', '13:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1400), '2 in the afternoon', '14:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1500), '3 in the afternoon', '15:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1600), '4 in the afternoon', '16:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1700), '5 in the afternoon', '17:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1800), '6 in the evening', '18:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d1900), '7 in the evening', '19:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d2000), '8 in the evening', '20:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d2100), '9 at night', '21:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d2200), '10 at night', '22:00, narrow-numeric'); +assert.sameValue(narrowNumeric.format(d2300), '11 at night', '23:00, narrow-numeric'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-short-en.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-short-en.js new file mode 100644 index 0000000000..c950aee0ca --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/dayPeriod-short-en.js @@ -0,0 +1,96 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of dayPeriod, short format. +features: [Intl.DateTimeFormat-dayPeriod] +locale: [en-US] +---*/ + +const d0000 = new Date(2017, 11, 12, 0, 0, 0, 0); +const d0100 = new Date(2017, 11, 12, 1, 0, 0, 0); +const d0200 = new Date(2017, 11, 12, 2, 0, 0, 0); +const d0300 = new Date(2017, 11, 12, 3, 0, 0, 0); +const d0400 = new Date(2017, 11, 12, 4, 0, 0, 0); +const d0500 = new Date(2017, 11, 12, 5, 0, 0, 0); +const d0600 = new Date(2017, 11, 12, 6, 0, 0, 0); +const d0700 = new Date(2017, 11, 12, 7, 0, 0, 0); +const d0800 = new Date(2017, 11, 12, 8, 0, 0, 0); +const d0900 = new Date(2017, 11, 12, 9, 0, 0, 0); +const d1000 = new Date(2017, 11, 12, 10, 0, 0, 0); +const d1100 = new Date(2017, 11, 12, 11, 0, 0, 0); +const d1200 = new Date(2017, 11, 12, 12, 0, 0, 0); +const d1300 = new Date(2017, 11, 12, 13, 0, 0, 0); +const d1400 = new Date(2017, 11, 12, 14, 0, 0, 0); +const d1500 = new Date(2017, 11, 12, 15, 0, 0, 0); +const d1600 = new Date(2017, 11, 12, 16, 0, 0, 0); +const d1700 = new Date(2017, 11, 12, 17, 0, 0, 0); +const d1800 = new Date(2017, 11, 12, 18, 0, 0, 0); +const d1900 = new Date(2017, 11, 12, 19, 0, 0, 0); +const d2000 = new Date(2017, 11, 12, 20, 0, 0, 0); +const d2100 = new Date(2017, 11, 12, 21, 0, 0, 0); +const d2200 = new Date(2017, 11, 12, 22, 0, 0, 0); +const d2300 = new Date(2017, 11, 12, 23, 0, 0, 0); + +const short = new Intl.DateTimeFormat('en', { + dayPeriod: 'short' +}); + +assert.sameValue(short.format(d0000), 'at night', '00:00, short format'); +assert.sameValue(short.format(d0100), 'at night', '01:00, short format'); +assert.sameValue(short.format(d0200), 'at night', '02:00, short format'); +assert.sameValue(short.format(d0300), 'at night', '03:00, short format'); +assert.sameValue(short.format(d0400), 'at night', '04:00, short format'); +assert.sameValue(short.format(d0500), 'at night', '05:00, short format'); +assert.sameValue(short.format(d0600), 'in the morning', '06:00, short format'); +assert.sameValue(short.format(d0700), 'in the morning', '07:00, short format'); +assert.sameValue(short.format(d0800), 'in the morning', '08:00, short format'); +assert.sameValue(short.format(d0900), 'in the morning', '09:00, short format'); +assert.sameValue(short.format(d1000), 'in the morning', '10:00, short format'); +assert.sameValue(short.format(d1100), 'in the morning', '11:00, short format'); +assert.sameValue(short.format(d1200), 'noon', '12:00, short format'); +assert.sameValue(short.format(d1300), 'in the afternoon', '13:00, short format'); +assert.sameValue(short.format(d1400), 'in the afternoon', '14:00, short format'); +assert.sameValue(short.format(d1500), 'in the afternoon', '15:00, short format'); +assert.sameValue(short.format(d1600), 'in the afternoon', '16:00, short format'); +assert.sameValue(short.format(d1700), 'in the afternoon', '17:00, short format'); +assert.sameValue(short.format(d1800), 'in the evening', '18:00, short format'); +assert.sameValue(short.format(d1900), 'in the evening', '19:00, short format'); +assert.sameValue(short.format(d2000), 'in the evening', '20:00, short format'); +assert.sameValue(short.format(d2100), 'at night', '21:00, short format'); +assert.sameValue(short.format(d2200), 'at night', '22:00, short format'); +assert.sameValue(short.format(d2300), 'at night', '23:00, short format'); + +const shortNumeric = new Intl.DateTimeFormat('en', { + dayPeriod: 'short', + hour: 'numeric' +}); + +assert.sameValue(shortNumeric.format(d0000), '12 at night', '00:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0100), '1 at night', '01:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0200), '2 at night', '02:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0300), '3 at night', '03:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0400), '4 at night', '04:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0500), '5 at night', '05:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0600), '6 in the morning', '06:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0700), '7 in the morning', '07:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0800), '8 in the morning', '08:00, short-numeric'); +assert.sameValue(shortNumeric.format(d0900), '9 in the morning', '09:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1000), '10 in the morning', '10:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1100), '11 in the morning', '11:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1200), '12 noon', '12:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1300), '1 in the afternoon', '13:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1400), '2 in the afternoon', '14:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1500), '3 in the afternoon', '15:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1600), '4 in the afternoon', '16:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1700), '5 in the afternoon', '17:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1800), '6 in the evening', '18:00, short-numeric'); +assert.sameValue(shortNumeric.format(d1900), '7 in the evening', '19:00, short-numeric'); +assert.sameValue(shortNumeric.format(d2000), '8 in the evening', '20:00, short-numeric'); +assert.sameValue(shortNumeric.format(d2100), '9 at night', '21:00, short-numeric'); +assert.sameValue(shortNumeric.format(d2200), '10 at night', '22:00, short-numeric'); +assert.sameValue(shortNumeric.format(d2300), '11 at night', '23:00, short-numeric'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-builtin.js new file mode 100644 index 0000000000..d5270e354a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-builtin.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.3.2_1_a_L15 +description: > + Tests that the function returned by + Intl.DateTimeFormat.prototype.format meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +var formatFn = new Intl.DateTimeFormat().format; + +assert.sameValue(Object.prototype.toString.call(formatFn), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatFn), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatFn), Function.prototype); + +assert.sameValue(formatFn.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatFn), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-length.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-length.js new file mode 100644 index 0000000000..805c197144 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.format +description: > + The length of the bound DateTime Format function is 1. +info: | + get Intl.DateTimeFormat.prototype.format + + ... + 4. If dtf.[[BoundFormat]] is undefined, then + a. Let F be a new built-in function object as defined in DateTime Format Functions (12.1.5). + b. Let bf be BoundFunctionCreate(F, dft, « »). + c. Perform ! DefinePropertyOrThrow(bf, "length", PropertyDescriptor {[[Value]]: 1, + [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}). + ... + +includes: [propertyHelper.js] +---*/ + +var formatFn = new Intl.DateTimeFormat().format; + +assert.sameValue(formatFn.length, 1); + +verifyNotEnumerable(formatFn, "length"); +verifyNotWritable(formatFn, "length"); +verifyConfigurable(formatFn, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-name.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-name.js new file mode 100644 index 0000000000..73922bca5f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/format-function-name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.format +description: > + The bound DateTimeFormat format function is an anonymous function. +info: | + 12.4.3 get Intl.DateTimeFormat.prototype.compare + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +---*/ + +var formatFn = new Intl.DateTimeFormat().format; + +verifyProperty(formatFn, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/fractionalSecondDigits.js new file mode 100644 index 0000000000..4d5b8db882 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/fractionalSecondDigits.js @@ -0,0 +1,34 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of fractionalSecondDigits. +features: [Intl.DateTimeFormat-fractionalSecondDigits] +locale: [en-US] +---*/ + +const d1 = new Date(2019, 7, 10, 1, 2, 3, 234); +const d2 = new Date(2019, 7, 10, 1, 2, 3, 567); + +let dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: undefined}); +assert.sameValue(dtf.format(d1), "02:03", "no fractionalSecondDigits"); +assert.sameValue(dtf.format(d2), "02:03", "no fractionalSecondDigits"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 1}); +assert.sameValue(dtf.format(d1), "02:03.2", "1 fractionalSecondDigits round down"); +assert.sameValue(dtf.format(d2), "02:03.5", "1 fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 2}); +assert.sameValue(dtf.format(d1), "02:03.23", "2 fractionalSecondDigits round down"); +assert.sameValue(dtf.format(d2), "02:03.56", "2 fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 3}); +assert.sameValue(dtf.format(d1), "02:03.234", "3 fractionalSecondDigits round down"); +assert.sameValue(dtf.format(d2), "02:03.567", "3 fractionalSecondDigits round down"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/length.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/length.js new file mode 100644 index 0000000000..9b9ff002b1 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/length.js @@ -0,0 +1,35 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.format +description: > + get Intl.DateTimeFormat.prototype.format.length is 0. +info: | + get Intl.DateTimeFormat.prototype.format + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format"); + +assert.sameValue(desc.get.length, 0); + +verifyNotEnumerable(desc.get, "length"); +verifyNotWritable(desc.get, "length"); +verifyConfigurable(desc.get, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/name.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/name.js new file mode 100644 index 0000000000..3729320d39 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/name.js @@ -0,0 +1,30 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.format +description: > + get Intl.DateTimeFormat.prototype.format.name is "get format". +info: | + 12.4.3 get Intl.DateTimeFormat.prototype.format + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format"); + +assert.sameValue(desc.get.name, "get format"); + +verifyNotEnumerable(desc.get, "name"); +verifyNotWritable(desc.get, "name"); +verifyConfigurable(desc.get, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/proleptic-gregorian-calendar.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/proleptic-gregorian-calendar.js new file mode 100644 index 0000000000..0a76e32cab --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/proleptic-gregorian-calendar.js @@ -0,0 +1,31 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.3.2_FDT_7_a_iv +description: > + Tests that format uses a proleptic Gregorian calendar with no year + 0. +author: Norbert Lindenberg +---*/ + +var dates = [ + 0, // January 1, 1970 + -62151602400000, // in June 1 BC + -8640000000000000 // beginning of ECMAScript time +]; + +var format = new Intl.DateTimeFormat(["en-US"], {year: "numeric", month: "long", timeZone: "UTC"}); + +// this test requires a Gregorian calendar, which we usually find in the US +assert.sameValue(format.resolvedOptions().calendar, "gregory", "Internal error: Didn't find Gregorian calendar"); + +dates.forEach(function (date) { + var year = new Date(date).getUTCFullYear(); + var expectedYear = year <= 0 ? 1 - year : year; + var expectedYearString = expectedYear.toLocaleString(["en-US"], {useGrouping: false}); + var dateString = format.format(date); + assert.notSameValue(dateString.indexOf(expectedYearString), -1, "Formatted year doesn't contain expected year – expected " + expectedYearString + ", got " + dateString + "."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/prop-desc.js new file mode 100644 index 0000000000..737d4841a2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/prop-desc.js @@ -0,0 +1,37 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.format +description: > + "format" property of Intl.DateTimeFormat.prototype. +info: | + get Intl.DateTimeFormat.prototype.format + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + Every accessor property described in clauses 18 through 26 and in Annex B.2 has the + attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. + If only a get accessor function is described, the set accessor function is the default + value, undefined. If only a set accessor is described the get accessor is the default + value, undefined. + +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format"); + +assert.sameValue(desc.set, undefined); +assert.sameValue(typeof desc.get, "function"); + +verifyNotEnumerable(Intl.DateTimeFormat.prototype, "format"); +verifyConfigurable(Intl.DateTimeFormat.prototype, "format"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/related-year-zh.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/related-year-zh.js new file mode 100644 index 0000000000..eba77bf9e9 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/related-year-zh.js @@ -0,0 +1,19 @@ +// Copyright 2019 Google Inc, Igalia S.L. All rights reserved. +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: > + Checks the output of 'relatedYear' and 'yearName' type, and + the choice of pattern based on calendar. +locale: [zh-u-ca-chinese] +---*/ + +const df = new Intl.DateTimeFormat("zh-u-ca-chinese", {year: "numeric"}); +const date = new Date(2019, 5, 1); +const formatted = df.format(date); +const expected = ["2019己亥年", "己亥年"]; +assert(expected.includes(formatted)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/shell.js new file mode 100644 index 0000000000..a96394ce86 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/shell.js @@ -0,0 +1,50 @@ +// GENERATED, DO NOT EDIT +// file: dateConstants.js +// Copyright (C) 2009 the Sputnik authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of date-centric values +defines: + - date_1899_end + - date_1900_start + - date_1969_end + - date_1970_start + - date_1999_end + - date_2000_start + - date_2099_end + - date_2100_start + - start_of_time + - end_of_time +---*/ + +var date_1899_end = -2208988800001; +var date_1900_start = -2208988800000; +var date_1969_end = -1; +var date_1970_start = 0; +var date_1999_end = 946684799999; +var date_2000_start = 946684800000; +var date_2099_end = 4102444799999; +var date_2100_start = 4102444800000; + +var start_of_time = -8.64e15; +var end_of_time = 8.64e15; + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/taint-Object-prototype.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/taint-Object-prototype.js new file mode 100644 index 0000000000..b4ca8b4b0d --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/taint-Object-prototype.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.3.2_TLT_2 +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintProperties(["weekday", "era", "year", "month", "day", "hour", "minute", "second", "inDST"]); + +var format = new Intl.DateTimeFormat(); +var time = format.format(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/throws-value-non-finite.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/throws-value-non-finite.js new file mode 100644 index 0000000000..598b9ec88e --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/throws-value-non-finite.js @@ -0,0 +1,20 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.3.2_FDT_1 +description: Tests that format handles non-finite values correctly. +author: Norbert Lindenberg +---*/ + +var invalidValues = [NaN, Infinity, -Infinity]; + +var format = new Intl.DateTimeFormat(); + +invalidValues.forEach(function (value) { + assert.throws(RangeError, function() { + var result = format.format(value); + }, "Invalid value " + value + " was not rejected."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/time-clip-near-time-boundaries.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/time-clip-near-time-boundaries.js new file mode 100644 index 0000000000..0c415ec7ea --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/time-clip-near-time-boundaries.js @@ -0,0 +1,39 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: | + TimeClip is applied when calling Intl.DateTimeFormat.prototype.format. +info: > + 12.1.6 PartitionDateTimePattern ( dateTimeFormat, x ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. ... + + 20.3.1.15 TimeClip ( time ) + ... + 2. If abs(time) > 8.64 × 10^15, return NaN. + ... + +includes: [dateConstants.js] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +// Test values near the start of the ECMAScript time range. +assert.throws(RangeError, function() { + dtf.format(start_of_time - 1); +}); +assert.sameValue(typeof dtf.format(start_of_time), "string"); +assert.sameValue(typeof dtf.format(start_of_time + 1), "string"); + +// Test values near the end of the ECMAScript time range. +assert.sameValue(typeof dtf.format(end_of_time - 1), "string"); +assert.sameValue(typeof dtf.format(end_of_time), "string"); +assert.throws(RangeError, function() { + dtf.format(end_of_time + 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/time-clip-to-integer.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/time-clip-to-integer.js new file mode 100644 index 0000000000..d7fbe4db66 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/time-clip-to-integer.js @@ -0,0 +1,39 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: | + TimeClip applies ToInteger on its input value. +info: > + 12.1.6 PartitionDateTimePattern ( dateTimeFormat, x ) + + 1. Let x be TimeClip(x). + 2. ... + + 20.3.1.15 TimeClip ( time ) + ... + 3. Let clippedTime be ! ToInteger(time). + 4. If clippedTime is -0, set clippedTime to +0. + 5. Return clippedTime. +---*/ + +// Switch to a time format instead of using DateTimeFormat's default date-only format. +var dtf = new Intl.DateTimeFormat(undefined, { + hour: "numeric", minute: "numeric", second: "numeric" +}); + +var expected = dtf.format(0); + +assert.sameValue(dtf.format(-0.9), expected, "format(-0.9)"); +assert.sameValue(dtf.format(-0.5), expected, "format(-0.5)"); +assert.sameValue(dtf.format(-0.1), expected, "format(-0.1)"); +assert.sameValue(dtf.format(-Number.MIN_VALUE), expected, "format(-Number.MIN_VALUE)"); +assert.sameValue(dtf.format(-0), expected, "format(-0)"); +assert.sameValue(dtf.format(+0), expected, "format(+0)"); +assert.sameValue(dtf.format(Number.MIN_VALUE), expected, "format(Number.MIN_VALUE)"); +assert.sameValue(dtf.format(0.1), expected, "format(0.1)"); +assert.sameValue(dtf.format(0.5), expected, "format(0.5)"); +assert.sameValue(dtf.format(0.9), expected, "format(0.9)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/timedatestyle-en.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/timedatestyle-en.js new file mode 100644 index 0000000000..b51cb84475 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/format/timedatestyle-en.js @@ -0,0 +1,106 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-date-time-style-pattern +description: Checks basic handling of timeStyle and dateStyle. +features: [Intl.DateTimeFormat-datetimestyle] +locale: [en-US] +---*/ + +const date = new Date("1886-05-01T14:12:47Z"); +const dateOptions = [ + ["full", "Saturday, May 1, 1886"], + ["long", "May 1, 1886"], + ["medium", "May 1, 1886"], + ["short", "5/1/86"], +]; + +const timeOptions = [ + ["full", "2:12:47 PM Coordinated Universal Time", "14:12:47 Coordinated Universal Time"], + ["long", "2:12:47 PM UTC", "14:12:47 UTC"], + ["medium", "2:12:47 PM", "14:12:47"], + ["short", "2:12 PM", "14:12"], +]; + +const options12 = [ + { "hour12": true }, + { "hourCycle": "h11" }, + { "hourCycle": "h12" }, + { "hourCycle": "h23", "hour12": true }, + { "hourCycle": "h24", "hour12": true }, +]; + +const options24 = [ + { "hour12": false }, + { "hourCycle": "h23" }, + { "hourCycle": "h24" }, + { "hourCycle": "h11", "hour12": false }, + { "hourCycle": "h12", "hour12": false }, +]; + +for (const [dateStyle, expected] of dateOptions) { + const dtf = new Intl.DateTimeFormat("en-US", { + dateStyle, + timeZone: "UTC", + }); + + const dateString = dtf.format(date); + assert.sameValue(dateString, expected, `Result for ${dateStyle}`); +} + +for (const [timeStyle, expected12, expected24] of timeOptions) { + const check = (locale, options, expected) => { + const dtf = new Intl.DateTimeFormat(locale, { + timeStyle, + timeZone: "UTC", + ...options + }); + + const dateString = dtf.format(date); + assert.sameValue(dateString, expected, `Result for ${timeStyle} with ${JSON.stringify(options)}`); + }; + + check("en-US", {}, expected12); + check("en-US-u-hc-h11", {}, expected12); + check("en-US-u-hc-h12", {}, expected12); + check("en-US-u-hc-h23", {}, expected24); + check("en-US-u-hc-h24", {}, expected24); + + for (const hourOptions of options12) { + check("en-US", hourOptions, expected12); + check("en-US-u-hc-h11", hourOptions, expected12); + check("en-US-u-hc-h12", hourOptions, expected12); + check("en-US-u-hc-h23", hourOptions, expected12); + check("en-US-u-hc-h24", hourOptions, expected12); + } + + for (const hourOptions of options24) { + check("en-US", hourOptions, expected24); + check("en-US-u-hc-h11", hourOptions, expected24); + check("en-US-u-hc-h12", hourOptions, expected24); + check("en-US-u-hc-h23", hourOptions, expected24); + check("en-US-u-hc-h24", hourOptions, expected24); + } +} + +for (const [dateStyle, expectedDate] of dateOptions) { + for (const [timeStyle, expectedTime] of timeOptions) { + const dtf = new Intl.DateTimeFormat("en-US", { + dateStyle, + timeStyle, + timeZone: "UTC", + }); + const result1 = [expectedDate, ", ", expectedTime].join(""); + const result2 = [expectedDate, " at ", expectedTime].join(""); + + const dateString = dtf.format(date); + assert.sameValue( + [result1, result2].includes(dateString), + true, + `Result for date=${dateStyle} and time=${timeStyle}` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-date-string.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-date-string.js new file mode 100644 index 0000000000..edbcbee2c6 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-date-string.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2017 André Bargull. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + The Date constructor is not called to convert the input value. +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + 8. Return ? FormatDateTimeRange(dtf, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. +features: [Intl.DateTimeFormat-formatRange] +---*/ + +const dtf = new Intl.DateTimeFormat(); +const dateTimeString = "2017-11-10T14:09:00.000Z"; +const date = new Date(dateTimeString); +// |dateTimeString| is valid ISO-8601 style date/time string. +assert.notSameValue(date, NaN); + +// ToNumber() will try to parse the string as an integer and yield NaN, rather +// than attempting to parse it like the Date constructor would. +assert.throws(RangeError, function() { + dtf.formatRange(dateTimeString, date); +}); + +assert.throws(RangeError, function() { + dtf.formatRange(date, dateTimeString); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-near-time-boundaries.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-near-time-boundaries.js new file mode 100644 index 0000000000..3f0141ed42 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-near-time-boundaries.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2017 André Bargull. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + TimeClip is applied when calling Intl.DateTimeFormat.prototype.formatRange. +info: | + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + + TimeClip ( time ) + ... + 2. If abs(time) > 8.64 × 10^15, return NaN. + ... + +includes: [dateConstants.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ + +const dtf = new Intl.DateTimeFormat(); +const date = Date.now(); + +// Test values near the start of the ECMAScript time range. +assert.throws(RangeError, function() { + dtf.formatRange(start_of_time - 1, date); +}); +assert.throws(RangeError, function() { + dtf.formatRange(date, start_of_time - 1); +}); +assert.sameValue(typeof dtf.formatRange(start_of_time, date), "string"); +assert.sameValue(typeof dtf.formatRange(start_of_time + 1, date), "string"); + +// Test values near the end of the ECMAScript time range. +assert.sameValue(typeof dtf.formatRange(date, end_of_time - 1), "string"); +assert.sameValue(typeof dtf.formatRange(date, end_of_time), "string"); +assert.throws(RangeError, function() { + dtf.formatRange(end_of_time + 1, date); +}); +assert.throws(RangeError, function() { + dtf.formatRange(date, end_of_time + 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-to-integer.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-to-integer.js new file mode 100644 index 0000000000..adabb74dc7 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-to-integer.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2017 André Bargull. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + TimeClip applies ToInteger on its input value. +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + + TimeClip ( time ) + ... + 3. Let clippedTime be ! ToInteger(time). + 4. If clippedTime is -0, set clippedTime to +0. + 5. Return clippedTime. +features: [Intl.DateTimeFormat-formatRange] +---*/ + +// Switch to a time format instead of using DateTimeFormat's default date-only format. +const dtf = new Intl.DateTimeFormat(undefined, { + hour: "numeric", minute: "numeric", second: "numeric" +}); +const date = Date.now(); +const expected = dtf.formatRange(0, date); + +assert.sameValue(dtf.formatRange(-0.9, date), expected, "formatRange(-0.9)"); +assert.sameValue(dtf.formatRange(-0.5, date), expected, "formatRange(-0.5)"); +assert.sameValue(dtf.formatRange(-0.1, date), expected, "formatRange(-0.1)"); +assert.sameValue(dtf.formatRange(-Number.MIN_VALUE, date), expected, "formatRange(-Number.MIN_VALUE)"); +assert.sameValue(dtf.formatRange(-0, date), expected, "formatRange(-0)"); +assert.sameValue(dtf.formatRange(+0, date), expected, "formatRange(+0)"); +assert.sameValue(dtf.formatRange(Number.MIN_VALUE, date), expected, "formatRange(Number.MIN_VALUE)"); +assert.sameValue(dtf.formatRange(0.1, date), expected, "formatRange(0.1)"); +assert.sameValue(dtf.formatRange(0.5, date), expected, "formatRange(0.5)"); +assert.sameValue(dtf.formatRange(0.9, date), expected, "formatRange(0.9)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-tonumber-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-tonumber-throws.js new file mode 100644 index 0000000000..a0178e5b92 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/argument-tonumber-throws.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Return abrupt completions from ToNumber(date) +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). +features: [Symbol,Intl.DateTimeFormat-formatRange] +---*/ + +const date = Date.now(); + +const objectValueOf = { + valueOf: function() { + throw new Test262Error(); + } +}; + +const objectToString = { + toString: function() { + throw new Test262Error(); + } +}; + +const dtf = new Intl.DateTimeFormat(["pt-BR"]); + +assert.throws(Test262Error, function() { + dtf.formatRange(objectValueOf, date); +}, "valueOf start"); + +assert.throws(Test262Error, function() { + dtf.formatRange(date, objectValueOf); +}, "valueOf end"); + +assert.throws(Test262Error, function() { + dtf.formatRange(objectToString, date); +}, "toString start"); + +assert.throws(Test262Error, function() { + dtf.formatRange(date, objectToString); +}, "toString end"); + +const s = Symbol('1'); +assert.throws(TypeError, function() { + dtf.formatRange(s, date); +}, "symbol start"); + +assert.throws(TypeError, function() { + dtf.formatRange(date, s); +}, "symbol end"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/builtin.js new file mode 100644 index 0000000000..2b42ca92ea --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Tests that the Intl.DateTimeFormat.prototype.formatRange function meets the + requirements for built-in objects defined by the ECMAScript Language + Specification. +includes: [isConstructor.js] +features: [Reflect.construct,Intl.DateTimeFormat-formatRange] +---*/ + +const formatRange = Intl.DateTimeFormat.prototype.formatRange; + +assert.sameValue(Object.prototype.toString.call(formatRange), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatRange), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatRange), Function.prototype); + +assert.sameValue(formatRange.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatRange), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-is-infinity-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-is-infinity-throws.js new file mode 100644 index 0000000000..9ddfd159e8 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-is-infinity-throws.js @@ -0,0 +1,73 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date arg is cast to an Infinity value +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception. + 4. If startDate is undefined or endDate is undefined, throw a RangeError exception. + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + 7. If x is greater than y, throw a RangeError exception. + 8. Return ? FormatDateTimeRange(dtf, x, y). + + FormatDateTimeRange ( dateTimeFormat, x, y ) + + 1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + + TimeClip ( time ) + 1. If time is not finite, return NaN. + +features: [Intl.DateTimeFormat-formatRange] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var date = new Date(); + +assert.throws(RangeError, function() { + dtf.formatRange(Infinity, date); +}, "+Infinity/date"); + +assert.throws(RangeError, function() { + dtf.formatRange(-Infinity, date); +}, "-Infinity/date"); + +assert.throws(RangeError, function() { + dtf.formatRange(date, Infinity); +}, "date/+Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRange(date, -Infinity); +}, "date/-Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRange(Infinity, Infinity); +}, "+Infinity/+Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRange(-Infinity, -Infinity); +}, "-Infinity/-Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRange(Infinity, -Infinity); +}, "+Infinity/-Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRange(-Infinity, Infinity); +}, "-Infinity/+Infinity"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-is-nan-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-is-nan-throws.js new file mode 100644 index 0000000000..52621dd1a4 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-is-nan-throws.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date arg is cast to NaN +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception. + 4. If startDate is undefined or endDate is undefined, throw a RangeError exception. + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + 7. If x is greater than y, throw a RangeError exception. + 8. Return ? FormatDateTimeRange(dtf, x, y). + + FormatDateTimeRange ( dateTimeFormat, x, y ) + + 1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + +features: [Intl.DateTimeFormat-formatRange] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var date = new Date(); + +assert.throws(RangeError, function() { + dtf.formatRange(NaN, date); +}, "NaN/date"); + +assert.throws(RangeError, function() { + dtf.formatRange(date, NaN); +}, "date/NaN"); + +assert.throws(RangeError, function() { + dtf.formatRange(NaN, NaN); +}, "NaN/NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-same-returns-single-date.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-same-returns-single-date.js new file mode 100644 index 0000000000..684130fc7c --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-same-returns-single-date.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2021 Google Inc. All rights reserved. +// Copyright 2021 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + When startDate is equal to endDate, the output should be a string equal + to the output of Intl.DateTimeFormat.prototype.format. +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 4. Let x be ? ToNumber(startDate). + 5. Let y be ? ToNumber(endDate). + 6. Return ? FormatDateTimeRange(dtf, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 13. If dateFieldsPracticallyEqual is true, then + a. Let pattern be dateTimeFormat.[[Pattern]]. + b. Let patternParts be PartitionPattern(pattern). + c. Let result be ? FormatDateTimePattern(dateTimeFormat, patternParts, tm1). + d. For each r in result do + i. Set r.[[Source]] to "shared". + e. Return result. + +features: [Intl.DateTimeFormat-formatRange] +locale: [en-US] +---*/ + +{ + const date = new Date(2019, 7, 10, 1, 2, 3, 234); + + let dtf = new Intl.DateTimeFormat("en", { year: "numeric", month: "short", day: "numeric" }); + assert.sameValue(dtf.formatRange(date, date), dtf.format(date), "same output with date options"); + + dtf = new Intl.DateTimeFormat("en", { minute: "numeric", second: "numeric" }); + assert.sameValue(dtf.formatRange(date, date), dtf.format(date), "same output with time options"); + + dtf = new Intl.DateTimeFormat("en", { month: "short", day: "numeric", minute: "numeric" }); + assert.sameValue(dtf.formatRange(date, date), dtf.format(date), "same output with date-time options"); + + dtf = new Intl.DateTimeFormat("en", { dateStyle: "long", timeStyle: "short" }); + assert.sameValue(dtf.formatRange(date, date), dtf.format(date), "same output with dateStyle/timeStyle"); +} +{ + const date1 = new Date(2019, 7, 10, 1, 2, 3, 234); + const date2 = new Date(2019, 7, 10, 1, 2, 3, 235); + + let dtf = new Intl.DateTimeFormat("en", { year: "numeric", month: "short", day: "numeric" }); + assert.sameValue(dtf.formatRange(date1, date2), dtf.format(date1), "same output with date options"); + + dtf = new Intl.DateTimeFormat("en", { minute: "numeric", second: "numeric" }); + assert.sameValue(dtf.formatRange(date1, date2), dtf.format(date1), "same output with time options"); + + dtf = new Intl.DateTimeFormat("en", { month: "short", day: "numeric", minute: "numeric" }); + assert.sameValue(dtf.formatRange(date1, date2), dtf.format(date1), "same output with date-time options"); + + dtf = new Intl.DateTimeFormat("en", { dateStyle: "long", timeStyle: "short" }); + assert.sameValue(dtf.formatRange(date1, date2), dtf.format(date1), "same output with dateStyle/timeStyle"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-undefined-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-undefined-throws.js new file mode 100644 index 0000000000..69946151c5 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-undefined-throws.js @@ -0,0 +1,45 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a TypeError if startDate or endDate is undefined. +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception. + 4. If startDate is undefined or endDate is undefined, throw a TypeError exception. + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + +features: [Intl.DateTimeFormat-formatRange] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +assert.throws(TypeError, function() { + dtf.formatRange(); // Not possible to poison this one +}, "no args"); + +var poison = { valueOf() { throw new Test262Error(); } }; + +assert.throws(TypeError, function() { + dtf.formatRange(undefined, poison); +}, "date/undefined"); + +assert.throws(TypeError, function() { + dtf.formatRange(poison, undefined); +}, "undefined/date"); + +assert.throws(TypeError, function() { + dtf.formatRange(poison); +}, "only one arg"); + +assert.throws(TypeError, function() { + dtf.formatRange(undefined, undefined); +}, "undefined/undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-x-greater-than-y-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-x-greater-than-y-throws.js new file mode 100644 index 0000000000..52a44597a9 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/date-x-greater-than-y-throws.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date x is greater than y. +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 4. Let x be ? ToNumber(startDate). + 5. Let y be ? ToNumber(endDate). + 6. Return ? FormatDateTimeRange(dtf, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + 5. If x is greater than y, throw a RangeError exception. + +features: [Intl.DateTimeFormat-formatRange] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var x = new Date(); +var y = new Date(); +x.setDate(y.getDate() + 1); + +assert.throws(RangeError, function() { + dtf.formatRange(x, y); +}, "x > y"); + +assert.sameValue("string", typeof dtf.formatRange(x, x)); +assert.sameValue("string", typeof dtf.formatRange(y, y)); +assert.sameValue("string", typeof dtf.formatRange(y, x)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/en-US.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/en-US.js new file mode 100644 index 0000000000..7fc01e452a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/en-US.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2019 the V8 project authors, Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: Basic tests for the en-US output of formatRange() +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 8. Return ? FormatDateTimeRange(dtf, x, y). +locale: [en-US] +features: [Intl.DateTimeFormat-formatRange] +---*/ + +const date1 = new Date("2019-01-03T00:00:00"); +const date2 = new Date("2019-01-05T00:00:00"); +const date3 = new Date("2019-03-04T00:00:00"); +const date4 = new Date("2020-03-04T00:00:00"); + +let dtf = new Intl.DateTimeFormat("en-US"); +assert.sameValue(dtf.formatRange(date1, date1), "1/3/2019"); +assert.sameValue(dtf.formatRange(date1, date2), "1/3/2019 – 1/5/2019"); +assert.sameValue(dtf.formatRange(date1, date3), "1/3/2019 – 3/4/2019"); +assert.sameValue(dtf.formatRange(date1, date4), "1/3/2019 – 3/4/2020"); +assert.sameValue(dtf.formatRange(date2, date3), "1/5/2019 – 3/4/2019"); +assert.sameValue(dtf.formatRange(date2, date4), "1/5/2019 – 3/4/2020"); +assert.sameValue(dtf.formatRange(date3, date4), "3/4/2019 – 3/4/2020"); + +dtf = new Intl.DateTimeFormat("en-US", {year: "numeric", month: "short", day: "numeric"}); +assert.sameValue(dtf.formatRange(date1, date1), "Jan 3, 2019"); +assert.sameValue(dtf.formatRange(date1, date2), "Jan 3 – 5, 2019"); +assert.sameValue(dtf.formatRange(date1, date3), "Jan 3 – Mar 4, 2019"); +assert.sameValue(dtf.formatRange(date1, date4), "Jan 3, 2019 – Mar 4, 2020"); +assert.sameValue(dtf.formatRange(date2, date3), "Jan 5 – Mar 4, 2019"); +assert.sameValue(dtf.formatRange(date2, date4), "Jan 5, 2019 – Mar 4, 2020"); +assert.sameValue(dtf.formatRange(date3, date4), "Mar 4, 2019 – Mar 4, 2020"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/fractionalSecondDigits.js new file mode 100644 index 0000000000..89b83aeacb --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/fractionalSecondDigits.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of fractionalSecondDigits. +features: [Intl.DateTimeFormat-fractionalSecondDigits, Intl.DateTimeFormat-formatRange] +locale: [en-US] +---*/ + +const d1 = new Date(2019, 7, 10, 1, 2, 3, 234); +const d2 = new Date(2019, 7, 10, 1, 2, 3, 567); +const d3 = new Date(2019, 7, 10, 1, 2, 13, 987); + +let dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: undefined}); +assert.sameValue(dtf.formatRange(d1, d2), "02:03", "no fractionalSecondDigits"); +assert.sameValue(dtf.formatRange(d1, d3), "02:03 – 02:13", "no fractionalSecondDigits"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 1}); +assert.sameValue(dtf.formatRange(d1, d2), "02:03.2 – 02:03.5", "1 fractionalSecondDigits round down"); +assert.sameValue(dtf.formatRange(d1, d3), "02:03.2 – 02:13.9", "1 fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 2}); +assert.sameValue(dtf.formatRange(d1, d2), "02:03.23 – 02:03.56", "2 fractionalSecondDigits round down"); +assert.sameValue(dtf.formatRange(d1, d3), "02:03.23 – 02:13.98", "2 fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 3}); +assert.sameValue(dtf.formatRange(d1, d2), "02:03.234 – 02:03.567", "3 fractionalSecondDigits round down"); +assert.sameValue(dtf.formatRange(d1, d3), "02:03.234 – 02:13.987", "3 fractionalSecondDigits round down"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/length.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/length.js new file mode 100644 index 0000000000..f2f1997596 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.DateTimeFormat.prototype.formatRange.length. +includes: [propertyHelper.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ +verifyProperty(Intl.DateTimeFormat.prototype.formatRange, 'length', { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/name.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/name.js new file mode 100644 index 0000000000..1ef3d5199a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/name.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.DateTimeFormat.prototype.formatRange.name value and descriptor. +includes: [propertyHelper.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ +verifyProperty(Intl.DateTimeFormat.prototype.formatRange, 'name', { + value: 'formatRange', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/prop-desc.js new file mode 100644 index 0000000000..c628b1866b --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2016 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Property type and descriptor. +includes: [propertyHelper.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ + +assert.sameValue( + typeof Intl.DateTimeFormat.prototype.formatRange, + 'function', + '`typeof Intl.DateTimeFormat.prototype.formatRange` is `function`' +); + +verifyProperty(Intl.DateTimeFormat.prototype, 'formatRange', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/shell.js new file mode 100644 index 0000000000..a96394ce86 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/shell.js @@ -0,0 +1,50 @@ +// GENERATED, DO NOT EDIT +// file: dateConstants.js +// Copyright (C) 2009 the Sputnik authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of date-centric values +defines: + - date_1899_end + - date_1900_start + - date_1969_end + - date_1970_start + - date_1999_end + - date_2000_start + - date_2099_end + - date_2100_start + - start_of_time + - end_of_time +---*/ + +var date_1899_end = -2208988800001; +var date_1900_start = -2208988800000; +var date_1969_end = -1; +var date_1970_start = 0; +var date_1999_end = 946684799999; +var date_2000_start = 946684800000; +var date_2099_end = 4102444799999; +var date_2100_start = 4102444800000; + +var start_of_time = -8.64e15; +var end_of_time = 8.64e15; + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/this-bad-object.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/this-bad-object.js new file mode 100644 index 0000000000..f3bf16339f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/this-bad-object.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Throws a TypeError if this is not a DateTimeFormat object +features: [Intl.DateTimeFormat-formatRange] +---*/ + +const formatRange = Intl.DateTimeFormat.prototype.formatRange; + +assert.throws(TypeError, function() { + formatRange.call({}); +}, "{}"); + +assert.throws(TypeError, function() { + formatRange.call(new Date()); +}, "new Date()"); + +assert.throws(TypeError, function() { + formatRange.call(Intl.DateTimeFormat); +}, "Intl.DateTimeFormat"); + +assert.throws(TypeError, function() { + formatRange.call(Intl.DateTimeFormat.prototype); +}, "Intl.DateTimeFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/this-is-not-object-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/this-is-not-object-throws.js new file mode 100644 index 0000000000..8bd0016e2f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRange/this-is-not-object-throws.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a TypeError if this is not Object. +info: | + Intl.DateTimeFormat.prototype.formatRange ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + +features: [Intl.DateTimeFormat-formatRange, Symbol] +---*/ + +let formatRange = Intl.DateTimeFormat.prototype.formatRange; +let d1 = new Date("1997-08-22T00:00"); +let d2 = new Date("1999-06-26T00:00"); + +assert.throws(TypeError, function() { + formatRange.call(undefined, d1, d2); +}, "undefined"); + +assert.throws(TypeError, function() { + formatRange.call(null, d1, d2); +}, "null"); + +assert.throws(TypeError, function() { + formatRange.call(42, d1, d2); +}, "number"); + +assert.throws(TypeError, function() { + formatRange.call("foo", d1, d2); +}, "string"); + +assert.throws(TypeError, function() { + formatRange.call(false, d1, d2); +}, "false"); + +assert.throws(TypeError, function() { + formatRange.call(true, d1, d2); +}, "true"); + +var s = Symbol('3'); +assert.throws(TypeError, function() { + formatRange.call(s, d1, d2); +}, "symbol"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-date-string.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-date-string.js new file mode 100644 index 0000000000..b61c8219c6 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-date-string.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2017 André Bargull. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + The Date constructor is not called to convert the input value. +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + 8. Return ? FormatDateTimeRange(dtf, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. +features: [Intl.DateTimeFormat-formatRange] +---*/ + +const dtf = new Intl.DateTimeFormat(); +const dateTimeString = "2017-11-10T14:09:00.000Z"; +const date = new Date(dateTimeString); +// |dateTimeString| is valid ISO-8601 style date/time string. +assert.notSameValue(date, NaN); + +// ToNumber() will try to parse the string as an integer and yield NaN, rather +// than attempting to parse it like the Date constructor would. +assert.throws(RangeError, function() { + dtf.formatRangeToParts(dateTimeString, date); +}); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(date, dateTimeString); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-near-time-boundaries.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-near-time-boundaries.js new file mode 100644 index 0000000000..1ce7ce1e7c --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-near-time-boundaries.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2017 André Bargull. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + TimeClip is applied when calling Intl.DateTimeFormat.prototype.formatRangeToParts. +info: | + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + + TimeClip ( time ) + ... + 2. If abs(time) > 8.64 × 10^15, return NaN. + ... + +includes: [dateConstants.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ + +const dtf = new Intl.DateTimeFormat(); +const date = Date.now(); + +// Test values near the start of the ECMAScript time range. +assert.throws(RangeError, function() { + dtf.formatRangeToParts(start_of_time - 1, date); +}); +assert.throws(RangeError, function() { + dtf.formatRangeToParts(date, start_of_time - 1); +}); +assert.sameValue(typeof dtf.formatRangeToParts(start_of_time, date), "object"); +assert.sameValue(typeof dtf.formatRangeToParts(start_of_time + 1, date), "object"); + +// Test values near the end of the ECMAScript time range. +assert.sameValue(typeof dtf.formatRangeToParts(date, end_of_time - 1), "object"); +assert.sameValue(typeof dtf.formatRangeToParts(date, end_of_time), "object"); +assert.throws(RangeError, function() { + dtf.formatRangeToParts(end_of_time + 1, date); +}); +assert.throws(RangeError, function() { + dtf.formatRangeToParts(date, end_of_time + 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-to-integer.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-to-integer.js new file mode 100644 index 0000000000..eb36b29eac --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-to-integer.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2017 André Bargull. All rights reserved. +// Copyright (C) 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + TimeClip applies ToInteger on its input value. +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + + TimeClip ( time ) + ... + 3. Let clippedTime be ! ToInteger(time). + 4. If clippedTime is -0, set clippedTime to +0. + 5. Return clippedTime. +features: [Intl.DateTimeFormat-formatRange] +---*/ + +function* zip(a, b) { + assert.sameValue(a.length, b.length); + for (let i = 0; i < a.length; ++i) { + yield [i, a[i], b[i]]; + } +} + +function compare(actual, expected, message) { + for (const [i, actualEntry, expectedEntry] of zip(actual, expected)) { + assert.sameValue(actualEntry.type, expectedEntry.type, `${message}: type for entry ${i}`); + assert.sameValue(actualEntry.value, expectedEntry.value, `${message}: value for entry ${i}`); + assert.sameValue(actualEntry.source, expectedEntry.source, `${message}: source for entry ${i}`); + } +} + +// Switch to a time format instead of using DateTimeFormat's default date-only format. +const dtf = new Intl.DateTimeFormat(undefined, { + hour: "numeric", minute: "numeric", second: "numeric" +}); +const date = Date.now(); +const expected = dtf.formatRangeToParts(0, date); + +compare(dtf.formatRangeToParts(-0.9, date), expected, "formatRangeToParts(-0.9)"); +compare(dtf.formatRangeToParts(-0.5, date), expected, "formatRangeToParts(-0.5)"); +compare(dtf.formatRangeToParts(-0.1, date), expected, "formatRangeToParts(-0.1)"); +compare(dtf.formatRangeToParts(-Number.MIN_VALUE, date), expected, "formatRangeToParts(-Number.MIN_VALUE)"); +compare(dtf.formatRangeToParts(-0, date), expected, "formatRangeToParts(-0)"); +compare(dtf.formatRangeToParts(+0, date), expected, "formatRangeToParts(+0)"); +compare(dtf.formatRangeToParts(Number.MIN_VALUE, date), expected, "formatRangeToParts(Number.MIN_VALUE)"); +compare(dtf.formatRangeToParts(0.1, date), expected, "formatRangeToParts(0.1)"); +compare(dtf.formatRangeToParts(0.5, date), expected, "formatRangeToParts(0.5)"); +compare(dtf.formatRangeToParts(0.9, date), expected, "formatRangeToParts(0.9)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-tonumber-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-tonumber-throws.js new file mode 100644 index 0000000000..287c853cc1 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/argument-tonumber-throws.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Return abrupt completions from ToNumber(date) +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). +features: [Symbol,Intl.DateTimeFormat-formatRange] +---*/ + +const date = Date.now(); + +const objectValueOf = { + valueOf: function() { + throw new Test262Error(); + } +}; + +const objectToString = { + toString: function() { + throw new Test262Error(); + } +}; + +const dtf = new Intl.DateTimeFormat(["pt-BR"]); + +assert.throws(Test262Error, function() { + dtf.formatRangeToParts(objectValueOf, date); +}, "valueOf start"); + +assert.throws(Test262Error, function() { + dtf.formatRangeToParts(date, objectValueOf); +}, "valueOf end"); + +assert.throws(Test262Error, function() { + dtf.formatRangeToParts(objectToString, date); +}, "toString start"); + +assert.throws(Test262Error, function() { + dtf.formatRangeToParts(date, objectToString); +}, "toString end"); + +const s = Symbol('1'); +assert.throws(TypeError, function() { + dtf.formatRangeToParts(s, date); +}, "symbol start"); + +assert.throws(TypeError, function() { + dtf.formatRangeToParts(date, s); +}, "symbol end"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/builtin.js new file mode 100644 index 0000000000..6807ddf6b0 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2012 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Tests that the Intl.DateTimeFormat.prototype.formatRangeToParts function meets the + requirements for built-in objects defined by the ECMAScript Language + Specification. +includes: [isConstructor.js] +features: [Reflect.construct,Intl.DateTimeFormat-formatRange] +---*/ + +const formatRangeToParts = Intl.DateTimeFormat.prototype.formatRangeToParts; + +assert.sameValue(Object.prototype.toString.call(formatRangeToParts), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatRangeToParts), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatRangeToParts), Function.prototype); + +assert.sameValue(formatRangeToParts.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatRangeToParts), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-is-infinity-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-is-infinity-throws.js new file mode 100644 index 0000000000..d9d9b27c9d --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-is-infinity-throws.js @@ -0,0 +1,72 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date arg is cast to an Infinity value +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception. + 4. If startDate is undefined or endDate is undefined, throw a RangeError exception. + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + 7. If x is greater than y, throw a RangeError exception. + 8. Return ? FormatDateTimeRangeToParts(dtf, x, y). + + FormatDateTimeRangeToParts ( dateTimeFormat, x, y ) + + 1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + + TimeClip ( time ) + 1. If time is not finite, return NaN. + +features: [Intl.DateTimeFormat-formatRange] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var date = new Date(); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(Infinity, date); +}, "+Infinity/date"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(-Infinity, date); +}, "-Infinity/date"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(date, Infinity); +}, "date/+Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(date, -Infinity); +}, "date/-Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(Infinity, Infinity); +}, "+Infinity/+Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(-Infinity, -Infinity); +}, "-Infinity/-Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(Infinity, -Infinity); +}, "+Infinity/-Infinity"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(-Infinity, Infinity); +}, "-Infinity/+Infinity"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-is-nan-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-is-nan-throws.js new file mode 100644 index 0000000000..22d3f5af15 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-is-nan-throws.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date arg is cast to Nan +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception. + 4. If startDate is undefined or endDate is undefined, throw a RangeError exception. + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + 7. If x is greater than y, throw a RangeError exception. + 8. Return ? FormatDateTimeRangeToParts(dtf, x, y). + + FormatDateTimeRangeToParts ( dateTimeFormat, x, y ) + + 1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + +features: [Intl.DateTimeFormat-formatRange] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var date = new Date(); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(NaN, date); +}, "NaN/date"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(date, NaN); +}, "date/NaN"); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(NaN, NaN); +}, "NaN/NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-same-returns-single-date.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-same-returns-single-date.js new file mode 100644 index 0000000000..d12c7bb9a8 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-same-returns-single-date.js @@ -0,0 +1,79 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2021 Google Inc. All rights reserved. +// Copyright 2021 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: > + When startDate is equal to endDate, the output should be an Array of objects with the + same value for the `type` and `value` fields as in the Array returned by + Intl.DateTimeFormat.prototype.formatToParts. +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 4. Let x be ? ToNumber(startDate). + 5. Let y be ? ToNumber(endDate). + 6. Return ? FormatDateTimeRange(dtf, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 13. If dateFieldsPracticallyEqual is true, then + a. Let pattern be dateTimeFormat.[[Pattern]]. + b. Let patternParts be PartitionPattern(pattern). + c. Let result be ? FormatDateTimePattern(dateTimeFormat, patternParts, tm1). + d. For each r in result do + i. Set r.[[Source]] to "shared". + e. Return result. + +features: [Intl.DateTimeFormat-formatRange] +locale: [en-US] +---*/ + +function* zip(a, b) { + assert.sameValue(a.length, b.length); + for (let i = 0; i < a.length; ++i) { + yield [i, a[i], b[i]]; + } +} + +function compare(actual, expected) { + for (const [i, actualEntry, expectedEntry] of zip(actual, expected)) { + assert.sameValue(actualEntry.type, expectedEntry.type, `type for entry ${i}`); + assert.sameValue(actualEntry.value, expectedEntry.value, `value for entry ${i}`); + } +} + +{ + const date = new Date(2019, 7, 10, 1, 2, 3, 234); + + let dtf = new Intl.DateTimeFormat("en", { year: "numeric", month: "short", day: "numeric" }); + compare(dtf.formatRangeToParts(date, date), dtf.formatToParts(date), "same output with date options"); + + dtf = new Intl.DateTimeFormat("en", { minute: "numeric", second: "numeric" }); + compare(dtf.formatRangeToParts(date, date), dtf.formatToParts(date), "same output with time options"); + + dtf = new Intl.DateTimeFormat("en", { month: "short", day: "numeric", minute: "numeric" }); + compare(dtf.formatRangeToParts(date, date), dtf.formatToParts(date), "same output with date-time options"); + + dtf = new Intl.DateTimeFormat("en", { dateStyle: "long", timeStyle: "short" }); + compare(dtf.formatRangeToParts(date, date), dtf.formatToParts(date), "same output with dateStyle/timeStyle"); +} +{ + const date1 = new Date(2019, 7, 10, 1, 2, 3, 234); + const date2 = new Date(2019, 7, 10, 1, 2, 3, 235); + + let dtf = new Intl.DateTimeFormat("en", { year: "numeric", month: "short", day: "numeric" }); + compare(dtf.formatRangeToParts(date1, date2), dtf.formatToParts(date1), "same output with date options"); + + dtf = new Intl.DateTimeFormat("en", { minute: "numeric", second: "numeric" }); + compare(dtf.formatRangeToParts(date1, date2), dtf.formatToParts(date1), "same output with time options"); + + dtf = new Intl.DateTimeFormat("en", { month: "short", day: "numeric", minute: "numeric" }); + compare(dtf.formatRangeToParts(date1, date2), dtf.formatToParts(date1), "same output with date-time options"); + + dtf = new Intl.DateTimeFormat("en", { dateStyle: "long", timeStyle: "short" }); + compare(dtf.formatRangeToParts(date1, date2), dtf.formatToParts(date1), "same output with dateStyle/timeStyle"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-undefined-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-undefined-throws.js new file mode 100644 index 0000000000..7ac2c44bd1 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-undefined-throws.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a TypeError if startDate or endDate are undefined. +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception. + 4. If startDate is undefined or endDate is undefined, throw a TypeError exception. + 5. Let x be ? ToNumber(startDate). + 6. Let y be ? ToNumber(endDate). + +features: [Intl.DateTimeFormat-formatRange] +---*/ +var dtf = new Intl.DateTimeFormat(); + +assert.throws(TypeError, function() { + dtf.formatRangeToParts(); // Not possible to poison this one +}, "no args"); + +var poison = { valueOf() { throw new Test262Error(); } }; + +assert.throws(TypeError, function() { + dtf.formatRangeToParts(undefined, poison); +}, "date/undefined"); + +assert.throws(TypeError, function() { + dtf.formatRangeToParts(poison, undefined); +}, "undefined/date"); + +assert.throws(TypeError, function() { + dtf.formatRangeToParts(poison); +}, "only one arg"); + +assert.throws(TypeError, function() { + dtf.formatRangeToParts(undefined, undefined); +}, "undefined/undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-x-greater-than-y-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-x-greater-than-y-throws.js new file mode 100644 index 0000000000..ab7032065f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/date-x-greater-than-y-throws.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date x is greater than y. +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 4. Let x be ? ToNumber(startDate). + 5. Let y be ? ToNumber(endDate). + 6. Return ? FormatDateTimeRangeToParts(dtf, x, y). + + PartitionDateTimeRangePattern ( dateTimeFormat, x, y ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. Let y be TimeClip(y). + 4. If y is NaN, throw a RangeError exception. + 5. If x is greater than y, throw a RangeError exception. + +features: [Intl.DateTimeFormat-formatRange] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var x = new Date(); +var y = new Date(); +x.setDate(y.getDate() + 1); + +assert.throws(RangeError, function() { + dtf.formatRangeToParts(x, y); +}, "x > y"); +assert.sameValue("object", typeof dtf.formatRangeToParts(x, x)); +assert.sameValue("object", typeof dtf.formatRangeToParts(y, y)); +assert.sameValue("object", typeof dtf.formatRangeToParts(y, x)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/en-US.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/en-US.js new file mode 100644 index 0000000000..563acdd47c --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/en-US.js @@ -0,0 +1,202 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright (C) 2019 the V8 project authors, Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimerangepattern +description: Basic tests for the en-US output of formatRangeToParts() +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 8. Return ? FormatDateTimeRange(dtf, x, y). +locale: [en-US] +features: [Intl.DateTimeFormat-formatRange] +---*/ + +function* zip(a, b) { + assert.sameValue(a.length, b.length); + for (let i = 0; i < a.length; ++i) { + yield [i, a[i], b[i]]; + } +} + +function compare(actual, expected) { + for (const [i, actualEntry, expectedEntry] of zip(actual, expected)) { + assert.sameValue(actualEntry.type, expectedEntry.type, `type for entry ${i}`); + assert.sameValue(actualEntry.value, expectedEntry.value, `value for entry ${i}`); + assert.sameValue(actualEntry.source, expectedEntry.source, `source for entry ${i}`); + } +} + +const date1 = new Date("2019-01-03T00:00:00"); +const date2 = new Date("2019-01-05T00:00:00"); +const date3 = new Date("2019-03-04T00:00:00"); +const date4 = new Date("2020-03-04T00:00:00"); + +let dtf = new Intl.DateTimeFormat("en-US"); +compare(dtf.formatRangeToParts(date1, date1), [ + { type: "month", value: "1", source: "shared" }, + { type: "literal", value: "/", source: "shared" }, + { type: "day", value: "3", source: "shared" }, + { type: "literal", value: "/", source: "shared" }, + { type: "year", value: "2019", source: "shared" }, +]); +compare(dtf.formatRangeToParts(date1, date2), [ + { type: "month", value: "1", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "3", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "1", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "5", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2019", source: "endRange" }, +]); +compare(dtf.formatRangeToParts(date1, date3), [ + { type: "month", value: "1", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "3", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "3", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2019", source: "endRange" }, +]); +compare(dtf.formatRangeToParts(date1, date4), [ + { type: "month", value: "1", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "3", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "3", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2020", source: "endRange" }, +]); +compare(dtf.formatRangeToParts(date2, date3), [ + { type: "month", value: "1", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "5", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "3", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2019", source: "endRange" }, +]); +compare(dtf.formatRangeToParts(date2, date4), [ + { type: "month", value: "1", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "5", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "3", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2020", source: "endRange" }, +]); +compare(dtf.formatRangeToParts(date3, date4), [ + { type: "month", value: "3", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "day", value: "4", source: "startRange" }, + { type: "literal", value: "/", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "3", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: "/", source: "endRange" }, + { type: "year", value: "2020", source: "endRange" }, +]); + +dtf = new Intl.DateTimeFormat("en-US", {year: "numeric", month: "short", day: "numeric"}); +compare(dtf.formatRangeToParts(date1, date1), [ + { type: "month", value: "Jan", source: "shared" }, + { type: "literal", value: " ", source: "shared" }, + { type: "day", value: "3", source: "shared" }, + { type: "literal", value: ", ", source: "shared" }, + { type: "year", value: "2019", source: "shared" }, +]); +compare(dtf.formatRangeToParts(date1, date2), [ + { type: "month", value: "Jan", source: "shared" }, + { type: "literal", value: " ", source: "shared" }, + { type: "day", value: "3", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "day", value: "5", source: "endRange" }, + { type: "literal", value: ", ", source: "shared" }, + { type: "year", value: "2019", source: "shared" }, +]); +compare(dtf.formatRangeToParts(date1, date3), [ + { type: "month", value: "Jan", source: "startRange" }, + { type: "literal", value: " ", source: "startRange" }, + { type: "day", value: "3", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "Mar", source: "endRange" }, + { type: "literal", value: " ", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: ", ", source: "shared" }, + { type: "year", value: "2019", source: "shared" }, +]); +compare(dtf.formatRangeToParts(date1, date4), [ + { type: "month", value: "Jan", source: "startRange" }, + { type: "literal", value: " ", source: "startRange" }, + { type: "day", value: "3", source: "startRange" }, + { type: "literal", value: ", ", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "Mar", source: "endRange" }, + { type: "literal", value: " ", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: ", ", source: "endRange" }, + { type: "year", value: "2020", source: "endRange" }, +]); +compare(dtf.formatRangeToParts(date2, date3), [ + { type: "month", value: "Jan", source: "startRange" }, + { type: "literal", value: " ", source: "startRange" }, + { type: "day", value: "5", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "Mar", source: "endRange" }, + { type: "literal", value: " ", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: ", ", source: "shared" }, + { type: "year", value: "2019", source: "shared" }, +]); +compare(dtf.formatRangeToParts(date2, date4), [ + { type: "month", value: "Jan", source: "startRange" }, + { type: "literal", value: " ", source: "startRange" }, + { type: "day", value: "5", source: "startRange" }, + { type: "literal", value: ", ", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "Mar", source: "endRange" }, + { type: "literal", value: " ", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: ", ", source: "endRange" }, + { type: "year", value: "2020", source: "endRange" }, +]); +compare(dtf.formatRangeToParts(date3, date4), [ + { type: "month", value: "Mar", source: "startRange" }, + { type: "literal", value: " ", source: "startRange" }, + { type: "day", value: "4", source: "startRange" }, + { type: "literal", value: ", ", source: "startRange" }, + { type: "year", value: "2019", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "month", value: "Mar", source: "endRange" }, + { type: "literal", value: " ", source: "endRange" }, + { type: "day", value: "4", source: "endRange" }, + { type: "literal", value: ", ", source: "endRange" }, + { type: "year", value: "2020", source: "endRange" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/fractionalSecondDigits.js new file mode 100644 index 0000000000..d6af440b80 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/fractionalSecondDigits.js @@ -0,0 +1,154 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2020 Google Inc, Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of fractionalSecondDigits. +features: [Intl.DateTimeFormat-fractionalSecondDigits, Intl.DateTimeFormat-formatRange] +locale: [en-US] +---*/ + +function* zip(a, b) { + assert.sameValue(a.length, b.length); + for (let i = 0; i < a.length; ++i) { + yield [i, a[i], b[i]]; + } +} + +function compare(actual, expected) { + for (const [i, actualEntry, expectedEntry] of zip(actual, expected)) { + assert.sameValue(actualEntry.type, expectedEntry.type, `type for entry ${i}`); + assert.sameValue(actualEntry.value, expectedEntry.value, `value for entry ${i}`); + assert.sameValue(actualEntry.source, expectedEntry.source, `source for entry ${i}`); + } +} + +const d1 = new Date(2019, 7, 10, 1, 2, 3, 234); +const d2 = new Date(2019, 7, 10, 1, 2, 3, 567); +const d3 = new Date(2019, 7, 10, 1, 2, 13, 987); + +assert.throws(RangeError, () => { + new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 0}); + }, "fractionalSecondDigits 0 should throw RangeError for out of range"); + +assert.throws(RangeError, () => { + new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 4}); + }, "fractionalSecondDigits 4 should throw RangeError for out of range"); + +let dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: undefined}); + +compare(dtf.formatRangeToParts(d1, d2), [ + { type: "minute", value: "02", source: "shared" }, + { type: "literal", value: ":", source: "shared" }, + { type: "second", value: "03", source: "shared" } +]); + +compare(dtf.formatRangeToParts(d1, d3), [ + { type: "minute", value: "02", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "03", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "minute", value: "02", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "13", source: "endRange" } +]); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 1}); + +compare(dtf.formatRangeToParts(d1, d2), [ + { type: "minute", value: "02", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "03", source: "startRange" }, + { type: "literal", value: ".", source: "startRange" }, + { type: "fractionalSecond", value: "2", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "minute", value: "02", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "03", source: "endRange" }, + { type: "literal", value: ".", source: "endRange" }, + { type: "fractionalSecond", value: "5", source: "endRange" } +]); + +compare(dtf.formatRangeToParts(d1, d3), [ + { type: "minute", value: "02", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "03", source: "startRange" }, + { type: "literal", value: ".", source: "startRange" }, + { type: "fractionalSecond", value: "2", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "minute", value: "02", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "13", source: "endRange" }, + { type: "literal", value: ".", source: "endRange" }, + { type: "fractionalSecond", value: "9", source: "endRange" } +]); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 2}); + +compare(dtf.formatRangeToParts(d1, d2), [ + { type: "minute", value: "02", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "03", source: "startRange" }, + { type: "literal", value: ".", source: "startRange" }, + { type: "fractionalSecond", value: "23", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "minute", value: "02", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "03", source: "endRange" }, + { type: "literal", value: ".", source: "endRange" }, + { type: "fractionalSecond", value: "56", source: "endRange" } +]); + +compare(dtf.formatRangeToParts(d1, d3), [ + { type: "minute", value: "02", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "03", source: "startRange" }, + { type: "literal", value: ".", source: "startRange" }, + { type: "fractionalSecond", value: "23", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "minute", value: "02", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "13", source: "endRange" }, + { type: "literal", value: ".", source: "endRange" }, + { type: "fractionalSecond", value: "98", source: "endRange" } +]); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 3}); + +compare(dtf.formatRangeToParts(d1, d2), [ + { type: "minute", value: "02", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "03", source: "startRange" }, + { type: "literal", value: ".", source: "startRange" }, + { type: "fractionalSecond", value: "234", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "minute", value: "02", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "03", source: "endRange" }, + { type: "literal", value: ".", source: "endRange" }, + { type: "fractionalSecond", value: "567", source: "endRange" } +]); + +compare(dtf.formatRangeToParts(d1, d3), [ + { type: "minute", value: "02", source: "startRange" }, + { type: "literal", value: ":", source: "startRange" }, + { type: "second", value: "03", source: "startRange" }, + { type: "literal", value: ".", source: "startRange" }, + { type: "fractionalSecond", value: "234", source: "startRange" }, + { type: "literal", value: " \u2013 ", source: "shared" }, + { type: "minute", value: "02", source: "endRange" }, + { type: "literal", value: ":", source: "endRange" }, + { type: "second", value: "13", source: "endRange" }, + { type: "literal", value: ".", source: "endRange" }, + { type: "fractionalSecond", value: "987", source: "endRange" } +]); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/length.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/length.js new file mode 100644 index 0000000000..d737e906ea --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.DateTimeFormat.prototype.formatRangeToParts.length. +includes: [propertyHelper.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ +verifyProperty(Intl.DateTimeFormat.prototype.formatRangeToParts, 'length', { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/name.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/name.js new file mode 100644 index 0000000000..a125c4bdda --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/name.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Intl.DateTimeFormat.prototype.formatRangeToParts.name value and descriptor. +includes: [propertyHelper.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ +verifyProperty(Intl.DateTimeFormat.prototype.formatRangeToParts, 'name', { + value: 'formatRangeToParts', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/pattern-on-calendar.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/pattern-on-calendar.js new file mode 100644 index 0000000000..7161f44804 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/pattern-on-calendar.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks the DateTimeFormat choose different patterns based + on calendar. +features: [Intl.DateTimeFormat-formatRange] +locale: [en] +---*/ + +let calendars = [ + "buddhist", + "chinese", + "coptic", + "dangi", + "ethiopic", + "ethioaa", + "gregory", + "hebrew", + "indian", + "islamic", + "islamic-civil", + "islamic-rgsa", + "islamic-tbla", + "islamic-umalqura", + "japanese", + "persian", + "roc" +]; +let date1 = new Date(2017, 3, 12); +let date2 = new Date(); + +// serialize parts to a string by considering only the type and literal. +function serializeTypesAndLiteral(parts) { + let types = parts.map(part => { + if (part.type == "literal") { + return `${part.type}(${part.value})`; + } + return part.type; + }); + return types.join(":"); +} + +let df = new Intl.DateTimeFormat("en"); +let base = serializeTypesAndLiteral(df.formatRangeToParts(date1, date2)); + +const foundDifferentPattern = calendars.some(function(calendar) { + let cdf = new Intl.DateTimeFormat("en-u-ca-" + calendar); + return base != serializeTypesAndLiteral(cdf.formatRangeToParts(date1, date2)); +}); + +// Expect at least some calendar use different pattern. +assert.sameValue(foundDifferentPattern, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/prop-desc.js new file mode 100644 index 0000000000..c183abdc6c --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2016 Mozilla Corporation. All rights reserved. +// Copyright 2019 Igalia S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Property type and descriptor. +includes: [propertyHelper.js] +features: [Intl.DateTimeFormat-formatRange] +---*/ + +assert.sameValue( + typeof Intl.DateTimeFormat.prototype.formatRangeToParts, + 'function', + '`typeof Intl.DateTimeFormat.prototype.formatRangeToParts` is `function`' +); + +verifyProperty(Intl.DateTimeFormat.prototype, 'formatRangeToParts', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/shell.js new file mode 100644 index 0000000000..a96394ce86 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/shell.js @@ -0,0 +1,50 @@ +// GENERATED, DO NOT EDIT +// file: dateConstants.js +// Copyright (C) 2009 the Sputnik authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of date-centric values +defines: + - date_1899_end + - date_1900_start + - date_1969_end + - date_1970_start + - date_1999_end + - date_2000_start + - date_2099_end + - date_2100_start + - start_of_time + - end_of_time +---*/ + +var date_1899_end = -2208988800001; +var date_1900_start = -2208988800000; +var date_1969_end = -1; +var date_1970_start = 0; +var date_1999_end = 946684799999; +var date_2000_start = 946684800000; +var date_2099_end = 4102444799999; +var date_2100_start = 4102444800000; + +var start_of_time = -8.64e15; +var end_of_time = 8.64e15; + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/this-bad-object.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/this-bad-object.js new file mode 100644 index 0000000000..3cf6cbfb69 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/this-bad-object.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Throws a TypeError if this is not a DateTimeFormat object +features: [Intl.DateTimeFormat-formatRange] +---*/ + +const formatRangeToParts = Intl.DateTimeFormat.prototype.formatRangeToParts; + +assert.throws(TypeError, function() { + formatRangeToParts.call({}); +}, "{}"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(new Date()); +}, "new Date()"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(Intl.DateTimeFormat); +}, "Intl.DateTimeFormat"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(Intl.DateTimeFormat.prototype); +}, "Intl.DateTimeFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/this-is-not-object-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/this-is-not-object-throws.js new file mode 100644 index 0000000000..cf04cdc0af --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatRangeToParts/this-is-not-object-throws.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-formatRange is not released yet +// Copyright 2019 Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Throws a TypeError if this is not Object. +info: | + Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate , endDate ) + + 1. Let dtf be this value. + 2. If Type(dtf) is not Object, throw a TypeError exception. + +features: [Intl.DateTimeFormat-formatRange, Symbol] +---*/ + +let formatRangeToParts = Intl.DateTimeFormat.prototype.formatRangeToParts; +let d1 = new Date("1997-08-22T00:00"); +let d2 = new Date("1999-06-26T00:00"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(undefined, d1, d2); +}, "undefined"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(null, d1, d2); +}, "null"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(42, d1, d2); +}, "number"); + +assert.throws(TypeError, function() { + formatRangeToParts.call("foo", d1, d2); +}, "string"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(false, d1, d2); +}, "false"); + +assert.throws(TypeError, function() { + formatRangeToParts.call(true, d1, d2); +}, "true"); + +var s = Symbol('3'); +assert.throws(TypeError, function() { + formatRangeToParts.call(s, d1, d2); +}, "symbol"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-constructor-not-called.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-constructor-not-called.js new file mode 100644 index 0000000000..9c63ee3e52 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-constructor-not-called.js @@ -0,0 +1,38 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: | + The Date constructor is not called to convert the input value. +info: > + 12.4.4 Intl.DateTimeFormat.prototype.formatToParts ( date ) + + ... + 4. If date is undefined, then + ... + 5. Else, + a. Let x be ? ToNumber(date). + 5. Return ? FormatDateTimeToParts(dtf, x). + + 12.1.6 PartitionDateTimePattern ( dateTimeFormat, x ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. ... +---*/ + +var dtf = new Intl.DateTimeFormat(); + +var dateTimeString = "2017-11-10T14:09:00.000Z"; + +// |dateTimeString| is valid ISO-8601 style date/time string. +assert.notSameValue(new Date(dateTimeString), NaN); + +// Ensure string input values are not converted to time values by calling the +// Date constructor. +assert.throws(RangeError, function() { + dtf.formatToParts(dateTimeString); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-is-infinity-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-is-infinity-throws.js new file mode 100644 index 0000000000..071c07ed45 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-is-infinity-throws.js @@ -0,0 +1,35 @@ +// Copyright 2016 Leonardo Balter. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date arg is cast to an Infinity value +info: | + Intl.DateTimeFormat.prototype.formatToParts ([ date ]) + + 4. If _date_ is not provided or is *undefined*, then + a. Let _x_ be *%Date_now%*(). + 5. Else, + a. Let _x_ be ? ToNumber(_date_). + 6. Return ? FormatDateTimeToParts(_dtf_, _x_). + + FormatDateTimeToParts(dateTimeFormat, x) + + 1. Let _parts_ be ? PartitionDateTimePattern(_dateTimeFormat_, _x_). + + PartitionDateTimePattern (dateTimeFormat, x) + + 1. If _x_ is not a finite Number, throw a *RangeError* exception. +---*/ + +var dtf = new Intl.DateTimeFormat(["pt-BR"]); + +assert.throws(RangeError, function() { + dtf.formatToParts(Infinity); +}, "+Infinity"); + +assert.throws(RangeError, function() { + dtf.formatToParts(-Infinity); +}, "-Infinity"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-is-nan-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-is-nan-throws.js new file mode 100644 index 0000000000..ab062734e0 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/date-is-nan-throws.js @@ -0,0 +1,35 @@ +// Copyright 2016 Leonardo Balter. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Throws a RangeError if date arg is cast to NaN +info: | + Intl.DateTimeFormat.prototype.formatToParts ([ date ]) + + 4. If _date_ is not provided or is *undefined*, then + a. Let _x_ be *%Date_now%*(). + 5. Else, + a. Let _x_ be ? ToNumber(_date_). + 6. Return ? FormatDateTimeToParts(_dtf_, _x_). + + FormatDateTimeToParts(dateTimeFormat, x) + + 1. Let _parts_ be ? PartitionDateTimePattern(_dateTimeFormat_, _x_). + + PartitionDateTimePattern (dateTimeFormat, x) + + 1. If _x_ is not a finite Number, throw a *RangeError* exception. +---*/ + +var dtf = new Intl.DateTimeFormat(["pt-BR"]); + +assert.throws(RangeError, function() { + dtf.formatToParts(NaN); +}); + +assert.throws(RangeError, function() { + dtf.formatToParts("lol"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-long-en.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-long-en.js new file mode 100644 index 0000000000..c3595070d0 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-long-en.js @@ -0,0 +1,109 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of dayPeriod, long format. +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +const d0000 = new Date(2017, 11, 12, 0, 0, 0, 0); +const d0100 = new Date(2017, 11, 12, 1, 0, 0, 0); +const d0200 = new Date(2017, 11, 12, 2, 0, 0, 0); +const d0300 = new Date(2017, 11, 12, 3, 0, 0, 0); +const d0400 = new Date(2017, 11, 12, 4, 0, 0, 0); +const d0500 = new Date(2017, 11, 12, 5, 0, 0, 0); +const d0600 = new Date(2017, 11, 12, 6, 0, 0, 0); +const d0700 = new Date(2017, 11, 12, 7, 0, 0, 0); +const d0800 = new Date(2017, 11, 12, 8, 0, 0, 0); +const d0900 = new Date(2017, 11, 12, 9, 0, 0, 0); +const d1000 = new Date(2017, 11, 12, 10, 0, 0, 0); +const d1100 = new Date(2017, 11, 12, 11, 0, 0, 0); +const d1200 = new Date(2017, 11, 12, 12, 0, 0, 0); +const d1300 = new Date(2017, 11, 12, 13, 0, 0, 0); +const d1400 = new Date(2017, 11, 12, 14, 0, 0, 0); +const d1500 = new Date(2017, 11, 12, 15, 0, 0, 0); +const d1600 = new Date(2017, 11, 12, 16, 0, 0, 0); +const d1700 = new Date(2017, 11, 12, 17, 0, 0, 0); +const d1800 = new Date(2017, 11, 12, 18, 0, 0, 0); +const d1900 = new Date(2017, 11, 12, 19, 0, 0, 0); +const d2000 = new Date(2017, 11, 12, 20, 0, 0, 0); +const d2100 = new Date(2017, 11, 12, 21, 0, 0, 0); +const d2200 = new Date(2017, 11, 12, 22, 0, 0, 0); +const d2300 = new Date(2017, 11, 12, 23, 0, 0, 0); + +const long = new Intl.DateTimeFormat('en', { dayPeriod: 'long' }); + +function assertParts(parts, expected, message) { + assert.sameValue(parts.length, 1, `length should be 1, ${message}`); + assert.sameValue(parts[0].value, expected, `expected part value. ${message}`); + assert.sameValue(parts[0].type, 'dayPeriod', `part type is dayPeriod. ${message}`); +} + +assertParts(long.formatToParts(d0000), 'at night', '00:00, long format'); +assertParts(long.formatToParts(d0100), 'at night', '01:00, long format'); +assertParts(long.formatToParts(d0200), 'at night', '02:00, long format'); +assertParts(long.formatToParts(d0300), 'at night', '03:00, long format'); +assertParts(long.formatToParts(d0400), 'at night', '04:00, long format'); +assertParts(long.formatToParts(d0500), 'at night', '05:00, long format'); +assertParts(long.formatToParts(d0600), 'in the morning', '06:00, long format'); +assertParts(long.formatToParts(d0700), 'in the morning', '07:00, long format'); +assertParts(long.formatToParts(d0800), 'in the morning', '08:00, long format'); +assertParts(long.formatToParts(d0900), 'in the morning', '09:00, long format'); +assertParts(long.formatToParts(d1000), 'in the morning', '10:00, long format'); +assertParts(long.formatToParts(d1100), 'in the morning', '11:00, long format'); +assertParts(long.formatToParts(d1200), 'noon', '12:00, long format'); +assertParts(long.formatToParts(d1300), 'in the afternoon', '13:00, long format'); +assertParts(long.formatToParts(d1400), 'in the afternoon', '14:00, long format'); +assertParts(long.formatToParts(d1500), 'in the afternoon', '15:00, long format'); +assertParts(long.formatToParts(d1600), 'in the afternoon', '16:00, long format'); +assertParts(long.formatToParts(d1700), 'in the afternoon', '17:00, long format'); +assertParts(long.formatToParts(d1800), 'in the evening', '18:00, long format'); +assertParts(long.formatToParts(d1900), 'in the evening', '19:00, long format'); +assertParts(long.formatToParts(d2000), 'in the evening', '20:00, long format'); +assertParts(long.formatToParts(d2100), 'at night', '21:00, long format'); +assertParts(long.formatToParts(d2200), 'at night', '22:00, long format'); +assertParts(long.formatToParts(d2300), 'at night', '23:00, long format'); + +const longNumeric = new Intl.DateTimeFormat('en', { + dayPeriod: 'long', + hour: 'numeric' +}); + +function assertPartsNumeric(parts, hour, expected, message) { + assert.sameValue(parts.length, 3, `length should be 3, ${message}`); + assert.sameValue(parts[0].value, hour, `hour part value. ${message}`); + assert.sameValue(parts[0].type, 'hour', `hour part type. ${message}`); + assert.sameValue(parts[1].value, ' ', `literal part value. ${message}`); + assert.sameValue(parts[1].type, 'literal', `literal part type. ${message}`); + assert.sameValue(parts[2].value, expected, `expected part value. ${message}`); + assert.sameValue(parts[2].type, 'dayPeriod', `expected part type. ${message}`); +} + +assertPartsNumeric(longNumeric.formatToParts(d0000), '12', 'at night', '00:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0100), '1', 'at night', '01:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0200), '2', 'at night', '02:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0300), '3', 'at night', '03:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0400), '4', 'at night', '04:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0500), '5', 'at night', '05:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0600), '6', 'in the morning', '06:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0700), '7', 'in the morning', '07:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0800), '8', 'in the morning', '08:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d0900), '9', 'in the morning', '09:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1000), '10', 'in the morning', '10:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1100), '11', 'in the morning', '11:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1200), '12', 'noon', '12:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1300), '1', 'in the afternoon', '13:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1400), '2', 'in the afternoon', '14:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1500), '3', 'in the afternoon', '15:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1600), '4', 'in the afternoon', '16:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1700), '5', 'in the afternoon', '17:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1800), '6', 'in the evening', '18:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d1900), '7', 'in the evening', '19:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d2000), '8', 'in the evening', '20:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d2100), '9', 'at night', '21:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d2200), '10', 'at night', '22:00, long-numeric'); +assertPartsNumeric(longNumeric.formatToParts(d2300), '11', 'at night', '23:00, long-numeric'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-narrow-en.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-narrow-en.js new file mode 100644 index 0000000000..72a24eacbc --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-narrow-en.js @@ -0,0 +1,109 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of dayPeriod, narrow format. +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +const d0000 = new Date(2017, 11, 12, 0, 0, 0, 0); +const d0100 = new Date(2017, 11, 12, 1, 0, 0, 0); +const d0200 = new Date(2017, 11, 12, 2, 0, 0, 0); +const d0300 = new Date(2017, 11, 12, 3, 0, 0, 0); +const d0400 = new Date(2017, 11, 12, 4, 0, 0, 0); +const d0500 = new Date(2017, 11, 12, 5, 0, 0, 0); +const d0600 = new Date(2017, 11, 12, 6, 0, 0, 0); +const d0700 = new Date(2017, 11, 12, 7, 0, 0, 0); +const d0800 = new Date(2017, 11, 12, 8, 0, 0, 0); +const d0900 = new Date(2017, 11, 12, 9, 0, 0, 0); +const d1000 = new Date(2017, 11, 12, 10, 0, 0, 0); +const d1100 = new Date(2017, 11, 12, 11, 0, 0, 0); +const d1200 = new Date(2017, 11, 12, 12, 0, 0, 0); +const d1300 = new Date(2017, 11, 12, 13, 0, 0, 0); +const d1400 = new Date(2017, 11, 12, 14, 0, 0, 0); +const d1500 = new Date(2017, 11, 12, 15, 0, 0, 0); +const d1600 = new Date(2017, 11, 12, 16, 0, 0, 0); +const d1700 = new Date(2017, 11, 12, 17, 0, 0, 0); +const d1800 = new Date(2017, 11, 12, 18, 0, 0, 0); +const d1900 = new Date(2017, 11, 12, 19, 0, 0, 0); +const d2000 = new Date(2017, 11, 12, 20, 0, 0, 0); +const d2100 = new Date(2017, 11, 12, 21, 0, 0, 0); +const d2200 = new Date(2017, 11, 12, 22, 0, 0, 0); +const d2300 = new Date(2017, 11, 12, 23, 0, 0, 0); + +const narrow = new Intl.DateTimeFormat('en', { dayPeriod: 'narrow' }); + +function assertParts(parts, expected, message) { + assert.sameValue(parts.length, 1, `length should be 1, ${message}`); + assert.sameValue(parts[0].value, expected, `expected part value. ${message}`); + assert.sameValue(parts[0].type, 'dayPeriod', `part type is dayPeriod. ${message}`); +} + +assertParts(narrow.formatToParts(d0000), 'at night', '00:00, narrow format'); +assertParts(narrow.formatToParts(d0100), 'at night', '01:00, narrow format'); +assertParts(narrow.formatToParts(d0200), 'at night', '02:00, narrow format'); +assertParts(narrow.formatToParts(d0300), 'at night', '03:00, narrow format'); +assertParts(narrow.formatToParts(d0400), 'at night', '04:00, narrow format'); +assertParts(narrow.formatToParts(d0500), 'at night', '05:00, narrow format'); +assertParts(narrow.formatToParts(d0600), 'in the morning', '06:00, narrow format'); +assertParts(narrow.formatToParts(d0700), 'in the morning', '07:00, narrow format'); +assertParts(narrow.formatToParts(d0800), 'in the morning', '08:00, narrow format'); +assertParts(narrow.formatToParts(d0900), 'in the morning', '09:00, narrow format'); +assertParts(narrow.formatToParts(d1000), 'in the morning', '10:00, narrow format'); +assertParts(narrow.formatToParts(d1100), 'in the morning', '11:00, narrow format'); +assertParts(narrow.formatToParts(d1200), 'n', '12:00, narrow format'); +assertParts(narrow.formatToParts(d1300), 'in the afternoon', '13:00, narrow format'); +assertParts(narrow.formatToParts(d1400), 'in the afternoon', '14:00, narrow format'); +assertParts(narrow.formatToParts(d1500), 'in the afternoon', '15:00, narrow format'); +assertParts(narrow.formatToParts(d1600), 'in the afternoon', '16:00, narrow format'); +assertParts(narrow.formatToParts(d1700), 'in the afternoon', '17:00, narrow format'); +assertParts(narrow.formatToParts(d1800), 'in the evening', '18:00, narrow format'); +assertParts(narrow.formatToParts(d1900), 'in the evening', '19:00, narrow format'); +assertParts(narrow.formatToParts(d2000), 'in the evening', '20:00, narrow format'); +assertParts(narrow.formatToParts(d2100), 'at night', '21:00, narrow format'); +assertParts(narrow.formatToParts(d2200), 'at night', '22:00, narrow format'); +assertParts(narrow.formatToParts(d2300), 'at night', '23:00, narrow format'); + +const narrowNumeric = new Intl.DateTimeFormat('en', { + dayPeriod: 'narrow', + hour: 'numeric' +}); + +function assertPartsNumeric(parts, hour, expected, message) { + assert.sameValue(parts.length, 3, `length should be 3, ${message}`); + assert.sameValue(parts[0].value, hour, `hour part value. ${message}`); + assert.sameValue(parts[0].type, 'hour', `hour part type. ${message}`); + assert.sameValue(parts[1].value, ' ', `literal part value. ${message}`); + assert.sameValue(parts[1].type, 'literal', `literal part type. ${message}`); + assert.sameValue(parts[2].value, expected, `expected part value. ${message}`); + assert.sameValue(parts[2].type, 'dayPeriod', `expected part type. ${message}`); +} + +assertPartsNumeric(narrowNumeric.formatToParts(d0000), '12', 'at night', '00:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0100), '1', 'at night', '01:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0200), '2', 'at night', '02:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0300), '3', 'at night', '03:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0400), '4', 'at night', '04:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0500), '5', 'at night', '05:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0600), '6', 'in the morning', '06:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0700), '7', 'in the morning', '07:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0800), '8', 'in the morning', '08:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d0900), '9', 'in the morning', '09:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1000), '10', 'in the morning', '10:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1100), '11', 'in the morning', '11:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1200), '12', 'n', '12:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1300), '1', 'in the afternoon', '13:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1400), '2', 'in the afternoon', '14:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1500), '3', 'in the afternoon', '15:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1600), '4', 'in the afternoon', '16:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1700), '5', 'in the afternoon', '17:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1800), '6', 'in the evening', '18:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d1900), '7', 'in the evening', '19:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d2000), '8', 'in the evening', '20:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d2100), '9', 'at night', '21:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d2200), '10', 'at night', '22:00, narrow-numeric'); +assertPartsNumeric(narrowNumeric.formatToParts(d2300), '11', 'at night', '23:00, narrow-numeric'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-short-en.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-short-en.js new file mode 100644 index 0000000000..8301bfca84 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/dayPeriod-short-en.js @@ -0,0 +1,109 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of dayPeriod, short format. +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +const d0000 = new Date(2017, 11, 12, 0, 0, 0, 0); +const d0100 = new Date(2017, 11, 12, 1, 0, 0, 0); +const d0200 = new Date(2017, 11, 12, 2, 0, 0, 0); +const d0300 = new Date(2017, 11, 12, 3, 0, 0, 0); +const d0400 = new Date(2017, 11, 12, 4, 0, 0, 0); +const d0500 = new Date(2017, 11, 12, 5, 0, 0, 0); +const d0600 = new Date(2017, 11, 12, 6, 0, 0, 0); +const d0700 = new Date(2017, 11, 12, 7, 0, 0, 0); +const d0800 = new Date(2017, 11, 12, 8, 0, 0, 0); +const d0900 = new Date(2017, 11, 12, 9, 0, 0, 0); +const d1000 = new Date(2017, 11, 12, 10, 0, 0, 0); +const d1100 = new Date(2017, 11, 12, 11, 0, 0, 0); +const d1200 = new Date(2017, 11, 12, 12, 0, 0, 0); +const d1300 = new Date(2017, 11, 12, 13, 0, 0, 0); +const d1400 = new Date(2017, 11, 12, 14, 0, 0, 0); +const d1500 = new Date(2017, 11, 12, 15, 0, 0, 0); +const d1600 = new Date(2017, 11, 12, 16, 0, 0, 0); +const d1700 = new Date(2017, 11, 12, 17, 0, 0, 0); +const d1800 = new Date(2017, 11, 12, 18, 0, 0, 0); +const d1900 = new Date(2017, 11, 12, 19, 0, 0, 0); +const d2000 = new Date(2017, 11, 12, 20, 0, 0, 0); +const d2100 = new Date(2017, 11, 12, 21, 0, 0, 0); +const d2200 = new Date(2017, 11, 12, 22, 0, 0, 0); +const d2300 = new Date(2017, 11, 12, 23, 0, 0, 0); + +const short = new Intl.DateTimeFormat('en', { dayPeriod: 'short' }); + +function assertParts(parts, expected, message) { + assert.sameValue(parts.length, 1, `length should be 1, ${message}`); + assert.sameValue(parts[0].value, expected, `expected part value. ${message}`); + assert.sameValue(parts[0].type, 'dayPeriod', `part type is dayPeriod. ${message}`); +} + +assertParts(short.formatToParts(d0000), 'at night', '00:00, short format'); +assertParts(short.formatToParts(d0100), 'at night', '01:00, short format'); +assertParts(short.formatToParts(d0200), 'at night', '02:00, short format'); +assertParts(short.formatToParts(d0300), 'at night', '03:00, short format'); +assertParts(short.formatToParts(d0400), 'at night', '04:00, short format'); +assertParts(short.formatToParts(d0500), 'at night', '05:00, short format'); +assertParts(short.formatToParts(d0600), 'in the morning', '06:00, short format'); +assertParts(short.formatToParts(d0700), 'in the morning', '07:00, short format'); +assertParts(short.formatToParts(d0800), 'in the morning', '08:00, short format'); +assertParts(short.formatToParts(d0900), 'in the morning', '09:00, short format'); +assertParts(short.formatToParts(d1000), 'in the morning', '10:00, short format'); +assertParts(short.formatToParts(d1100), 'in the morning', '11:00, short format'); +assertParts(short.formatToParts(d1200), 'noon', '12:00, short format'); +assertParts(short.formatToParts(d1300), 'in the afternoon', '13:00, short format'); +assertParts(short.formatToParts(d1400), 'in the afternoon', '14:00, short format'); +assertParts(short.formatToParts(d1500), 'in the afternoon', '15:00, short format'); +assertParts(short.formatToParts(d1600), 'in the afternoon', '16:00, short format'); +assertParts(short.formatToParts(d1700), 'in the afternoon', '17:00, short format'); +assertParts(short.formatToParts(d1800), 'in the evening', '18:00, short format'); +assertParts(short.formatToParts(d1900), 'in the evening', '19:00, short format'); +assertParts(short.formatToParts(d2000), 'in the evening', '20:00, short format'); +assertParts(short.formatToParts(d2100), 'at night', '21:00, short format'); +assertParts(short.formatToParts(d2200), 'at night', '22:00, short format'); +assertParts(short.formatToParts(d2300), 'at night', '23:00, short format'); + +const shortNumeric = new Intl.DateTimeFormat('en', { + dayPeriod: 'short', + hour: 'numeric' +}); + +function assertPartsNumeric(parts, hour, expected, message) { + assert.sameValue(parts.length, 3, `length should be 3, ${message}`); + assert.sameValue(parts[0].value, hour, `hour part value. ${message}`); + assert.sameValue(parts[0].type, 'hour', `hour part type. ${message}`); + assert.sameValue(parts[1].value, ' ', `literal part value. ${message}`); + assert.sameValue(parts[1].type, 'literal', `literal part type. ${message}`); + assert.sameValue(parts[2].value, expected, `expected part value. ${message}`); + assert.sameValue(parts[2].type, 'dayPeriod', `expected part type. ${message}`); +} + +assertPartsNumeric(shortNumeric.formatToParts(d0000), '12', 'at night', '00:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0100), '1', 'at night', '01:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0200), '2', 'at night', '02:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0300), '3', 'at night', '03:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0400), '4', 'at night', '04:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0500), '5', 'at night', '05:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0600), '6', 'in the morning', '06:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0700), '7', 'in the morning', '07:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0800), '8', 'in the morning', '08:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d0900), '9', 'in the morning', '09:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1000), '10', 'in the morning', '10:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1100), '11', 'in the morning', '11:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1200), '12', 'noon', '12:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1300), '1', 'in the afternoon', '13:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1400), '2', 'in the afternoon', '14:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1500), '3', 'in the afternoon', '15:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1600), '4', 'in the afternoon', '16:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1700), '5', 'in the afternoon', '17:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1800), '6', 'in the evening', '18:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d1900), '7', 'in the evening', '19:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d2000), '8', 'in the evening', '20:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d2100), '9', 'at night', '21:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d2200), '10', 'at night', '22:00, short-numeric'); +assertPartsNumeric(shortNumeric.formatToParts(d2300), '11', 'at night', '23:00, short-numeric'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/formatToParts.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/formatToParts.js new file mode 100644 index 0000000000..d1898c5c1d --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/formatToParts.js @@ -0,0 +1,19 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Property type and descriptor. +includes: [propertyHelper.js] +---*/ + +assert.sameValue( + typeof Intl.DateTimeFormat.prototype.formatToParts, + 'function', + '`typeof Intl.DateTimeFormat.prototype.formatToParts` is `function`' +); + +verifyNotEnumerable(Intl.DateTimeFormat.prototype, 'formatToParts'); +verifyWritable(Intl.DateTimeFormat.prototype, 'formatToParts'); +verifyConfigurable(Intl.DateTimeFormat.prototype, 'formatToParts'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/fractionalSecondDigits.js new file mode 100644 index 0000000000..30d96b4d31 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/fractionalSecondDigits.js @@ -0,0 +1,69 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: Checks basic handling of fractionalSecondDigits. +features: [Intl.DateTimeFormat-fractionalSecondDigits] +locale: [en-US] +---*/ + +const d1 = new Date(2019, 7, 10, 1, 2, 3, 234); +const d2 = new Date(2019, 7, 10, 1, 2, 3, 567); + +function assertParts(parts, minute, second, fractionalSecond, message) { + if (fractionalSecond === null) { + assert.sameValue(parts.length, 3, `length should be 3, ${message}`); + } else { + assert.sameValue(parts.length, 5, `length should be 5, ${message}`); + } + assert.sameValue(parts[0].value, minute, `minute part value. ${message}`); + assert.sameValue(parts[0].type, 'minute', `minute part type. ${message}`); + assert.sameValue(parts[1].value, ':', `literal part value. ${message}`); + assert.sameValue(parts[1].type, 'literal', `literal part type. ${message}`); + assert.sameValue(parts[2].value, second, `second part value. ${message}`); + assert.sameValue(parts[2].type, 'second', `second part type. ${message}`); + if (fractionalSecond !== null) { + assert.sameValue(parts[3].value, '.', `literal part value. ${message}`); + assert.sameValue(parts[3].type, 'literal', `literal part type. ${message}`); + assert.sameValue(parts[4].value, fractionalSecond, `fractionalSecond part value. ${message}`); + assert.sameValue(parts[4].type, 'fractionalSecond', `fractionalSecond part type. ${message}`); + } +} + +assert.throws(RangeError, () => { + new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 0}); +}, "fractionalSecondDigits 0 should throw RangeError for out of range"); + +assert.throws(RangeError, () => { + new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 4}); +}, "fractionalSecondDigits 4 should throw RangeError for out of range"); + +let dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric"}); +assertParts(dtf.formatToParts(d1), "02", "03", null, "no fractionalSecondDigits round down"); +assertParts(dtf.formatToParts(d2), "02", "03", null, "no fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: undefined}); +assertParts(dtf.formatToParts(d1), "02", "03", null, "no fractionalSecondDigits round down"); +assertParts(dtf.formatToParts(d2), "02", "03", null, "no fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 1}); +assertParts(dtf.formatToParts(d1), "02", "03", "2", "1 fractionalSecondDigits round down"); +assertParts(dtf.formatToParts(d2), "02", "03", "5", "1 fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 2}); +assertParts(dtf.formatToParts(d1), "02", "03", "23", "2 fractionalSecondDigits round down"); +assertParts(dtf.formatToParts(d2), "02", "03", "56", "2 fractionalSecondDigits round down"); + +dtf = new Intl.DateTimeFormat( + 'en', { minute: "numeric", second: "numeric", fractionalSecondDigits: 3}); +assertParts(dtf.formatToParts(d1), "02", "03", "234", "3 fractionalSecondDigits round down"); +assertParts(dtf.formatToParts(d2), "02", "03", "567", "3 fractionalSecondDigits round down"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/length.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/length.js new file mode 100644 index 0000000000..cc596ada97 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/length.js @@ -0,0 +1,15 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Intl.DateTimeFormat.prototype.formatToParts.length. +includes: [propertyHelper.js] +---*/ +verifyProperty(Intl.DateTimeFormat.prototype.formatToParts, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/main.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/main.js new file mode 100644 index 0000000000..79ad4f324e --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/main.js @@ -0,0 +1,75 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Tests for existance and behavior of Intl.DateTimeFormat.prototype.formatToParts +---*/ + +function reduce(parts) { + return parts.map(part => part.value).join(''); +} + +function compareFTPtoFormat(locales, options, value) { + const dtf = new Intl.DateTimeFormat(locales, options); + assert.sameValue( + dtf.format(value), + reduce(dtf.formatToParts(value)), + `Expected the same value for value ${value}, + locales: ${locales} and options: ${options}` + ); +} + +compareFTPtoFormat(); +compareFTPtoFormat('pl'); +compareFTPtoFormat(['pl']); +compareFTPtoFormat([]); +compareFTPtoFormat(['de'], undefined, 0); +compareFTPtoFormat(['de'], undefined, -10); +compareFTPtoFormat(['de'], undefined, 25324234235); +compareFTPtoFormat(['de'], { + day: '2-digit' +}, Date.now()); +compareFTPtoFormat(['de'], { + day: 'numeric', + year: '2-digit' +}, Date.now()); +compareFTPtoFormat(['ar'], { + month: 'numeric', + day: 'numeric', + year: '2-digit' +}, Date.now()); + +const actualPartTypes = new Intl.DateTimeFormat('en-us', { + weekday: 'long', + era: 'long', + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + hour12: true, + timeZone: 'UTC', + timeZoneName: 'long' +}).formatToParts(Date.UTC(2012, 11, 17, 3, 0, 42)) + .map(part => part.type); + +const legalPartTypes = [ + 'weekday', + 'era', + 'year', + 'month', + 'day', + 'hour', + 'minute', + 'second', + 'literal', + 'dayPeriod', + 'timeZoneName', +]; + +actualPartTypes.forEach(function(type) { + assert(legalPartTypes.includes(type), `${type} is not a legal type`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/name.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/name.js new file mode 100644 index 0000000000..92b4805ee9 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/name.js @@ -0,0 +1,15 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Intl.DateTimeFormat.prototype.formatToParts.name value and descriptor. +includes: [propertyHelper.js] +---*/ +verifyProperty(Intl.DateTimeFormat.prototype.formatToParts, 'name', { + value: 'formatToParts', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js new file mode 100644 index 0000000000..9a87da8dbc --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js @@ -0,0 +1,55 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Checks the DateTimeFormat choose different patterns based + on calendar. +locale: [en] +---*/ + +let calendars = [ + "buddhist", + "chinese", + "coptic", + "dangi", + "ethiopic", + "ethioaa", + "gregory", + "hebrew", + "indian", + "islamic", + "islamic-civil", + "islamic-rgsa", + "islamic-tbla", + "islamic-umalqura", + "japanese", + "persian", + "roc" +]; +let date = new Date(); + +// serialize parts to a string by considering only the type and literal. +function serializeTypesAndLiteral(parts) { + let types = parts.map(part => { + if (part.type == "literal") { + return `${part.type}(${part.value})`; + } + return part.type; + }); + return types.join(":"); +} + +let df = new Intl.DateTimeFormat("en"); +let base = serializeTypesAndLiteral(df.formatToParts(date)); + +const foundDifferentPattern = calendars.some(function(calendar) { + let cdf = new Intl.DateTimeFormat("en-u-ca-" + calendar); + return base != serializeTypesAndLiteral(cdf.formatToParts(date)); +}); + +// Expect at least some calendar use different pattern. +assert.sameValue(foundDifferentPattern, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/related-year-zh.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/related-year-zh.js new file mode 100644 index 0000000000..1033404e00 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/related-year-zh.js @@ -0,0 +1,35 @@ +// Copyright 2019 Google Inc, Igalia S.L. All rights reserved. +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: > + Checks the output of 'relatedYear' and 'yearName' type, and + the choice of pattern based on calendar. +locale: [zh-u-ca-chinese] +---*/ + +const df = new Intl.DateTimeFormat("zh-u-ca-chinese", {year: "numeric"}); +const date = new Date(2019, 5, 1); +const actual = df.formatToParts(date); + +const expected = [ + {type: "relatedYear", value: "2019"}, + {type: "yearName", value: "己亥"}, + {type: "literal", value: "年"}, +]; + +assert.sameValue(Array.isArray(actual), true, 'actual is Array'); + +if (actual.length <= 2) { + expected.shift(); // removes the relatedYear +} + +actual.forEach(({ type, value }, i) => { + const { type: eType, value: eValue } = expected[i]; + assert.sameValue(type, eType, `actual[${i}].type should be ${eType}`); + assert.sameValue(value, eValue, `actual[${i}].value should be ${eValue}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/related-year.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/related-year.js new file mode 100644 index 0000000000..92aae9e730 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/related-year.js @@ -0,0 +1,23 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: > + Checks the output of 'relatedYear' and 'yearName' type, and + the choose of pattern base on calendar. +locale: [en-u-ca-chinese] +---*/ + +let df = new Intl.DateTimeFormat("en-u-ca-chinese", {year: "numeric"}); +let parts = df.formatToParts(new Date()); +var relatedYearCount = 0; +var yearNameCount = 0; +parts.forEach(function(part) { + relatedYearCount += (part.type == "relatedYear") ? 1 : 0; + yearNameCount += (part.type == "yearName") ? 1 : 0; +}); +assert.sameValue(relatedYearCount > 0, true); +assert.sameValue(yearNameCount > 0, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/return-abrupt-tonumber-date.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/return-abrupt-tonumber-date.js new file mode 100644 index 0000000000..b8141a3776 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/return-abrupt-tonumber-date.js @@ -0,0 +1,44 @@ +// Copyright 2016 Leonardo Balter. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Return abrupt completions from ToNumber(date) +info: | + Intl.DateTimeFormat.prototype.formatToParts ([ date ]) + + 4. If _date_ is not provided or is *undefined*, then + a. Let _x_ be *%Date_now%*(). + 5. Else, + a. Let _x_ be ? ToNumber(_date_). +features: [Symbol] +---*/ + +var obj1 = { + valueOf: function() { + throw new Test262Error(); + } +}; + +var obj2 = { + toString: function() { + throw new Test262Error(); + } +}; + +var dtf = new Intl.DateTimeFormat(["pt-BR"]); + +assert.throws(Test262Error, function() { + dtf.formatToParts(obj1); +}, "valueOf"); + +assert.throws(Test262Error, function() { + dtf.formatToParts(obj2); +}, "toString"); + +var s = Symbol('1'); +assert.throws(TypeError, function() { + dtf.formatToParts(s); +}, "symbol"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/shell.js new file mode 100644 index 0000000000..62c6315a70 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/shell.js @@ -0,0 +1,31 @@ +// GENERATED, DO NOT EDIT +// file: dateConstants.js +// Copyright (C) 2009 the Sputnik authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of date-centric values +defines: + - date_1899_end + - date_1900_start + - date_1969_end + - date_1970_start + - date_1999_end + - date_2000_start + - date_2099_end + - date_2100_start + - start_of_time + - end_of_time +---*/ + +var date_1899_end = -2208988800001; +var date_1900_start = -2208988800000; +var date_1969_end = -1; +var date_1970_start = 0; +var date_1999_end = 946684799999; +var date_2000_start = 946684800000; +var date_2099_end = 4102444799999; +var date_2100_start = 4102444800000; + +var start_of_time = -8.64e15; +var end_of_time = 8.64e15; diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/this-has-not-internal-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/this-has-not-internal-throws.js new file mode 100644 index 0000000000..18dae83a16 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/this-has-not-internal-throws.js @@ -0,0 +1,19 @@ +// Copyright 2016 Leonardo Balter. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: > + Throws a TypeError if this is not a DateTimeFormat object +---*/ + +var formatToParts = Intl.DateTimeFormat.prototype.formatToParts; + +assert.throws(TypeError, function() { + formatToParts.call({}); +}, "{}"); + +assert.throws(TypeError, function() { + formatToParts.call(new Date()); +}, "new Date()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/this-is-not-object-throws.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/this-is-not-object-throws.js new file mode 100644 index 0000000000..0837bfb1ca --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/this-is-not-object-throws.js @@ -0,0 +1,40 @@ +// Copyright 2016 Leonardo Balter. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Throws a TypeError if this is not Object +features: [Symbol] +---*/ + +var formatToParts = Intl.DateTimeFormat.prototype.formatToParts; + +assert.throws(TypeError, function() { + formatToParts.call(undefined); +}, "undefined"); + +assert.throws(TypeError, function() { + formatToParts.call(null); +}, "null"); + +assert.throws(TypeError, function() { + formatToParts.call(42); +}, "number"); + +assert.throws(TypeError, function() { + formatToParts.call("foo"); +}, "string"); + +assert.throws(TypeError, function() { + formatToParts.call(false); +}, "false"); + +assert.throws(TypeError, function() { + formatToParts.call(true); +}, "true"); + +var s = Symbol('1'); +assert.throws(TypeError, function() { + formatToParts.call(s); +}, "symbol"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/time-clip-near-time-boundaries.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/time-clip-near-time-boundaries.js new file mode 100644 index 0000000000..61599ebbc1 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/time-clip-near-time-boundaries.js @@ -0,0 +1,39 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: | + TimeClip is applied when calling Intl.DateTimeFormat.prototype.formatToParts. +info: > + 12.1.6 PartitionDateTimePattern ( dateTimeFormat, x ) + + 1. Let x be TimeClip(x). + 2. If x is NaN, throw a RangeError exception. + 3. ... + + 20.3.1.15 TimeClip ( time ) + ... + 2. If abs(time) > 8.64 × 10^15, return NaN. + ... + +includes: [dateConstants.js] +---*/ + +var dtf = new Intl.DateTimeFormat(); + +// Test values near the start of the ECMAScript time range. +assert.throws(RangeError, function() { + dtf.formatToParts(start_of_time - 1); +}); +assert.sameValue(typeof dtf.formatToParts(start_of_time), "object"); +assert.sameValue(typeof dtf.formatToParts(start_of_time + 1), "object"); + +// Test values near the end of the ECMAScript time range. +assert.sameValue(typeof dtf.formatToParts(end_of_time - 1), "object"); +assert.sameValue(typeof dtf.formatToParts(end_of_time), "object"); +assert.throws(RangeError, function() { + dtf.formatToParts(end_of_time + 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/time-clip-to-integer.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/time-clip-to-integer.js new file mode 100644 index 0000000000..576b08ca92 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/formatToParts/time-clip-to-integer.js @@ -0,0 +1,43 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-partitiondatetimepattern +description: | + TimeClip applies ToInteger on its input value. +info: > + 12.1.6 PartitionDateTimePattern ( dateTimeFormat, x ) + + 1. Let x be TimeClip(x). + 2. ... + + 20.3.1.15 TimeClip ( time ) + ... + 3. Let clippedTime be ! ToInteger(time). + 4. If clippedTime is -0, set clippedTime to +0. + 5. Return clippedTime. +---*/ + +// Switch to a time format instead of using DateTimeFormat's default date-only format. +var dtf = new Intl.DateTimeFormat(undefined, { + hour: "numeric", minute: "numeric", second: "numeric" +}); + +function formatAsString(dtf, time) { + return dtf.formatToParts(time).map(part => part.value).join(""); +} + +var expected = formatAsString(dtf, 0); + +assert.sameValue(formatAsString(dtf, -0.9), expected, "formatToParts(-0.9)"); +assert.sameValue(formatAsString(dtf, -0.5), expected, "formatToParts(-0.5)"); +assert.sameValue(formatAsString(dtf, -0.1), expected, "formatToParts(-0.1)"); +assert.sameValue(formatAsString(dtf, -Number.MIN_VALUE), expected, "formatToParts(-Number.MIN_VALUE)"); +assert.sameValue(formatAsString(dtf, -0), expected, "formatToParts(-0)"); +assert.sameValue(formatAsString(dtf, +0), expected, "formatToParts(+0)"); +assert.sameValue(formatAsString(dtf, Number.MIN_VALUE), expected, "formatToParts(Number.MIN_VALUE)"); +assert.sameValue(formatAsString(dtf, 0.1), expected, "formatToParts(0.1)"); +assert.sameValue(formatAsString(dtf, 0.5), expected, "formatToParts(0.5)"); +assert.sameValue(formatAsString(dtf, 0.9), expected, "formatToParts(0.9)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/prop-desc.js new file mode 100644 index 0000000000..711e47059a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/prop-desc.js @@ -0,0 +1,19 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.2.1 +description: > + Tests that Intl.DateTimeFormat.prototype has the required + attributes. +author: Norbert Lindenberg +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.DateTimeFormat, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js new file mode 100644 index 0000000000..294b8f4d80 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/basic.js @@ -0,0 +1,75 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.3.3 +description: > + Tests that the object returned by + Intl.DateTimeFormat.prototype.resolvedOptions has the right + properties. +author: Norbert Lindenberg +includes: [testIntl.js, propertyHelper.js] +---*/ + +var actual = new Intl.DateTimeFormat().resolvedOptions(); + +var actual2 = new Intl.DateTimeFormat().resolvedOptions(); +assert.notSameValue(actual2, actual, "resolvedOptions returned the same object twice."); + +// source: CLDR file common/bcp47/calendar.xml; version CLDR 32. +var calendars = [ + "buddhist", + "chinese", + "coptic", + "dangi", + "ethioaa", + "ethiopic-amete-alem", + "ethiopic", + "gregory", + "hebrew", + "indian", + "islamic", + "islamic-umalqura", + "islamic-tbla", + "islamic-civil", + "islamic-rgsa", + "iso8601", + "japanese", + "persian", + "roc", + "islamicc", +]; + +// this assumes the default values where the specification provides them +assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale), + "Invalid locale: " + actual.locale); +assert.notSameValue(calendars.indexOf(actual.calendar), -1, + "Invalid calendar: " + actual.calendar); +assert(isValidNumberingSystem(actual.numberingSystem), + "Invalid numbering system: " + actual.numberingSystem); +assert(isCanonicalizedStructurallyValidTimeZoneName(actual.timeZone), + "Invalid time zone: " + actual.timeZone); +assert.notSameValue(["2-digit", "numeric"].indexOf(actual.year), -1, + "Invalid year: " + actual.year); +assert.notSameValue(["2-digit", "numeric", "narrow", "short", "long"].indexOf(actual.month), -1, + "Invalid month: " + actual.month); +assert.notSameValue(["2-digit", "numeric"].indexOf(actual.day), -1, + "Invalid day: " + actual.day); + +var dataPropertyDesc = { writable: true, enumerable: true, configurable: true }; +verifyProperty(actual, "locale", dataPropertyDesc); +verifyProperty(actual, "calendar", dataPropertyDesc); +verifyProperty(actual, "numberingSystem", dataPropertyDesc); +verifyProperty(actual, "timeZone", dataPropertyDesc); +verifyProperty(actual, "weekday", undefined); +verifyProperty(actual, "era", undefined); +verifyProperty(actual, "year", dataPropertyDesc); +verifyProperty(actual, "month", dataPropertyDesc); +verifyProperty(actual, "day", dataPropertyDesc); +verifyProperty(actual, "hour", undefined); +verifyProperty(actual, "minute", undefined); +verifyProperty(actual, "second", undefined); +verifyProperty(actual, "timeZoneName", undefined); +verifyProperty(actual, "hour12", undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/builtin.js new file mode 100644 index 0000000000..643376e7e2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.3.3_L15 +description: > + Tests that Intl.DateTimeFormat.prototype.resolvedOptions meets + the requirements for built-in objects defined by the introduction + of chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.DateTimeFormat.prototype.resolvedOptions), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.DateTimeFormat.prototype.resolvedOptions), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.DateTimeFormat.prototype.resolvedOptions), Function.prototype); + +assert.sameValue(Intl.DateTimeFormat.prototype.resolvedOptions.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.DateTimeFormat.prototype.resolvedOptions), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-dateStyle.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-dateStyle.js new file mode 100644 index 0000000000..e6e06a1ad0 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-dateStyle.js @@ -0,0 +1,69 @@ +// Copyright 2019 Mozilla Corporation, Igalia S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.resolvedOptions +description: > + Intl.DateTimeFormat.prototype.resolvedOptions properly + reflect hourCycle settings when using dateStyle. +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + +const hcValues = ["h11", "h12", "h23", "h24"]; +const hour12Values = ["h11", "h12"]; + +for (const dateStyle of ["full", "long", "medium", "short"]) { + assert.sameValue(new Intl.DateTimeFormat([], { dateStyle }).resolvedOptions().dateStyle, + dateStyle, + `Should support dateStyle=${dateStyle}`); + + /* Values passed via unicode extension key work */ + + for (const hcValue of hcValues) { + const resolvedOptions = new Intl.DateTimeFormat(`de-u-hc-${hcValue}`, { + dateStyle, + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, undefined); + assert.sameValue(resolvedOptions.hour12, undefined); + } + + /* Values passed via options work */ + + for (const hcValue of hcValues) { + const resolvedOptions = new Intl.DateTimeFormat("en-US", { + dateStyle, + hourCycle: hcValue + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, undefined); + assert.sameValue(resolvedOptions.hour12, undefined); + } + + let resolvedOptions = new Intl.DateTimeFormat("en-US-u-hc-h12", { + dateStyle, + hourCycle: "h23" + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, undefined); + assert.sameValue(resolvedOptions.hour12, undefined); + + resolvedOptions = new Intl.DateTimeFormat("fr", { + dateStyle, + hour12: true, + hourCycle: "h23" + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, undefined); + assert.sameValue(resolvedOptions.hour12, undefined); + + resolvedOptions = new Intl.DateTimeFormat("fr-u-hc-h24", { + dateStyle, + hour12: true, + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, undefined); + assert.sameValue(resolvedOptions.hour12, undefined); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-default.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-default.js new file mode 100644 index 0000000000..906518c44b --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-default.js @@ -0,0 +1,58 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.resolvedOptions +description: > + Intl.DateTimeFormat.prototype.resolvedOptions properly + reflect hourCycle settings. +info: | + 12.4.5 Intl.DateTimeFormat.prototype.resolvedOptions() + + 12.1.1 InitializeDateTimeFormat ( dateTimeFormat, locales, options ) + 29. If dateTimeFormat.[[Hour]] is not undefined, then + a. Let hcDefault be dataLocaleData.[[hourCycle]]. + b. Let hc be dateTimeFormat.[[HourCycle]]. + c. If hc is null, then + i. Set hc to hcDefault. + d. If hour12 is not undefined, then + i. If hour12 is true, then + 1. If hcDefault is "h11" or "h23", then + a. Set hc to "h11". + 2. Else, + a. Set hc to "h12". + ii. Else, + 1. Assert: hour12 is false. + 2. If hcDefault is "h11" or "h23", then + a. Set hc to "h23". + 3. Else, + a. Set hc to "h24". + e. Set dateTimeFormat.[[HourCycle]] to hc. + +locale: [en, fr, it, ja, zh, ko, ar, hi] +---*/ + +let locales = ["en", "fr", "it", "ja", "zh", "ko", "ar", "hi"]; + +locales.forEach(function(locale) { + let hcDefault = (new Intl.DateTimeFormat(locale, {hour: "numeric"})) + .resolvedOptions().hourCycle; + if (hcDefault == "h11" || hcDefault == "h23") { + assert.sameValue("h11", + (new Intl.DateTimeFormat(locale, {hour: "numeric", hour12: true})) + .resolvedOptions().hourCycle); + assert.sameValue("h23", + (new Intl.DateTimeFormat(locale, {hour: "numeric", hour12: false})) + .resolvedOptions().hourCycle); + } else { + assert.sameValue(true, hcDefault == "h12" || hcDefault == "h24") + assert.sameValue("h12", + (new Intl.DateTimeFormat(locale, {hour: "numeric", hour12: true})) + .resolvedOptions().hourCycle); + assert.sameValue("h24", + (new Intl.DateTimeFormat(locale, {hour: "numeric", hour12: false})) + .resolvedOptions().hourCycle); + } +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-timeStyle.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-timeStyle.js new file mode 100644 index 0000000000..7fc96e2adb --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-timeStyle.js @@ -0,0 +1,89 @@ +// Copyright 2019 Mozilla Corporation, Igalia S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.resolvedOptions +description: > + Intl.DateTimeFormat.prototype.resolvedOptions properly + reflect hourCycle settings when using timeStyle. +includes: [propertyHelper.js] +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + +const hcValues = ["h11", "h12", "h23", "h24"]; +const hour12Values = ["h11", "h12"]; +const dataPropertyDesc = { writable: true, enumerable: true, configurable: true }; + +for (const timeStyle of ["full", "long", "medium", "short"]) { + assert.sameValue(new Intl.DateTimeFormat([], { timeStyle }).resolvedOptions().timeStyle, + timeStyle, + `Should support timeStyle=${timeStyle}`); + + /* Values passed via unicode extension key work */ + + for (const hcValue of hcValues) { + const resolvedOptions = new Intl.DateTimeFormat(`de-u-hc-${hcValue}`, { + timeStyle, + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, hcValue); + assert.sameValue(resolvedOptions.hour12, hour12Values.includes(hcValue)); + } + + /* Values passed via options work */ + + for (const hcValue of hcValues) { + const resolvedOptions = new Intl.DateTimeFormat("en-US", { + timeStyle, + hourCycle: hcValue + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, hcValue); + assert.sameValue(resolvedOptions.hour12, hour12Values.includes(hcValue)); + + verifyProperty(resolvedOptions, "hourCycle", dataPropertyDesc); + verifyProperty(resolvedOptions, "hour12", dataPropertyDesc); + } + + /* When both extension key and option is passed, option takes precedence */ + + let resolvedOptions = new Intl.DateTimeFormat("en-US-u-hc-h12", { + timeStyle, + hourCycle: "h23" + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, "h23"); + assert.sameValue(resolvedOptions.hour12, false); + + verifyProperty(resolvedOptions, "hourCycle", dataPropertyDesc); + verifyProperty(resolvedOptions, "hour12", dataPropertyDesc); + + /* When hour12 and hourCycle are set, hour12 takes precedence */ + + resolvedOptions = new Intl.DateTimeFormat("fr", { + timeStyle, + hour12: true, + hourCycle: "h23" + }).resolvedOptions(); + + assert(hour12Values.includes(resolvedOptions.hourCycle)); + assert.sameValue(resolvedOptions.hour12, true); + + verifyProperty(resolvedOptions, "hourCycle", dataPropertyDesc); + verifyProperty(resolvedOptions, "hour12", dataPropertyDesc); + + /* When hour12 and extension key are set, hour12 takes precedence */ + + resolvedOptions = new Intl.DateTimeFormat("fr-u-hc-h24", { + timeStyle, + hour12: true, + }).resolvedOptions(); + + assert(hour12Values.includes(resolvedOptions.hourCycle)); + assert.sameValue(resolvedOptions.hour12, true); + + verifyProperty(resolvedOptions, "hourCycle", dataPropertyDesc); + verifyProperty(resolvedOptions, "hour12", dataPropertyDesc); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle.js new file mode 100644 index 0000000000..07c3913191 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle.js @@ -0,0 +1,101 @@ +// Copyright 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.resolvedOptions +description: > + Intl.DateTimeFormat.prototype.resolvedOptions properly + reflect hourCycle settings. +info: | + 12.4.5 Intl.DateTimeFormat.prototype.resolvedOptions() + +includes: [propertyHelper.js] +---*/ + +/* Values passed via unicode extension key work */ + +const hcValues = ['h11', 'h12', 'h23', 'h24']; +const hour12Values = ['h11', 'h12']; + +const dataPropertyDesc = { writable: true, enumerable: true, configurable: true }; + +for (const hcValue of hcValues) { + const resolvedOptions = new Intl.DateTimeFormat(`de-u-hc-${hcValue}`, { + hour: 'numeric' + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, hcValue); + assert.sameValue(resolvedOptions.hour12, hour12Values.includes(hcValue)); + + verifyProperty(resolvedOptions, 'hourCycle', dataPropertyDesc); + verifyProperty(resolvedOptions, 'hour12', dataPropertyDesc); +} + +/* Values passed via options work */ + +for (const hcValue of hcValues) { + const resolvedOptions = new Intl.DateTimeFormat(`en-US`, { + hour: 'numeric', + hourCycle: hcValue + }).resolvedOptions(); + + assert.sameValue(resolvedOptions.hourCycle, hcValue); + assert.sameValue(resolvedOptions.hour12, hour12Values.includes(hcValue)); + + verifyProperty(resolvedOptions, 'hourCycle', dataPropertyDesc); + verifyProperty(resolvedOptions, 'hour12', dataPropertyDesc); +} + +/* When both extension key and option is passed, option takes precedence */ + +let resolvedOptions = new Intl.DateTimeFormat(`en-US-u-hc-h12`, { + hour: 'numeric', + hourCycle: 'h23' +}).resolvedOptions(); + +assert.sameValue(resolvedOptions.hourCycle, 'h23'); +assert.sameValue(resolvedOptions.hour12, false); + +verifyProperty(resolvedOptions, 'hourCycle', dataPropertyDesc); +verifyProperty(resolvedOptions, 'hour12', dataPropertyDesc); + +/* When hour12 and hourCycle are set, hour12 takes precedence */ + +resolvedOptions = new Intl.DateTimeFormat(`fr`, { + hour: 'numeric', + hour12: true, + hourCycle: 'h23' +}).resolvedOptions(); + +assert(hour12Values.includes(resolvedOptions.hourCycle)); +assert.sameValue(resolvedOptions.hour12, true); + +verifyProperty(resolvedOptions, 'hourCycle', dataPropertyDesc); +verifyProperty(resolvedOptions, 'hour12', dataPropertyDesc); + +/* When hour12 and extension key are set, hour12 takes precedence */ + +resolvedOptions = new Intl.DateTimeFormat(`fr-u-hc-h24`, { + hour: 'numeric', + hour12: true, +}).resolvedOptions(); + +assert(hour12Values.includes(resolvedOptions.hourCycle)); +assert.sameValue(resolvedOptions.hour12, true); + +verifyProperty(resolvedOptions, 'hourCycle', dataPropertyDesc); +verifyProperty(resolvedOptions, 'hour12', dataPropertyDesc); + +/* When the hour is not in the pattern, hourCycle and hour12 are not defined. */ + +resolvedOptions = new Intl.DateTimeFormat("fr", { + hourCycle: "h12", + hour12: false, +}).resolvedOptions(); + +assert.sameValue(resolvedOptions.hour, undefined, + "Precondition: hour should not be included by default"); +assert.sameValue(resolvedOptions.hourCycle, undefined); +assert.sameValue(resolvedOptions.hour12, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..5e2070baf0 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.resolvedoptions +description: > + Intl.DateTimeFormat.prototype.resolvedOptions.length is 0. +info: | + Intl.DateTimeFormat.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.prototype.resolvedOptions.length, 0); + +verifyNotEnumerable(Intl.DateTimeFormat.prototype.resolvedOptions, "length"); +verifyNotWritable(Intl.DateTimeFormat.prototype.resolvedOptions, "length"); +verifyConfigurable(Intl.DateTimeFormat.prototype.resolvedOptions, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..808c268e74 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.resolvedOptions +description: > + Intl.DateTimeFormat.prototype.resolvedOptions.name is "resolvedOptions". +info: | + 12.4.4 Intl.DateTimeFormat.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.prototype.resolvedOptions.name, "resolvedOptions"); + +verifyNotEnumerable(Intl.DateTimeFormat.prototype.resolvedOptions, "name"); +verifyNotWritable(Intl.DateTimeFormat.prototype.resolvedOptions, "name"); +verifyConfigurable(Intl.DateTimeFormat.prototype.resolvedOptions, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-dayPeriod.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-dayPeriod.js new file mode 100644 index 0000000000..fa49b52b68 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-dayPeriod.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [arrayContains.js] +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +const options = new Intl.DateTimeFormat([], { + "dayPeriod": "short", + "hour": "numeric", + "minute": "numeric", +}).resolvedOptions(); + +const expected = [ + "locale", + "calendar", + "numberingSystem", + "timeZone", + "hourCycle", + "hour12", + "dayPeriod", + "hour", + "minute", +]; + +let actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(arrayContains(actual, expected)); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-fractionalSecondDigits.js new file mode 100644 index 0000000000..a5160bb3c8 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-fractionalSecondDigits.js @@ -0,0 +1,37 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [arrayContains.js] +features: [Intl.DateTimeFormat-fractionalSecondDigits] +---*/ + +const options = new Intl.DateTimeFormat([], { + "fractionalSecondDigits": 3, + "minute": "numeric", + "second": "numeric", +}).resolvedOptions(); + +const expected = [ + "locale", + "calendar", + "numberingSystem", + "timeZone", + "minute", + "second", + "fractionalSecondDigits", +]; + +let actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(arrayContains(actual, expected)); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-style.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-style.js new file mode 100644 index 0000000000..338701c4de --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order-style.js @@ -0,0 +1,43 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [arrayContains.js] +features: [Intl.DateTimeFormat-datetimestyle] +---*/ + +const options = new Intl.DateTimeFormat([], { + "hourCycle": "h24", + "weekday": "short", + "era": "short", + "year": "numeric", + "month": "numeric", + "day": "numeric", + "hour": "numeric", + "minute": "numeric", + "second": "numeric", + "timeZoneName": "short", +}).resolvedOptions(); + +const expected = [ + "locale", + "calendar", + "numberingSystem", + "timeZone", + "hourCycle", + "hour12", +]; + +let actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(arrayContains(actual, expected)); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js new file mode 100644 index 0000000000..8f50b76b2d --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js @@ -0,0 +1,51 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [arrayContains.js] +---*/ + +const options = new Intl.DateTimeFormat([], { + "hourCycle": "h24", + "weekday": "short", + "era": "short", + "year": "numeric", + "month": "numeric", + "day": "numeric", + "hour": "numeric", + "minute": "numeric", + "second": "numeric", + "timeZoneName": "short", +}).resolvedOptions(); + +const expected = [ + "locale", + "calendar", + "numberingSystem", + "timeZone", + "hourCycle", + "hour12", + "weekday", + "era", + "year", + "month", + "day", + "hour", + "minute", + "second", + "timeZoneName", +]; + +let actual = Object.getOwnPropertyNames(options); + +// Ensure all expected items are in actual and also allow other properties +// implemented in new proposals. +assert(arrayContains(actual, expected)); +for (var i = 1; i < expected.length; i++) { + // Ensure the order as expected but allow additional new property in between + assert(actual.indexOf(expected[i-1]) < actual.indexOf(expected[i])); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..c4f9742f07 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype.resolvedoptions +description: > + "resolvedOptions" property of Intl.DateTimeFormat.prototype. +info: | + Intl.DateTimeFormat.prototype.resolvedOptions () + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.DateTimeFormat.prototype, "resolvedOptions"); +verifyWritable(Intl.DateTimeFormat.prototype, "resolvedOptions"); +verifyConfigurable(Intl.DateTimeFormat.prototype, "resolvedOptions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/resolved-locale-with-hc-unicode.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/resolved-locale-with-hc-unicode.js new file mode 100644 index 0000000000..5b0516ca27 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/resolved-locale-with-hc-unicode.js @@ -0,0 +1,89 @@ +// Copyright 2018 André Bargull. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.prototype.resolvedOptions +description: > + The resolved locale doesn't include a hc Unicode extension value if the + hour12 or hourCycle option is also present. +info: | + 12.1.1 InitializeDateTimeFormat(dateTimeFormat, locales, options) + ... + 6. Let hour12 be ? GetOption(options, "hour12", "boolean", undefined, undefined). + 7. Let hourCycle be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined). + 8. If hour12 is not undefined, then + a. Let hourCycle be null. + 9. Set opt.[[hc]] to hourCycle. + ... + + 9.2.6 ResolveLocale(availableLocales, requestedLocales, options, relevantExtensionKeys, localeData) + ... + 8. For each element key of relevantExtensionKeys in List order, do + ... + i. If options has a field [[<key>]], then + i. Let optionsValue be options.[[<key>]]. + ii. Assert: Type(optionsValue) is either String, Undefined, or Null. + iii. If keyLocaleData contains optionsValue, then + 1. If SameValue(optionsValue, value) is false, then + a. Let value be optionsValue. + b. Let supportedExtensionAddition be "". + ... +---*/ + +var defaultLocale = new Intl.DateTimeFormat().resolvedOptions().locale; +var defaultLocaleWithHourCycle = defaultLocale + "-u-hc-h11"; + +function assertLocale(locale, expectedLocale, options, message) { + var resolved = new Intl.DateTimeFormat(locale, { + hour: "2-digit", + hour12: options.hour12, + hourCycle: options.hourCycle, + }).resolvedOptions(); + assert.sameValue(resolved.locale, expectedLocale, message + " (With hour option.)"); + + // Also test the case when no hour option is present at all. + // The resolved options don't include hour12 and hourCycle if the date-time + // formatter doesn't include an hour option. This restriction doesn't apply + // to the hc Unicode extension value. + resolved = new Intl.DateTimeFormat(locale, { + hour12: options.hour12, + hourCycle: options.hourCycle, + }).resolvedOptions(); + assert.sameValue(resolved.locale, expectedLocale, message + " (Without hour option.)"); +} + +assertLocale(defaultLocaleWithHourCycle, defaultLocale, { + hour12: false, + hourCycle: "h23", +}, "hour12 and hourCycle options and hc Unicode extension value are present."); + +assertLocale(defaultLocaleWithHourCycle, defaultLocale, { + hour12: false, +}, "hour12 option and hc Unicode extension value are present."); + +assertLocale(defaultLocaleWithHourCycle, defaultLocale, { + hourCycle: "h23", +}, "hourCycle option and hc Unicode extension value are present."); + +assertLocale(defaultLocaleWithHourCycle, defaultLocaleWithHourCycle, { +}, "Only hc Unicode extension value is present."); + +// And make sure the hc Unicode extension doesn't get added if it's not present +// in the requested locale. +assertLocale(defaultLocale, defaultLocale, { + hour12: false, + hourCycle: "h23", +}, "hour12 and hourCycle options are present, but no hc Unicode extension value."); + +assertLocale(defaultLocale, defaultLocale, { + hour12: false, +}, "hourCycle option is present, but no hc Unicode extension value."); + +assertLocale(defaultLocale, defaultLocale, { + hourCycle: "h23", +}, "hourCycle option is present, but no hc Unicode extension value."); + +assertLocale(defaultLocale, defaultLocale, { +}, "No options are present and no hc Unicode extension value."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..857452379f --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/resolvedOptions/shell.js @@ -0,0 +1,50 @@ +// GENERATED, DO NOT EDIT +// file: arrayContains.js +// Copyright (C) 2017 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Verify that a subArray is contained within an array. +defines: [arrayContains] +---*/ + +/** + * @param {Array} array + * @param {Array} subArray + */ + +function arrayContains(array, subArray) { + var found; + for (var i = 0; i < subArray.length; i++) { + found = false; + for (var j = 0; j < array.length; j++) { + if (subArray[i] === array[j]) { + found = true; + break; + } + } + if (!found) { + return false; + } + } + return true; +} + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/shell.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/this-value-datetimeformat-prototype.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/this-value-datetimeformat-prototype.js new file mode 100644 index 0000000000..34db44141b --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/this-value-datetimeformat-prototype.js @@ -0,0 +1,17 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-properties-of-intl-datetimeformat-prototype-object +description: > + Tests that Intl.DateTimeFormat.prototype is not an object that has + been initialized as an Intl.DateTimeFormat. +author: Roozbeh Pournader +---*/ + +// test by calling a function that should fail as "this" is not an object +// initialized as an Intl.DateTimeFormat +assert.throws(TypeError, () => Intl.DateTimeFormat.prototype.format(0), + "Intl.DateTimeFormat's prototype is not an object that has been initialized as an Intl.DateTimeFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/this-value-not-datetimeformat.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/this-value-not-datetimeformat.js new file mode 100644 index 0000000000..4805ca2f69 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/this-value-not-datetimeformat.js @@ -0,0 +1,28 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.3_b +description: > + Tests that Intl.DateTimeFormat.prototype functions throw a + TypeError if called on a non-object value or an object that hasn't + been initialized as a DateTimeFormat. +author: Norbert Lindenberg +---*/ + +var functions = { + "format getter": Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get, + resolvedOptions: Intl.DateTimeFormat.prototype.resolvedOptions +}; +var invalidTargets = [undefined, null, true, 0, "DateTimeFormat", [], {}]; + +Object.getOwnPropertyNames(functions).forEach(function (functionName) { + var f = functions[functionName]; + invalidTargets.forEach(function (target) { + assert.throws(TypeError, function() { + f.call(target); + }, "Calling " + functionName + " on " + target + " was not rejected."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString-changed-tag.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString-changed-tag.js new file mode 100644 index 0000000000..69b853ad0a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString-changed-tag.js @@ -0,0 +1,30 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype-@@tostringtag +description: > + Object.prototype.toString utilizes Intl.DateTimeFormat.prototype[@@toStringTag]. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". + + Intl.DateTimeFormat.prototype [ @@toStringTag ] + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.toStringTag] +---*/ + +Object.defineProperty(Intl.DateTimeFormat.prototype, Symbol.toStringTag, { + value: "test262", +}); + +assert.sameValue(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object test262]"); +assert.sameValue(Object.prototype.toString.call(new Intl.DateTimeFormat()), "[object test262]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString-removed-tag.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString-removed-tag.js new file mode 100644 index 0000000000..170562a720 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString-removed-tag.js @@ -0,0 +1,24 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype-@@tostringtag +description: > + Object.prototype.toString doesn't special-case neither Intl.DateTimeFormat instances nor its prototype. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". +features: [Symbol.toStringTag] +---*/ + +delete Intl.DateTimeFormat.prototype[Symbol.toStringTag]; + +assert.sameValue(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object Object]"); +assert.sameValue(Object.prototype.toString.call(new Intl.DateTimeFormat()), "[object Object]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString.js new file mode 100644 index 0000000000..f8e5d3db50 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toString.js @@ -0,0 +1,26 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype-@@tostringtag +description: > + Object.prototype.toString utilizes Intl.DateTimeFormat.prototype[@@toStringTag]. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". + + Intl.DateTimeFormat.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl.DateTimeFormat". +features: [Symbol.toStringTag] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object Intl.DateTimeFormat]"); +assert.sameValue(Object.prototype.toString.call(new Intl.DateTimeFormat()), "[object Intl.DateTimeFormat]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toStringTag.js new file mode 100644 index 0000000000..b118adeac8 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/prototype/toStringTag/toStringTag.js @@ -0,0 +1,25 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.prototype-@@tostringtag +description: > + Property descriptor of Intl.DateTimeFormat.prototype[@@toStringTag]. +info: | + Intl.DateTimeFormat.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl.DateTimeFormat". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.toStringTag] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.DateTimeFormat.prototype, Symbol.toStringTag, { + value: "Intl.DateTimeFormat", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/required-date-time-formats.js b/js/src/tests/test262/intl402/DateTimeFormat/required-date-time-formats.js new file mode 100644 index 0000000000..6a17fc5edb --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/required-date-time-formats.js @@ -0,0 +1,48 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.2.3_c +description: > + Tests that Intl.DateTimeFormat provides the required date-time + format component subsets. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var locales = ["de-DE", "en-US", "hi-IN", "id-ID", "ja-JP", "th-TH", "zh-Hans-CN", "zh-Hant-TW", "zxx"]; +var subsets = [ + {weekday: "long", year: "numeric", month: "numeric", day: "numeric", + hour: "numeric", minute: "numeric", second: "numeric"}, + {weekday: "long", year: "numeric", month: "numeric", day: "numeric"}, + {year: "numeric", month: "numeric", day: "numeric"}, + {year: "numeric", month: "numeric"}, + {month: "numeric", day: "numeric"}, + {hour: "numeric", minute: "numeric", second: "numeric"}, + {hour: "numeric", minute: "numeric"} +]; + +locales.forEach(function (locale) { + subsets.forEach(function (subset) { + var format = new Intl.DateTimeFormat([locale], subset); + var actual = format.resolvedOptions(); + getDateTimeComponents().forEach(function (component) { + if (actual.hasOwnProperty(component)) { + assert(subset.hasOwnProperty(component), + "Unrequested component " + component + + " added to requested subset " + JSON.stringify(subset) + + "; locale " + locale + "."); + assert.notSameValue(getDateTimeComponentValues(component).indexOf(actual[component]), -1, + "Invalid value " + actual[component] + " for date-time component " + component + "." + + " (Testing locale " + locale + "; subset " + JSON.stringify(subset) + ")"); + } else { + assert.sameValue(subset.hasOwnProperty(component), false, + "Missing component " + component + + " from requested subset " + JSON.stringify(subset) + + "; locale " + locale + "."); + } + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/shell.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/subclassing.js b/js/src/tests/test262/intl402/DateTimeFormat/subclassing.js new file mode 100644 index 0000000000..c7167676b8 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/subclassing.js @@ -0,0 +1,30 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.2 +description: Tests that Intl.DateTimeFormat can be subclassed. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +// get a date-time format and have it format an array of dates for comparison with the subclass +var locales = ["tlh", "id", "en"]; +var a = [new Date(0), Date.now(), new Date(Date.parse("1989-11-09T17:57:00Z"))]; +var referenceDateTimeFormat = new Intl.DateTimeFormat(locales); +var referenceFormatted = a.map(referenceDateTimeFormat.format); + +class MyDateTimeFormat extends Intl.DateTimeFormat { + constructor(locales, options) { + super(locales, options); + // could initialize MyDateTimeFormat properties + } + // could add methods to MyDateTimeFormat.prototype +} + +var format = new MyDateTimeFormat(locales); +var actual = a.map(format.format); +assert.compareArray(actual, referenceFormatted); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/basic.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/basic.js new file mode 100644 index 0000000000..8b4e2884e7 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/basic.js @@ -0,0 +1,25 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.2.2_a +description: > + Tests that Intl.DateTimeFormat has a supportedLocalesOf property, + and it works as planned. +author: Roozbeh Pournader +---*/ + +var defaultLocale = new Intl.DateTimeFormat().resolvedOptions().locale; +var notSupported = 'zxx'; // "no linguistic content" +var requestedLocales = [defaultLocale, notSupported]; + +var supportedLocales; + +assert(Intl.DateTimeFormat.hasOwnProperty('supportedLocalesOf'), "Intl.DateTimeFormat doesn't have a supportedLocalesOf property."); + +supportedLocales = Intl.DateTimeFormat.supportedLocalesOf(requestedLocales); +assert.sameValue(supportedLocales.length, 1, 'The length of supported locales list is not 1.'); + +assert.sameValue(supportedLocales[0], defaultLocale, 'The default locale is not returned in the supported list.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/browser.js diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/builtin.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/builtin.js new file mode 100644 index 0000000000..5af3ea6504 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.2.2_L15 +description: > + Tests that Intl.DateTimeFormat.supportedLocalesOf meets the + requirements for built-in objects defined by the introduction of + chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.DateTimeFormat.supportedLocalesOf), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.DateTimeFormat.supportedLocalesOf), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.DateTimeFormat.supportedLocalesOf), Function.prototype); + +assert.sameValue(Intl.DateTimeFormat.supportedLocalesOf.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.DateTimeFormat.supportedLocalesOf), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/length.js new file mode 100644 index 0000000000..728265c107 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.supportedlocalesof +description: > + Intl.DateTimeFormat.supportedLocalesOf.length is 1. +info: | + Intl.DateTimeFormat.supportedLocalesOf ( locales [ , options ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.supportedLocalesOf.length, 1); + +verifyNotEnumerable(Intl.DateTimeFormat.supportedLocalesOf, "length"); +verifyNotWritable(Intl.DateTimeFormat.supportedLocalesOf, "length"); +verifyConfigurable(Intl.DateTimeFormat.supportedLocalesOf, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/name.js new file mode 100644 index 0000000000..1575c0d168 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DateTimeFormat.supportedLocalesOf +description: > + Intl.DateTimeFormat.supportedLocalesOf.name is "supportedLocalesOf". +info: | + 12.3.2 Intl.DateTimeFormat.supportedLocalesOf (locales [ , options ]) + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.DateTimeFormat.supportedLocalesOf.name, "supportedLocalesOf"); + +verifyNotEnumerable(Intl.DateTimeFormat.supportedLocalesOf, "name"); +verifyNotWritable(Intl.DateTimeFormat.supportedLocalesOf, "name"); +verifyConfigurable(Intl.DateTimeFormat.supportedLocalesOf, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/prop-desc.js new file mode 100644 index 0000000000..3a81c9f952 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.datetimeformat.supportedlocalesof +description: > + "supportedLocalesOf" property of Intl.DateTimeFormat. +info: | + Intl.DateTimeFormat.supportedLocalesOf ( locales [ , options ] ) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.DateTimeFormat, "supportedLocalesOf"); +verifyWritable(Intl.DateTimeFormat, "supportedLocalesOf"); +verifyConfigurable(Intl.DateTimeFormat, "supportedLocalesOf"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/taint-Object-prototype.js b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/taint-Object-prototype.js new file mode 100644 index 0000000000..47ed85a18c --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/supportedLocalesOf/taint-Object-prototype.js @@ -0,0 +1,16 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 12.2.2_b +description: > + Tests that Intl.DateTimeFormat.supportedLocalesOf doesn't access + arguments that it's not given. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintDataProperty(Object.prototype, "1"); +new Intl.DateTimeFormat("und"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-date-time-components.js b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-date-time-components.js new file mode 100644 index 0000000000..a05e77b80e --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-date-time-components.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_22 +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintProperties(["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZone"]); + +var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; +assert(isCanonicalizedStructurallyValidLanguageTag(locale), "DateTimeFormat returns invalid locale " + locale + "."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-dayPeriod.js b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-dayPeriod.js new file mode 100644 index 0000000000..a0f21acc24 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-dayPeriod.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(release_or_beta) -- Intl.DateTimeFormat-dayPeriod is not released yet +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +includes: [testIntl.js] +features: [Intl.DateTimeFormat-dayPeriod] +---*/ + +taintProperties(["dayPeriod"]); + +var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; +assert(isCanonicalizedStructurallyValidLanguageTag(locale), "DateTimeFormat returns invalid locale " + locale + "."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-fractionalSecondDigits.js b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-fractionalSecondDigits.js new file mode 100644 index 0000000000..6b7836e1c8 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype-fractionalSecondDigits.js @@ -0,0 +1,18 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializedatetimeformat +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +includes: [testIntl.js] +features: [Intl.DateTimeFormat-fractionalSecondDigits] +---*/ + +taintProperties(["fractionalSecondDigits"]); + +var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; +assert(isCanonicalizedStructurallyValidLanguageTag(locale), "DateTimeFormat returns invalid locale " + locale + "."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype.js b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype.js new file mode 100644 index 0000000000..5dd7b61535 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/taint-Object-prototype.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_5 +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintProperties(["localeMatcher"]); + +var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; +assert(isCanonicalizedStructurallyValidLanguageTag(locale), "DateTimeFormat returns invalid locale " + locale + "."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/test-option-date-time-components.js b/js/src/tests/test262/intl402/DateTimeFormat/test-option-date-time-components.js new file mode 100644 index 0000000000..a0e0a16dc7 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/test-option-date-time-components.js @@ -0,0 +1,17 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_23 +description: > + Tests that the options for the date and time components are + processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +getDateTimeComponents().forEach(function (component) { + testOption(Intl.DateTimeFormat, component, "string", getDateTimeComponentValues(component), undefined, {isILD: true}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/test-option-formatMatcher.js b/js/src/tests/test262/intl402/DateTimeFormat/test-option-formatMatcher.js new file mode 100644 index 0000000000..41c25d6e99 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/test-option-formatMatcher.js @@ -0,0 +1,13 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_25 +description: Tests that the option formatMatcher is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.DateTimeFormat, "formatMatcher", "string", ["basic", "best fit"], "best fit", {noReturn: true}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/test-option-hour12.js b/js/src/tests/test262/intl402/DateTimeFormat/test-option-hour12.js new file mode 100644 index 0000000000..c6a4124bf9 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/test-option-hour12.js @@ -0,0 +1,16 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_18 +description: Tests that the option hour12 is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.DateTimeFormat, "hour12", "boolean", undefined, undefined, + {extra: {any: {hour: "numeric", minute: "numeric"}}}); +testOption(Intl.DateTimeFormat, "hour12", "boolean", undefined, undefined, + {noReturn: true}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/test-option-localeMatcher.js b/js/src/tests/test262/intl402/DateTimeFormat/test-option-localeMatcher.js new file mode 100644 index 0000000000..6adf184682 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/test-option-localeMatcher.js @@ -0,0 +1,13 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 12.1.1_6 +description: Tests that the option localeMatcher is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.DateTimeFormat, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/this-value-ignored.js b/js/src/tests/test262/intl402/DateTimeFormat/this-value-ignored.js new file mode 100644 index 0000000000..e96110d1ca --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/this-value-ignored.js @@ -0,0 +1,37 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl-datetimeformat-constructor +description: > + Tests that the this-value is ignored in DateTimeFormat, if the this-value + isn't a DateTimeFormat instance. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + if (Constructor === Intl.DateTimeFormat) + return; + + var obj, newObj; + + // variant 1: use constructor in a "new" expression + obj = new Constructor(); + newObj = Intl.DateTimeFormat.call(obj); + assert.notSameValue(obj, newObj, "DateTimeFormat object created with \"new\" was not ignored as this-value."); + + // variant 2: use constructor as a function + if (Constructor !== Intl.Collator && + Constructor !== Intl.NumberFormat && + Constructor !== Intl.DateTimeFormat) + { + // Newer Intl constructors are not callable as a function. + return; + } + obj = Constructor(); + newObj = Intl.DateTimeFormat.call(obj); + assert.notSameValue(obj, newObj, "DateTimeFormat object created with constructor as function was not ignored as this-value."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/timezone-canonicalized.js b/js/src/tests/test262/intl402/DateTimeFormat/timezone-canonicalized.js new file mode 100644 index 0000000000..e7e28cd0e6 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/timezone-canonicalized.js @@ -0,0 +1,37 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.4_c +description: > + Tests that additional time zone names, if accepted, are handled + correctly. +author: Norbert Lindenberg +---*/ + +// canonicalization specified in conformance clause +var additionalTimeZoneNames = { + "Etc/GMT": "UTC", + "Greenwich": "UTC", + "PRC": "Asia/Shanghai", + "AmErIcA/LoS_aNgElEs": "America/Los_Angeles", + "etc/gmt+7": "Etc/GMT+7" +}; + +Object.getOwnPropertyNames(additionalTimeZoneNames).forEach(function (name) { + var format, error; + try { + format = new Intl.DateTimeFormat([], {timeZone: name}); + } catch (e) { + error = e; + } + if (error === undefined) { + var actual = format.resolvedOptions().timeZone; + var expected = additionalTimeZoneNames[name]; + assert.sameValue(actual, expected, "Time zone name " + name + " was accepted, but incorrectly canonicalized."); + } else { + assert(error instanceof RangeError, "Time zone name " + name + " was rejected with wrong error " + error.name + "."); + } +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/timezone-invalid.js b/js/src/tests/test262/intl402/DateTimeFormat/timezone-invalid.js new file mode 100644 index 0000000000..f42ffd0201 --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/timezone-invalid.js @@ -0,0 +1,28 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.4_b +description: Tests that invalid time zone names are not accepted. +author: Norbert Lindenberg +---*/ + +var invalidTimeZoneNames = [ + "", + "MEZ", // localized abbreviation + "Pacific Time", // localized long form + "cnsha", // BCP 47 time zone code + "invalid", // as the name says + "Europe/İstanbul", // non-ASCII letter + "asıa/baku", // non-ASCII letter + "europe/brußels" // non-ASCII letter +]; + +invalidTimeZoneNames.forEach(function (name) { + // this must throw an exception for an invalid time zone name + assert.throws(RangeError, function() { + var format = new Intl.DateTimeFormat(["de-de"], {timeZone: name}); + }, "Invalid time zone name " + name + " was not rejected."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DateTimeFormat/timezone-utc.js b/js/src/tests/test262/intl402/DateTimeFormat/timezone-utc.js new file mode 100644 index 0000000000..f27d109b1a --- /dev/null +++ b/js/src/tests/test262/intl402/DateTimeFormat/timezone-utc.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.4_a +description: Tests that valid time zone names are accepted. +author: Norbert Lindenberg +---*/ + +var validTimeZoneNames = [ + "UTC", + "utc" // time zone names are case-insensitive +]; + +validTimeZoneNames.forEach(function (name) { + // this must not throw an exception for a valid time zone name + var format = new Intl.DateTimeFormat(["de-de"], {timeZone: name}); + assert.sameValue(format.resolvedOptions().timeZone, name.toUpperCase(), "Time zone name " + name + " was not correctly accepted."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/browser.js b/js/src/tests/test262/intl402/DisplayNames/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/browser.js diff --git a/js/src/tests/test262/intl402/DisplayNames/ctor-custom-get-prototype-poison-throws.js b/js/src/tests/test262/intl402/DisplayNames/ctor-custom-get-prototype-poison-throws.js new file mode 100644 index 0000000000..cb68a161ba --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/ctor-custom-get-prototype-poison-throws.js @@ -0,0 +1,46 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt from Get Prototype from a custom NewTarget +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + ... + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + 3. Let proto be ? Get(constructor, "prototype"). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.DisplayNames, Reflect, Proxy] +---*/ + +var custom = new Proxy(new Function(), { + get(target, key) { + if (key === 'prototype') { + throw new Test262Error(); + } + + return target[key]; + } +}); + +assert.throws(Test262Error, () => { + Reflect.construct(Intl.DisplayNames, [], custom); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/ctor-custom-prototype.js b/js/src/tests/test262/intl402/DisplayNames/ctor-custom-prototype.js new file mode 100644 index 0000000000..7ee1e0d702 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/ctor-custom-prototype.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Custom Prototype of the returned object based on the NewTarget +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + ... + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + 3. Let proto be ? Get(constructor, "prototype"). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.DisplayNames, Reflect] +---*/ + +var custom = new Function(); +custom.prototype = {}; + +const obj = Reflect.construct(Intl.DisplayNames, [undefined, {type: 'language'}], custom); + +assert.sameValue(Object.getPrototypeOf(obj), custom.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/ctor-default-prototype.js b/js/src/tests/test262/intl402/DisplayNames/ctor-default-prototype.js new file mode 100644 index 0000000000..cce416f9ff --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/ctor-default-prototype.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Prototype of the returned object is DisplayNames.prototype +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 27. Return displayNames. +features: [Intl.DisplayNames] +---*/ + +var obj = new Intl.DisplayNames(undefined, {type: 'language'}); + +assert.sameValue(Object.getPrototypeOf(obj), Intl.DisplayNames.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/instance-extensible.js b/js/src/tests/test262/intl402/DisplayNames/instance-extensible.js new file mode 100644 index 0000000000..93d002091f --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/instance-extensible.js @@ -0,0 +1,40 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Instance is extensible +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + ObjectCreate ( proto [ , internalSlotsList ] ) + + ... + 2. Let obj be a newly created object with an internal slot for each name in internalSlotsList. + 3. Set obj's essential internal methods to the default ordinary object definitions specified in 9.1. + 4. Set obj.[[Prototype]] to proto. + 5. Set obj.[[Extensible]] to true. + 6. Return obj. +features: [Intl.DisplayNames] +---*/ + +var obj = new Intl.DisplayNames(undefined, {type: 'language'}); + +assert(Object.isExtensible(obj)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/length.js b/js/src/tests/test262/intl402/DisplayNames/length.js new file mode 100644 index 0000000000..2e8c435bd9 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Intl.DisplayNames.length is 2. +info: | + ECMAScript Standard Built-in Objects: + + 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 }. +includes: [propertyHelper.js] +features: [Intl.DisplayNames] +---*/ + +verifyProperty(Intl.DisplayNames, "length", { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/locales-invalid-throws.js b/js/src/tests/test262/intl402/DisplayNames/locales-invalid-throws.js new file mode 100644 index 0000000000..70bc899905 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/locales-invalid-throws.js @@ -0,0 +1,34 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Throws TypeError if locales is not undefined, a string, or an array-like object. +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + 3. Let requestedLocales be ? CanonicalizeLocaleList(locales). + ... + + CanonicalizeLocaleList ( locales ) + + 1. If locales is undefined, then + a. Return a new empty List. + 2. Let seen be a new empty List. + 3. If Type(locales) is String, then + a. Let O be CreateArrayFromList(« locales »). + 4. Else, + a. Let O be ? ToObject(locales). + 5. Let len be ? ToLength(? Get(O, "length")). +features: [Intl.DisplayNames] +---*/ + +assert.throws(TypeError, () => { + new Intl.DisplayNames(null); +}, 'null'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/locales-length-poison-throws.js b/js/src/tests/test262/intl402/DisplayNames/locales-length-poison-throws.js new file mode 100644 index 0000000000..e88e37a36a --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/locales-length-poison-throws.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from Get Locales length +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + 3. Let requestedLocales be ? CanonicalizeLocaleList(locales). + ... + + CanonicalizeLocaleList ( locales ) + + 1. If locales is undefined, then + a. Return a new empty List. + 2. Let seen be a new empty List. + 3. If Type(locales) is String, then + a. Let O be CreateArrayFromList(« locales »). + 4. Else, + a. Let O be ? ToObject(locales). + 5. Let len be ? ToLength(? Get(O, "length")). +features: [Intl.DisplayNames, Symbol] +---*/ + +var locales = {}; + +Object.defineProperty(locales, 'length', { + get() { + throw new Test262Error(); + } +}); + +assert.throws(Test262Error, () => { + new Intl.DisplayNames(locales); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/locales-length-tolength-throws.js b/js/src/tests/test262/intl402/DisplayNames/locales-length-tolength-throws.js new file mode 100644 index 0000000000..a9c8b3e1e0 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/locales-length-tolength-throws.js @@ -0,0 +1,75 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from Locales invalid length +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + 3. Let requestedLocales be ? CanonicalizeLocaleList(locales). + ... + + CanonicalizeLocaleList ( locales ) + + 1. If locales is undefined, then + a. Return a new empty List. + 2. Let seen be a new empty List. + 3. If Type(locales) is String, then + a. Let O be CreateArrayFromList(« locales »). + 4. Else, + a. Let O be ? ToObject(locales). + 5. Let len be ? ToLength(? Get(O, "length")). + + ToLength ( argument ) + + 1. Let len be ? ToInteger(argument). + ... +features: [Intl.DisplayNames, Symbol, BigInt] +---*/ + +var locales = { + length: { + valueOf() { + throw new Test262Error(); + } + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames(locales); +}, 'poisoned valueOf for ToNumber'); + +locales.length = { + [Symbol.toPrimitive]() { + throw new Test262Error(); + } +}; +assert.throws(Test262Error, () => { + new Intl.DisplayNames(locales); +}, 'poisoned ToPrimitive for ToNumber'); + +locales.length = { + toString() { + throw new Test262Error(); + } +}; +assert.throws(Test262Error, () => { + new Intl.DisplayNames(locales); +}, 'poisoned toString for ToNumber'); + +locales.length = Symbol(); +assert.throws(TypeError, () => { + new Intl.DisplayNames(locales); +}, 'length is Symbol'); + +locales.length = BigInt(1); +assert.throws(TypeError, () => { + new Intl.DisplayNames(locales); +}, 'length is BigInt'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/locales-symbol-length.js b/js/src/tests/test262/intl402/DisplayNames/locales-symbol-length.js new file mode 100644 index 0000000000..53f07eca22 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/locales-symbol-length.js @@ -0,0 +1,64 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + CanonicalizeLocaleList tries to fetch length from Object. +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + 3. Let requestedLocales be ? CanonicalizeLocaleList(locales). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + + CanonicalizeLocaleList ( locales ) + + 1. If locales is undefined, then + a. Return a new empty List. + 2. Let seen be a new empty List. + 3. If Type(locales) is String, then + a. Let O be CreateArrayFromList(« locales »). + 4. Else, + a. Let O be ? ToObject(locales). + 5. Let len be ? ToLength(? Get(O, "length")). +features: [Intl.DisplayNames, Symbol] +locale: [en] +includes: [compareArray.js] +---*/ + +let calls = []; +let symbol = Symbol(); + +Symbol.prototype.length = 1; + +Object.defineProperty(Symbol.prototype, 'length', { + get() { + assert.notSameValue(this, symbol, 'this is an object from given symbol'); + assert.sameValue(this.valueOf(), symbol, 'internal value is the symbol'); + assert(this instanceof Symbol); + calls.push('length'); + return 1; + } +}); + +Object.defineProperty(Symbol.prototype, '0', { + get() { + assert.notSameValue(this, symbol, 'this is an object from given symbol'); + assert.sameValue(this.valueOf(), symbol, 'internal value is the symbol'); + assert(this instanceof Symbol); + calls.push('0'); + return 'en'; + } +}); + +new Intl.DisplayNames(symbol, {type: 'language'}); + +assert.compareArray(calls, ['length', '0']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/name.js b/js/src/tests/test262/intl402/DisplayNames/name.js new file mode 100644 index 0000000000..6cfaf9855f --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/name.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Intl.DisplayNames.name is "DisplayNames". +info: | + 17 ECMAScript Standard Built-in Objects: + + 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, the name property of a built-in Function object, + if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.DisplayNames] +---*/ + +verifyProperty(Intl.DisplayNames, "name", { + value: "DisplayNames", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-fallback-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-fallback-abrupt-throws.js new file mode 100644 index 0000000000..4f77f225a6 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-fallback-abrupt-throws.js @@ -0,0 +1,40 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption fallback +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames, Symbol] +locale: [en] +---*/ + +var options = { type: 'language' }; +Object.defineProperty(options, 'fallback', { + get() { throw new Test262Error(); }, +}); + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-fallback-invalid-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-fallback-invalid-throws.js new file mode 100644 index 0000000000..c1d6c5ae21 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-fallback-invalid-throws.js @@ -0,0 +1,59 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from an invalid fallback option +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », "language"). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + 2. If value is not undefined, then + ... + c. If type is "string", then + i. Let value be ? ToString(value). + d. If values is not undefined, then + i. If values does not contain an element equal to value, throw a RangeError exception. + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {fallback: 'err', type: 'language'}); +}, 'err'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {fallback: 'non', type: 'language'}); +}, 'non, not none'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {fallback: null, type: 'language'}); +}, 'null'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {fallback: '', type: 'language'}); +}, 'the empty string'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {fallback: ['code', 'none'], type: 'language'}); +}, 'an array with the valid options is not necessarily valid'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-fallback-toString-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-fallback-toString-abrupt-throws.js new file mode 100644 index 0000000000..231117aee4 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-fallback-toString-abrupt-throws.js @@ -0,0 +1,59 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption fallback +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames, Symbol] +locale: [en] +---*/ + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', { + type: 'language', fallback: { toString() { throw new Test262Error(); }} + }); +}, 'from toString'); + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', { + type: 'language', + fallback: {toString: undefined, valueOf() {throw new Test262Error(); }} + }); +}, 'from valueOf'); + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', { + type: 'language', + fallback: { [Symbol.toPrimitive]() { throw new Test262Error(); } } + }); +}, 'from ToPrimitive'); + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', { + type: 'language', + fallback: Symbol() + }); +}, 'symbol value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-fallback-valid.js b/js/src/tests/test262/intl402/DisplayNames/options-fallback-valid.js new file mode 100644 index 0000000000..b97245a3d2 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-fallback-valid.js @@ -0,0 +1,50 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Valid options for fallback +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +// results for option values verified in the tests for resolvedOptions + +const fallbacks = [ + undefined, + 'code', + 'none' +]; + +fallbacks.forEach(fallback => { + const obj = new Intl.DisplayNames('en', { fallback, type: 'language'}); + + assert(obj instanceof Intl.DisplayNames, `instanceof check - ${fallback}`); + assert.sameValue(Object.getPrototypeOf(obj), Intl.DisplayNames.prototype, `proto check - ${fallback}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-abrupt-throws.js new file mode 100644 index 0000000000..1cb0a8013c --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-abrupt-throws.js @@ -0,0 +1,39 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption localeMatcher +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +var options = {}; +Object.defineProperty(options, 'localeMatcher', { + get() { throw new Test262Error(); }, +}); + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-invalid-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-invalid-throws.js new file mode 100644 index 0000000000..a0f1cfd744 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-invalid-throws.js @@ -0,0 +1,69 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from an invalid localeMatcher option +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + 2. If value is not undefined, then + ... + c. If type is "string", then + i. Let value be ? ToString(value). + d. If values is not undefined, then + i. If values does not contain an element equal to value, throw a RangeError exception. + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +var options = { + localeMatcher: 'bestfit' // not "best fit" +}; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'bestfit'); + +options.localeMatcher = 'look up'; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'look up'); + +options.localeMatcher = null; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'null'); + +options.localeMatcher = ''; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'the empty string'); + +// The world could burn +options.localeMatcher = ['lookup', 'best fit']; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'an array with the valid options is not necessarily valid'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-toString-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-toString-abrupt-throws.js new file mode 100644 index 0000000000..64ecd3c1e9 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-toString-abrupt-throws.js @@ -0,0 +1,69 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption localeMatcher +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames, Symbol] +locale: [en] +---*/ + +var options = { + localeMatcher: { + toString() { + throw new Test262Error(); + } + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from toString'); + +options.localeMatcher = { + toString: undefined, + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from valueOf'); + +options.localeMatcher = { + [Symbol.toPrimitive]() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from ToPrimitive'); + +options.localeMatcher = Symbol(); + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', options); +}, 'symbol value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-valid.js b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-valid.js new file mode 100644 index 0000000000..c934443d8a --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-localeMatcher-valid.js @@ -0,0 +1,50 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Valid options for localeMatcher +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +// results for option values verified in the tests for resolvedOptions + +const localeMatchers = [ + undefined, + 'lookup', + 'best fit' +]; + +localeMatchers.forEach(localeMatcher => { + const obj = new Intl.DisplayNames('en', { localeMatcher, type: 'language' }); + + assert(obj instanceof Intl.DisplayNames, `instanceof check - ${localeMatcher}`); + assert.sameValue(Object.getPrototypeOf(obj), Intl.DisplayNames.prototype, `proto check - ${localeMatcher}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-null-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-null-throws.js new file mode 100644 index 0000000000..dca7bf9caa --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-null-throws.js @@ -0,0 +1,28 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Throws TypeError if options is null +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', null); +}, 'null'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-random-properties-unchecked.js b/js/src/tests/test262/intl402/DisplayNames/options-random-properties-unchecked.js new file mode 100644 index 0000000000..2bd057a4dd --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-random-properties-unchecked.js @@ -0,0 +1,54 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Random options are not checked or used, including case sensitive +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 7. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +var options = { type: 'language' }; +Object.defineProperty(options, 'fallBack', { + get() { throw new Test262Error(); } +}); +Object.defineProperty(options, 'localematcher', { + get() { throw new Test262Error(); } +}); +Object.defineProperty(options, 'locale-matcher', { + get() { throw new Test262Error(); } +}); +Object.defineProperty(options, 'Type', { + get() { throw new Test262Error(); } +}); + +var obj = new Intl.DisplayNames('en', options); + +assert(obj instanceof Intl.DisplayNames); +assert.sameValue(Object.getPrototypeOf(obj), Intl.DisplayNames.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-style-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-style-abrupt-throws.js new file mode 100644 index 0000000000..51d7d4a6d8 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-style-abrupt-throws.js @@ -0,0 +1,46 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption style +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency", "weekday", "month", "quarter", "dayPeriod", "dateTimeField" », "language"). + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +var options = {}; +Object.defineProperty(options, 'style', { + get() { throw new Test262Error(); }, +}); + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-style-invalid-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-style-invalid-throws.js new file mode 100644 index 0000000000..76083d3793 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-style-invalid-throws.js @@ -0,0 +1,77 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from an invalid style option +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + 2. If value is not undefined, then + ... + c. If type is "string", then + i. Let value be ? ToString(value). + d. If values is not undefined, then + i. If values does not contain an element equal to value, throw a RangeError exception. + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +var options = { + style: 'small' +}; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'small'); + +options.style = 'very long'; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'very long'); + +options.style = 'full'; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'full'); + +options.style = null; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'null'); + +options.style = ''; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'the empty string'); + +options.style = ['narrow', 'short', 'long']; + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', options); +}, 'an array with the valid options is not necessarily valid'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-style-toString-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-style-toString-abrupt-throws.js new file mode 100644 index 0000000000..ac03b3ce1e --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-style-toString-abrupt-throws.js @@ -0,0 +1,72 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption style +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames, Symbol] +locale: [en] +---*/ + +var options = { + style: { + toString() { + throw new Test262Error(); + } + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from toString'); + +options.style = { + toString: undefined, + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from valueOf'); + +options.style = { + [Symbol.toPrimitive]() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from ToPrimitive'); + +options.style = Symbol(); + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', options); +}, 'symbol value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-style-valid.js b/js/src/tests/test262/intl402/DisplayNames/options-style-valid.js new file mode 100644 index 0000000000..e2a8fd9890 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-style-valid.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Valid options for localeMatcher +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +// results for option values verified in the tests for resolvedOptions + +const styles = [ + undefined, + 'narrow', + 'short', + 'long' +]; + +const types = ['language', 'region', 'script', 'currency']; + +types.forEach( type => { + styles.forEach(style => { + var obj = new Intl.DisplayNames('en', { style, type }); + + assert(obj instanceof Intl.DisplayNames, `instanceof check - ${style}`); + assert.sameValue(Object.getPrototypeOf(obj), Intl.DisplayNames.prototype, `proto check - ${style}`); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-type-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-type-abrupt-throws.js new file mode 100644 index 0000000000..d7362cd778 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-type-abrupt-throws.js @@ -0,0 +1,46 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption type +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency", "weekday", "month", "quarter", "dayPeriod", "dateTimeField" », "language"). + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +var options = {}; +Object.defineProperty(options, 'type', { + get() { throw new Test262Error(); }, +}); + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-type-invalid-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-type-invalid-throws.js new file mode 100644 index 0000000000..bdbaecae82 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-type-invalid-throws.js @@ -0,0 +1,78 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from an invalid type option +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + 2. If value is not undefined, then + ... + c. If type is "string", then + i. Let value be ? ToString(value). + d. If values is not undefined, then + i. If values does not contain an element equal to value, throw a RangeError exception. + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', undefined); +}, 'undefined options'); + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', {}); +}, '{} options'); + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', {type: undefined}); +}, 'undefined type'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {type: 'lang'}); +}, 'type = lang'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {type: 'dayPeriod'}); +}, 'dayPeriod not supported yet'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {type: 'weekday'}); +}, 'weekday not supported yet'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {type: null}); +}, 'type = null'); + + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {type: ''}); +}, 'type = ""'); + +assert.throws(RangeError, () => { + new Intl.DisplayNames('en', {type: ['language', 'region', 'script', 'currency']}); +}, 'an array with the valid options is not necessarily valid'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-type-toString-abrupt-throws.js b/js/src/tests/test262/intl402/DisplayNames/options-type-toString-abrupt-throws.js new file mode 100644 index 0000000000..36f43563cf --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-type-toString-abrupt-throws.js @@ -0,0 +1,76 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Return abrupt completion from GetOption type +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency", "weekday", "month", "quarter", "dayPeriod", "dateTimeField" », "language"). + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames, Symbol] +locale: [en] +---*/ + +var options = { + type: { + toString() { + throw new Test262Error(); + } + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from toString'); + +options.type = { + toString: undefined, + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from valueOf'); + +options.type = { + [Symbol.toPrimitive]() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.DisplayNames('en', options); +}, 'from ToPrimitive'); + +options.type = Symbol(); + +assert.throws(TypeError, () => { + new Intl.DisplayNames('en', options); +}, 'symbol value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/options-type-valid.js b/js/src/tests/test262/intl402/DisplayNames/options-type-valid.js new file mode 100644 index 0000000000..54e884e880 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/options-type-valid.js @@ -0,0 +1,45 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Valid options for localeMatcher +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 4. Let options be ? ToObject(options). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.DisplayNames] +locale: [en] +---*/ + +// results for option values verified in the tests for resolvedOptions + +const types = [ + 'language', + 'region', + 'script', + 'currency' +]; + +types.forEach(type => { + const obj = new Intl.DisplayNames('en', { type }); + + assert(obj instanceof Intl.DisplayNames, `instanceof check - ${type}`); + assert.sameValue(Object.getPrototypeOf(obj), Intl.DisplayNames.prototype, `proto check - ${type}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prop-desc.js b/js/src/tests/test262/intl402/DisplayNames/prop-desc.js new file mode 100644 index 0000000000..337f52b0ab --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prop-desc.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Property descriptor of Intl.DisplayNames +info: | + 17 ECMAScript Standard Built-in Objects: + + 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. +includes: [propertyHelper.js] +features: [Intl.DisplayNames] +---*/ + +assert.sameValue(typeof Intl.DisplayNames, "function", "`typeof Intl.DisplayNames` is `'function'`"); + +verifyProperty(Intl, "DisplayNames", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/DisplayNames/proto-from-ctor-realm.js new file mode 100644 index 0000000000..cac9302e8f --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/proto-from-ctor-realm.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-Intl.DisplayNames +description: Default [[Prototype]] value derived from realm of the newTarget +info: | + Intl.DisplayNames ( locales , options ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let displayNames be ? OrdinaryCreateFromConstructor(NewTarget, "%DisplayNamesPrototype%", + « [[InitializedDisplayNames]], [[Locale]], [[Style]], [[Type]], [[Fallback]], [[Fields]] »). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, "prototype"). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.DisplayNames, cross-realm, Reflect] +---*/ + +var other = $262.createRealm().global; +var C = new other.Function(); +C.prototype = null; + +var o = Reflect.construct(Intl.DisplayNames, [undefined, {type: 'language'}], C); + +assert.sameValue(Object.getPrototypeOf(o), other.Intl.DisplayNames.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/proto.js b/js/src/tests/test262/intl402/DisplayNames/proto.js new file mode 100644 index 0000000000..7ef279226b --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/proto.js @@ -0,0 +1,15 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + The internal prototype of Intl.DisplayNames +features: [Intl.DisplayNames] +---*/ + +var proto = Object.getPrototypeOf(Intl.DisplayNames); + +assert.sameValue(proto, Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/Symbol.toStringTag.js b/js/src/tests/test262/intl402/DisplayNames/prototype/Symbol.toStringTag.js new file mode 100644 index 0000000000..de8db1a805 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/Symbol.toStringTag.js @@ -0,0 +1,23 @@ +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.DisplayNames.prototype-@@tostringtag +description: > + Property descriptor of DisplayNames.prototype[@@toStringTag] +info: | + The initial value of the @@toStringTag property is the string value "Intl.DisplayNames". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.DisplayNames, Symbol.toStringTag] +---*/ + +verifyProperty(Intl.DisplayNames.prototype, Symbol.toStringTag, { + value: "Intl.DisplayNames", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/browser.js b/js/src/tests/test262/intl402/DisplayNames/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/browser.js diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/prop-desc.js b/js/src/tests/test262/intl402/DisplayNames/prototype/prop-desc.js new file mode 100644 index 0000000000..1c35488ac3 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/prop-desc.js @@ -0,0 +1,22 @@ +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype +description: > + Property descriptor of Intl.DisplayNames.prototype +info: | + The value of Intl.DisplayNames.prototype is %DisplayNamesPrototype%. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +includes: [propertyHelper.js] +features: [Intl.DisplayNames] +---*/ + +verifyProperty(Intl.DisplayNames, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/default-option-values.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/default-option-values.js new file mode 100644 index 0000000000..96475e2ded --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/default-option-values.js @@ -0,0 +1,82 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Default values for each option +info: | + Intl.DisplayNames.prototype.resolvedOptions () + + 1. Let pr be the this value. + 2. If Type(pr) is not Object or pr does not have an [[InitializedDisplayNames]] internal slot, + throw a TypeError exception. + 3. Let options be ! ObjectCreate(%ObjectPrototype%). + 4. For each row of Table 6, except the header row, in table order, do + a. Let p be the Property value of the current row. + b. Let v be the value of pr's internal slot whose name is the Internal Slot value of the current row. + c. If v is not undefined, then + i. Perform ! CreateDataPropertyOrThrow(options, p, v). + 6. Return options. + + Table 6: Resolved Options of DisplayNames Instances + + [[Locale]]: "locale" + [[Style]]: "style" + [[Type]]: "type" + [[Fallback]]: "fallback" + + Intl.DisplayNames ( locales , options ) + + ... + 7. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 9. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, + %DisplayNames%.[[RelevantExtensionKeys]]). + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + 17. Set displayNames.[[Locale]] to the value of r.[[Locale]]. + ... + + CreateDataProperty ( O, P, V ) + + ... + 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, + [[Configurable]]: true }. + ... +locale: [en-US] +features: [Intl.DisplayNames] +includes: [propertyHelper.js] +---*/ + +var dn = new Intl.DisplayNames('en-US', {type: 'language'}); + +var options = dn.resolvedOptions(); + +verifyProperty(options, 'style', { + value: 'long', + writable: true, + enumerable: true, + configurable: true +}); + +verifyProperty(options, 'type', { + value: 'language', + writable: true, + enumerable: true, + configurable: true +}); + +verifyProperty(options, 'fallback', { + value: 'code', + writable: true, + enumerable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..402df82db0 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Intl.DisplayNames.prototype.resolvedOptions.length is 0. +info: | + ECMAScript Standard Built-in Objects: + + 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 }. +includes: [propertyHelper.js] +features: [Intl.DisplayNames] +---*/ + +verifyProperty(Intl.DisplayNames.prototype.resolvedOptions, "length", { + value: 0, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..91f54d44cc --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/name.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Intl.DisplayNames.prototype.resolvedOptions.name is "resolvedOptions". +info: | + 17 ECMAScript Standard Built-in Objects: + + 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, the name property of a built-in Function object, + if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.DisplayNames] +---*/ + +verifyProperty(Intl.DisplayNames.prototype.resolvedOptions, "name", { + value: "resolvedOptions", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-fallback.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-fallback.js new file mode 100644 index 0000000000..75215ab8e6 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-fallback.js @@ -0,0 +1,86 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Values for the fallback option +info: | + Intl.DisplayNames.prototype.resolvedOptions () + + 1. Let pr be the this value. + 2. If Type(pr) is not Object or pr does not have an [[InitializedDisplayNames]] internal slot, + throw a TypeError exception. + 3. Let options be ! ObjectCreate(%ObjectPrototype%). + 4. For each row of Table 6, except the header row, in table order, do + a. Let p be the Property value of the current row. + b. Let v be the value of pr's internal slot whose name is the Internal Slot value of the current row. + c. If v is not undefined, then + i. Perform ! CreateDataPropertyOrThrow(options, p, v). + 6. Return options. + + Table 6: Resolved Options of DisplayNames Instances + + [[Locale]]: "locale" + [[Style]]: "style" + [[Type]]: "type" + [[Fallback]]: "fallback" + + Intl.DisplayNames ( locales , options ) + + ... + 10. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, + %DisplayNames%.[[RelevantExtensionKeys]]). + 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + 17. Set displayNames.[[Locale]] to the value of r.[[Locale]]. + ... + + CreateDataProperty ( O, P, V ) + + ... + 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, + [[Configurable]]: true }. + ... +locale: [en-US] +features: [Intl.DisplayNames] +includes: [propertyHelper.js] +---*/ + +const fallbacks = ['code', 'none']; +const types = ['language', 'region', 'script', 'currency']; + +types.forEach(type => { + fallbacks.forEach(fallback => { + const dn = new Intl.DisplayNames('en-US', { fallback, type }); + const options = dn.resolvedOptions(); + + verifyProperty(options, 'fallback', { + value: fallback, + writable: true, + enumerable: true, + configurable: true + }); + + verifyProperty(options, 'type', { + value: type, + writable: true, + enumerable: true, + configurable: true + }); + + verifyProperty(options, 'style', { + value: 'long', + writable: true, + enumerable: true, + configurable: true + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-style.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-style.js new file mode 100644 index 0000000000..364e72e7fe --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-style.js @@ -0,0 +1,88 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Values for the style option +info: | + Intl.DisplayNames.prototype.resolvedOptions () + + 1. Let pr be the this value. + 2. If Type(pr) is not Object or pr does not have an [[InitializedDisplayNames]] internal slot, + throw a TypeError exception. + 3. Let options be ! ObjectCreate(%ObjectPrototype%). + 4. For each row of Table 6, except the header row, in table order, do + a. Let p be the Property value of the current row. + b. Let v be the value of pr's internal slot whose name is the Internal Slot value of the current row. + c. If v is not undefined, then + i. Perform ! CreateDataPropertyOrThrow(options, p, v). + 6. Return options. + + Table 6: Resolved Options of DisplayNames Instances + + [[Locale]]: "locale" + [[Style]]: "style" + [[Type]]: "type" + [[Fallback]]: "fallback" + + Intl.DisplayNames ( locales , options ) + + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 10. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, + %DisplayNames%.[[RelevantExtensionKeys]]). + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + 17. Set displayNames.[[Locale]] to the value of r.[[Locale]]. + ... + + CreateDataProperty ( O, P, V ) + + ... + 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, + [[Configurable]]: true }. + ... +locale: [en-US] +features: [Intl.DisplayNames] +includes: [propertyHelper.js] +---*/ + +const styles = ['narrow', 'short', 'long']; +const types = ['language', 'region', 'script', 'currency']; + +types.forEach(type => { + styles.forEach(style => { + const dn = new Intl.DisplayNames('en-US', { style, type }); + const options = dn.resolvedOptions(); + + verifyProperty(options, 'style', { + value: style, + writable: true, + enumerable: true, + configurable: true + }); + + verifyProperty(options, 'type', { + value: type, + writable: true, + enumerable: true, + configurable: true + }); + + verifyProperty(options, 'fallback', { + value: 'code', + writable: true, + enumerable: true, + configurable: true + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-type.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-type.js new file mode 100644 index 0000000000..104d59b968 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/option-type.js @@ -0,0 +1,85 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Values for the type option +info: | + Intl.DisplayNames.prototype.resolvedOptions () + + 1. Let pr be the this value. + 2. If Type(pr) is not Object or pr does not have an [[InitializedDisplayNames]] internal slot, + throw a TypeError exception. + 3. Let options be ! ObjectCreate(%ObjectPrototype%). + 4. For each row of Table 6, except the header row, in table order, do + a. Let p be the Property value of the current row. + b. Let v be the value of pr's internal slot whose name is the Internal Slot value of the current row. + c. If v is not undefined, then + i. Perform ! CreateDataPropertyOrThrow(options, p, v). + 6. Return options. + + Table 6: Resolved Options of DisplayNames Instances + + [[Locale]]: "locale" + [[Style]]: "style" + [[Type]]: "type" + [[Fallback]]: "fallback" + + Intl.DisplayNames ([ locales [ , options ]]) + + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 10. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, + %DisplayNames%.[[RelevantExtensionKeys]]). + 11. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 13. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency"», + "language"). + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + 17. Set displayNames.[[Locale]] to the value of r.[[Locale]]. + ... + + CreateDataProperty ( O, P, V ) + + ... + 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, + [[Configurable]]: true }. + ... +locale: [en-US] +features: [Intl.DisplayNames] +includes: [propertyHelper.js] +---*/ + +var types = ['language', 'region', 'script', 'currency']; + +types.forEach(type => { + var dn = new Intl.DisplayNames('en-US', { type }); + var options = dn.resolvedOptions(); + + verifyProperty(options, 'type', { + value: type, + writable: true, + enumerable: true, + configurable: true + }); + + verifyProperty(options, 'fallback', { + value: 'code', + writable: true, + enumerable: true, + configurable: true + }); + + verifyProperty(options, 'style', { + value: 'long', + writable: true, + enumerable: true, + configurable: true + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..1766f5a5ce --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,30 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Property descriptor of Intl.DisplayNames.prototype.resolvedOptions +info: | + 17 ECMAScript Standard Built-in Objects: + + 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. +includes: [propertyHelper.js] +features: [Intl.DisplayNames] +---*/ + +assert.sameValue( + typeof Intl.DisplayNames.prototype.resolvedOptions, + "function", + "`typeof Intl.DisplayNames.prototype.resolvedOptions` is `'function'`" +); + +verifyProperty(Intl.DisplayNames.prototype, "resolvedOptions", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/return-object.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/return-object.js new file mode 100644 index 0000000000..b6048675ca --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/return-object.js @@ -0,0 +1,99 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Returns a new ordinary object on each call, with data properties containing values from internals +info: | + Intl.DisplayNames.prototype.resolvedOptions () + + 1. Let pr be the this value. + 2. If Type(pr) is not Object or pr does not have an [[InitializedDisplayNames]] internal slot, + throw a TypeError exception. + 3. Let options be ! ObjectCreate(%ObjectPrototype%). + 4. For each row of Table 6, except the header row, in table order, do + a. Let p be the Property value of the current row. + b. Let v be the value of pr's internal slot whose name is the Internal Slot value of the current row. + c. If v is not undefined, then + i. Perform ! CreateDataPropertyOrThrow(options, p, v). + 6. Return options. + + Table 6: Resolved Options of DisplayNames Instances + + [[Locale]]: "locale" + [[Style]]: "style" + [[Type]]: "type" + [[Fallback]]: "fallback" + + Intl.DisplayNames ( locales , options ) + + ... + 7. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + 9. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]], requestedLocales, opt, + %DisplayNames%.[[RelevantExtensionKeys]]). + 10. Let style be ? GetOption(options, "style", "string", « "narrow", "short", "long" », "long"). + ... + 12. Let type be ? GetOption(options, "type", "string", « "language", "region", "script", "currency" », undefined). + 13. If type is undefined, throw a TypeError exception. + ... + 15. Let fallback be ? GetOption(options, "fallback", "string", « "code", "none" », "code"). + ... + 17. Set displayNames.[[Locale]] to the value of r.[[Locale]]. + ... + + CreateDataProperty ( O, P, V ) + + ... + 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, + [[Configurable]]: true }. + ... +locale: [en-US] +features: [Intl.DisplayNames, Reflect] +includes: [propertyHelper.js, compareArray.js] +---*/ + +const dn = new Intl.DisplayNames('en-US', {type: 'language'}); + +const options = dn.resolvedOptions(); +const other = dn.resolvedOptions(); + +assert.notSameValue(options, other, 'each call returns a new object'); + +assert.sameValue(Object.getPrototypeOf(options), Object.prototype, 'ordinary object #1'); +assert.sameValue(Object.getPrototypeOf(other), Object.prototype, 'ordinary object #2'); + +assert.compareArray( + Reflect.ownKeys(options), + ['locale', 'style', 'type', 'fallback'], + 'all the data properties set to this object, in order of creation' +); + +verifyProperty(options, 'locale', { + value: 'en-US', + writable: true, + enumerable: true, + configurable: true +}); + +const explicit = new Intl.DisplayNames( + 'en', { localeMatcher: 'lookup', type: 'language' }).resolvedOptions(); + +assert.sameValue( + explicit.hasOwnProperty('localeMatcher'), + false, + 'the localeMatcher option is not set, option was explicitly set' +); + +const extra = new Intl.DisplayNames( + 'en', { chaos: 'yes', random: 'sure', '0': 42, type: 'language' }).resolvedOptions(); + +assert.compareArray( + Reflect.ownKeys(extra), + ['locale', 'style', 'type', 'fallback'], + 'extra properties are not reflected in the resolvedOptions' +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/shell.js diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/this-not-object-throws.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/this-not-object-throws.js new file mode 100644 index 0000000000..42cac5976e --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/this-not-object-throws.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Throws a TypeError if this is not Object. +info: | + Intl.DisplayNames.prototype.resolvedOptions () + + 1. Let pr be the this value. + 2. If Type(pr) is not Object or pr does not have an [[InitializedDisplayNames]] internal slot, + throw a TypeError exception. + ... +features: [Intl.DisplayNames, Symbol] +---*/ + +var resolvedOptions = Intl.DisplayNames.prototype.resolvedOptions; + +assert.throws(TypeError, function() { + resolvedOptions(); +}, 'direct call'); + +assert.throws(TypeError, function() { + resolvedOptions.call('en'); +}, 'string'); + +assert.throws(TypeError, function() { + resolvedOptions.call(1); +}, 'number'); + +assert.throws(TypeError, function() { + resolvedOptions.call(null); +}, 'null'); + +assert.throws(TypeError, function() { + resolvedOptions.call(true); +}, 'true'); + +assert.throws(TypeError, function() { + resolvedOptions.call(false); +}, 'false'); + +var symbol = Symbol(); +assert.throws(TypeError, function() { + resolvedOptions.call(symbol); +}, 'symbol'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/this-object-lacks-internal-throws.js b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/this-object-lacks-internal-throws.js new file mode 100644 index 0000000000..9ad4c1517b --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/resolvedOptions/this-object-lacks-internal-throws.js @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames.prototype.resolvedOptions +description: > + Throws a TypeError if this does not have an [[InitializedDisplayNames]] internal slot. +info: | + Intl.DisplayNames.prototype.resolvedOptions () + + 1. Let pr be the this value. + 2. If Type(pr) is not Object or pr does not have an [[InitializedDisplayNames]] internal slot, + throw a TypeError exception. + ... +features: [Intl.DisplayNames] +---*/ + +var resolvedOptions = Intl.DisplayNames.prototype.resolvedOptions; + +assert.throws(TypeError, function() { + Intl.DisplayNames.prototype.resolvedOptions(); +}, 'Intl.DisplayNames.prototype does not have the internal slot'); + +assert.throws(TypeError, function() { + resolvedOptions.call({}); +}, 'ordinary object'); + +assert.throws(TypeError, function() { + resolvedOptions.call(Intl.DisplayNames); +}, 'Intl.DisplayNames does not have the internal slot'); + +assert.throws(TypeError, function() { + resolvedOptions.call(Intl); +}, 'Intl does not have the internal slot'); + +// Not DisplayNames!!! +var dtf = new Intl.DateTimeFormat(); + +assert.throws(TypeError, function() { + resolvedOptions.call(dtf); +}, 'resolvedOptions cannot be used with instances from different Intl ctors'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/DisplayNames/prototype/shell.js b/js/src/tests/test262/intl402/DisplayNames/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/prototype/shell.js diff --git a/js/src/tests/test262/intl402/DisplayNames/shell.js b/js/src/tests/test262/intl402/DisplayNames/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/shell.js diff --git a/js/src/tests/test262/intl402/DisplayNames/undefined-newtarget-throws.js b/js/src/tests/test262/intl402/DisplayNames/undefined-newtarget-throws.js new file mode 100644 index 0000000000..3b28c14486 --- /dev/null +++ b/js/src/tests/test262/intl402/DisplayNames/undefined-newtarget-throws.js @@ -0,0 +1,28 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.DisplayNames +description: > + Throws a TypeError if Intl.DisplayNames is called as a function. +info: | + Intl.DisplayNames ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + ... +features: [Intl.DisplayNames] +---*/ + +assert.throws(TypeError, function() { + Intl.DisplayNames(); +}); + +assert.throws(TypeError, function() { + Intl.DisplayNames('en'); +}); + +assert.throws(TypeError, function() { + Intl.DisplayNames(['en']); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/browser.js b/js/src/tests/test262/intl402/Intl/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/browser.js diff --git a/js/src/tests/test262/intl402/Intl/builtin.js b/js/src/tests/test262/intl402/Intl/builtin.js new file mode 100644 index 0000000000..7641f06945 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/builtin.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: intl-object +description: > + Tests that Intl meets the requirements for built-in objects + defined by the introduction of chapter 17 of the ECMAScript + Language Specification. +author: Norbert Lindenberg +---*/ + +assert(Object.isExtensible(Intl), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl), Object.prototype, + "The [[Prototype]] of Intl is %ObjectPrototype%."); + +assert.sameValue(this.Intl, Intl, + "%Intl% is accessible as a property of the global object."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/Locale-object.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/Locale-object.js new file mode 100644 index 0000000000..49ed15f8cc --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/Locale-object.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests for Locale objects in the argument to getCanonicalLocales +info: | + CanonicalizeLocaleList ( locales ) + 7. c. iii. If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then + 1. Let tag be kValue.[[Locale]]. +includes: [compareArray.js] +features: [Intl.Locale] +---*/ + +assert.compareArray(Intl.getCanonicalLocales([ + "fr-CA", + new Intl.Locale("en-gb-oxendict"), + "de", + new Intl.Locale("jp", { "calendar": "gregory" }), + "zh", + new Intl.Locale("fr-CA"), +]), [ + "fr-CA", + "en-GB-oxendict", + "de", + "jp-u-ca-gregory", + "zh", +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/browser.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/browser.js diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/canonicalized-tags.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/canonicalized-tags.js new file mode 100644 index 0000000000..f80e448086 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/canonicalized-tags.js @@ -0,0 +1,66 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Call Intl.getCanonicalLocales function with valid language tags. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + a. Let Pk be ToString(k). + b. Let kPresent be ? HasProperty(O, Pk). + c. If kPresent is true, then + i. Let kValue be ? Get(O, Pk). + ... + iii. Let tag be ? ToString(kValue). + ... + v. Let canonicalizedTag be CanonicalizeLanguageTag(tag). + vi. If canonicalizedTag is not an element of seen, append canonicalizedTag as the last element of seen. + ... +includes: [testIntl.js] +---*/ + +var canonicalizedTags = { + "de": "de", + "DE-de": "de-DE", + "de-DE": "de-DE", + "cmn": "zh", + "CMN-hANS": "zh-Hans", + "cmn-hans-cn": "zh-Hans-CN", + "es-419": "es-419", + "es-419-u-nu-latn": "es-419-u-nu-latn", + "cmn-hans-cn-u-ca-t-ca-x-t-u": "zh-Hans-CN-t-ca-u-ca-x-t-u", + "de-gregory-u-ca-gregory": "de-gregory-u-ca-gregory", + "sgn-GR": "gss", + "ji": "yi", + "de-DD": "de-DE", + "in": "id", + "sr-cyrl-ekavsk": "sr-Cyrl-ekavsk", + "en-ca-newfound": "en-CA-newfound", + "sl-rozaj-biske-1994": "sl-1994-biske-rozaj", + "da-u-attr": "da-u-attr", + "da-u-attr-co-search": "da-u-attr-co-search", +}; + +// make sure the data above is correct +Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) { + var canonicalizedTag = canonicalizedTags[tag]; + assert( + isCanonicalizedStructurallyValidLanguageTag(canonicalizedTag), + "Test data \"" + canonicalizedTag + "\" is not canonicalized and structurally valid language tag." + ); +}); + +Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) { + var canonicalLocales = Intl.getCanonicalLocales(tag); + assert.sameValue(canonicalLocales.length, 1); + assert.sameValue(canonicalLocales[0], canonicalizedTags[tag]); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/canonicalized-unicode-ext-seq.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/canonicalized-unicode-ext-seq.js new file mode 100644 index 0000000000..07edfac0e7 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/canonicalized-unicode-ext-seq.js @@ -0,0 +1,41 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Implementations are allowed to canonicalize extension subtag sequences. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. Let canonicalizedTag be CanonicalizeLanguageTag(tag). + ... + + 6.2.3 CanonicalizeLanguageTag (locale) + The specifications for extensions to BCP 47 language tags, such as + RFC 6067, may include canonicalization rules for the extension subtag + sequences they define that go beyond the canonicalization rules of + RFC 5646 section 4.5. Implementations are allowed, but not required, + to apply these additional rules. +---*/ + +var locale = "it-u-nu-latn-ca-gregory"; + +// RFC 6067: The canonical order of keywords is in US-ASCII order by key. +var sorted = "it-u-ca-gregory-nu-latn"; + +var canonicalLocales = Intl.getCanonicalLocales(locale); +assert.sameValue(canonicalLocales.length, 1); + +var canonicalLocale = canonicalLocales[0]; +assert((canonicalLocale === locale) || (canonicalLocale === sorted)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/complex-language-subtag-replacement.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/complex-language-subtag-replacement.js new file mode 100644 index 0000000000..1401971928 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/complex-language-subtag-replacement.js @@ -0,0 +1,60 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Assert non-simple language subtag replacements work as expected. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + + - Replace aliases in the unicode_language_id and tlang (if any) using the following process: + - If the language subtag matches the type attribute of a languageAlias element in + Supplemental Data, replace the language subtag with the replacement value. + 1. If there are additional subtags in the replacement value, add them to the result, + but only if there is no corresponding subtag already in the tag. + +includes: [testIntl.js] +---*/ + +// CLDR contains language mappings where in addition to the language subtag also +// the script or region subtag is modified, unless they're already present. + +const testData = { + // "sh" adds "Latn", unless a script subtag is already present. + // <languageAlias type="sh" replacement="sr_Latn" reason="legacy"/> + "sh": "sr-Latn", + "sh-Cyrl": "sr-Cyrl", + + // "cnr" adds "ME", unless a region subtag is already present. + // <languageAlias type="cnr" replacement="sr_ME" reason="legacy"/> + "cnr": "sr-ME", + "cnr-BA": "sr-BA", +}; + +for (let [tag, canonical] of Object.entries(testData)) { + // Make sure the test data is correct. + assert( + isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonicalized and structurally valid language tag." + ); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/complex-region-subtag-replacement.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/complex-region-subtag-replacement.js new file mode 100644 index 0000000000..f8a316d6f2 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/complex-region-subtag-replacement.js @@ -0,0 +1,110 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Assert non-simple region subtag replacements work as expected. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + + - Replace aliases in the unicode_language_id and tlang (if any) using the following process: + - If the region subtag matches the type attribute of a territoryAlias element in + Supplemental Data, replace the language subtag with the replacement value, as follows: + 1. If there is a single territory in the replacement, use it. + 2. If there are multiple territories: + 1. Look up the most likely territory for the base language code (and script, if there is one). + 2. If that likely territory is in the list, use it. + 3. Otherwise, use the first territory in the list. + +includes: [testIntl.js] +---*/ + +// CLDR contains region mappings where the replacement region depends on the +// likely subtags from the language and script subtags. + +const testData = { + // For example, the breakup of the Soviet Union ("SU") means that the region of + // the Soviet Union ("SU") is replaced by Russia ("RU"), Armenia ("AM"), or + // many others -- depending on the specified (or merely likely) language and + // script subtags: + // + // <territoryAlias type="SU" replacement="RU AM AZ BY EE GE KZ KG LV LT MD TJ TM UA UZ" reason="deprecated"/> + // <territoryAlias type="810" replacement="RU AM AZ BY EE GE KZ KG LV LT MD TJ TM UA UZ" reason="overlong"/> + "ru-SU": "ru-RU", + "ru-810": "ru-RU", + "en-SU": "en-RU", + "en-810": "en-RU", + "und-SU": "und-RU", + "und-810": "und-RU", + "und-Latn-SU": "und-Latn-RU", + "und-Latn-810": "und-Latn-RU", + + // Armenia can be the preferred region when the language is "hy" (Armenian) or + // the script is "Armn" (Armenian). + // + // <likelySubtag from="hy" to="hy_Armn_AM"/> + // <likelySubtag from="und_Armn" to="hy_Armn_AM"/> + "hy-SU": "hy-AM", + "hy-810": "hy-AM", + "und-Armn-SU": "und-Armn-AM", + "und-Armn-810": "und-Armn-AM", + + // <territoryAlias type="CS" replacement="RS ME" reason="deprecated"/> + // + // The following likely-subtags entries contain "RS" and "ME": + // + // <likelySubtag from="sr" to="sr_Cyrl_RS"/> + // <likelySubtag from="sr_ME" to="sr_Latn_ME"/> + // <likelySubtag from="und_RS" to="sr_Cyrl_RS"/> + // <likelySubtag from="und_ME" to="sr_Latn_ME"/> + // + // In this case there is no language/script combination (without a region + // subtag) where "ME" is ever chosen, so the replacement is always "RS". + "sr-CS": "sr-RS", + "sr-Latn-CS": "sr-Latn-RS", + "sr-Cyrl-CS": "sr-Cyrl-RS", + + // The existing region in the source locale identifier is ignored when selecting + // the likely replacement region. For example take "az-NT", which is Azerbaijani + // spoken in the Neutral Zone. The replacement region for "NT" is either + // "SA" (Saudi-Arabia) or "IQ" (Iraq), and there is also a likely subtags entry + // for "az-IQ". But when only looking at the language subtag in "az-NT", "az" is + // always resolved to "az-Latn-AZ", and because "AZ" is not in the list ["SA", + // "IQ"], the final replacement region is the default for "NT", namely "SA". + // That means "az-NT" will be canonicalised to "az-SA" and not "az-IQ", even + // though the latter may be a more sensible candidate based on the actual usage + // of the target locales. + // + // <territoryAlias type="NT" replacement="SA IQ" reason="deprecated"/> + // <likelySubtag from="az_IQ" to="az_Arab_IQ"/> + // <likelySubtag from="az" to="az_Latn_AZ"/> + "az-NT": "az-SA", +}; + +for (let [tag, canonical] of Object.entries(testData)) { + // Make sure the test data is correct. + assert( + isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonicalized and structurally valid language tag." + ); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/descriptor.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/descriptor.js new file mode 100644 index 0000000000..4251540049 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/descriptor.js @@ -0,0 +1,24 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Intl.getCanonicalLocales property attributes. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + + 17 ECMAScript Standard Built-in Objects: + 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. +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl, 'getCanonicalLocales', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/duplicates.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/duplicates.js new file mode 100644 index 0000000000..3f0b9e93fc --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/duplicates.js @@ -0,0 +1,21 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests the getCanonicalLocales function for duplicate locales scenario. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [compareArray.js] +---*/ + +assert(compareArray( + Intl.getCanonicalLocales( + ['ab-cd', 'ff', 'de-rt', 'ab-Cd']), ['ab-CD', 'ff', 'de-RT'])); + +var locales = Intl.getCanonicalLocales(['en-US', 'en-US']); +assert(compareArray(locales, ['en-US']), 'en-US'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/elements-not-reordered.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/elements-not-reordered.js new file mode 100644 index 0000000000..67a1239d62 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/elements-not-reordered.js @@ -0,0 +1,29 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Language tags are not reordered. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + vi. If canonicalizedTag is not an element of seen, append canonicalizedTag as the last element of seen. + ... +---*/ + +var canonicalLocales = Intl.getCanonicalLocales(["zu", "af"]); + +assert.sameValue(canonicalLocales.length, 2); +assert.sameValue(canonicalLocales[0], "zu"); +assert.sameValue(canonicalLocales[1], "af"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/error-cases.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/error-cases.js new file mode 100644 index 0000000000..b0c4b8a9a8 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/error-cases.js @@ -0,0 +1,48 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests the getCanonicalLocales function for error tags. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +features: [Symbol] +---*/ + +var rangeErrorCases = + [ + "en-us-", + "-en-us", + "en-us-en-us", + "--", + "-", + "", + "-e-" + ]; + +rangeErrorCases.forEach(function(re) { + assert.throws(RangeError, function() { + Intl.getCanonicalLocales(re); + }); +}); + +var typeErrorCases = + [ + null, + [null], + [undefined], + [true], + [NaN], + [2], + [Symbol('foo')] + ]; + +typeErrorCases.forEach(function(te) { + assert.throws(TypeError, function() { + Intl.getCanonicalLocales(te); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/get-locale.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/get-locale.js new file mode 100644 index 0000000000..99032e02c9 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/get-locale.js @@ -0,0 +1,27 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Test Intl.getCanonicalLocales for step 7.c.i. +info: | + 9.2.1 CanonicalizeLocaleList (locales) + 7. Repeat, while k < len. + c. If kPresent is true, then + i. Let kValue be ? Get(O, Pk). +---*/ + +var locales = { + '0': 'en-US', + length: 2 +}; + +Object.defineProperty(locales, "1", { + get: function() { throw new Test262Error() } +}); + +assert.throws(Test262Error, function() { + Intl.getCanonicalLocales(locales); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/getCanonicalLocales.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/getCanonicalLocales.js new file mode 100644 index 0000000000..ae7e8bff11 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/getCanonicalLocales.js @@ -0,0 +1,24 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Property type and descriptor. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [propertyHelper.js] +---*/ + +assert.sameValue( + typeof Intl.getCanonicalLocales, + 'function', + '`typeof Intl.getCanonicalLocales` is `function`' +); + +verifyNotEnumerable(Intl, 'getCanonicalLocales'); +verifyWritable(Intl, 'getCanonicalLocales'); +verifyConfigurable(Intl, 'getCanonicalLocales'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/grandfathered.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/grandfathered.js new file mode 100644 index 0000000000..4a26d4d2e0 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/grandfathered.js @@ -0,0 +1,35 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +// Split from intl402/Locale/likely-subtags-grandfathered.js +/*--- +esid: sec-intl.getcanonicallocales +description: > + Verifies canonicalization of specific tags. +---*/ + + +const regularGrandfathered = [ + { + tag: "art-lojban", + canonical: "jbo", + }, + { + tag: "zh-guoyu", + canonical: "zh", + }, + { + tag: "zh-hakka", + canonical: "hak", + }, + { + tag: "zh-xiang", + canonical: "hsn", + }, +]; + +for (const {tag, canonical} of regularGrandfathered) { + assert.sameValue(Intl.getCanonicalLocales(tag)[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/has-property.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/has-property.js new file mode 100644 index 0000000000..2c77014cec --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/has-property.js @@ -0,0 +1,32 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Test Intl.getCanonicalLocales.name for step 7.b. +info: | + 9.2.1 CanonicalizeLocaleList (locales) + 7. Repeat, while k < len. + b. Let kPresent be HasProperty(O, Pk). +features: [Proxy] +---*/ + +var locales = { + '0': 'en-US', + '1': 'pt-BR', + length: 2 +}; + +var p = new Proxy(locales, { + has: function(_, prop) { + if (prop === '0') { + throw new Test262Error(); + } + } +}); + +assert.throws(Test262Error, function() { + Intl.getCanonicalLocales(p); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/invalid-tags.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/invalid-tags.js new file mode 100644 index 0000000000..22949e8370 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/invalid-tags.js @@ -0,0 +1,32 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Throws a RangeError if the language tag is invalid. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + ... + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + iv. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + ... +includes: [testIntl.js] +---*/ + +var invalidLanguageTags = getInvalidLanguageTags(); +for (var i = 0; i < invalidLanguageTags.length; ++i) { + var invalidTag = invalidLanguageTags[i]; + assert.throws(RangeError, function() { + Intl.getCanonicalLocales(invalidTag) + }, "Language tag: " + invalidTag); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/length.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/length.js new file mode 100644 index 0000000000..6291926549 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/length.js @@ -0,0 +1,20 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Intl.getCanonicalLocales.length. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.getCanonicalLocales.length, 1); + +verifyNotEnumerable(Intl.getCanonicalLocales, "length"); +verifyNotWritable(Intl.getCanonicalLocales, "length"); +verifyConfigurable(Intl.getCanonicalLocales, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/locales-is-not-a-string.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/locales-is-not-a-string.js new file mode 100644 index 0000000000..bff120d275 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/locales-is-not-a-string.js @@ -0,0 +1,33 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests for scenario where locales is not a string +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [compareArray.js] +features: [Symbol] +---*/ + +var gCL = Intl.getCanonicalLocales; + +function assertArray(l, r) { + assert(compareArray(l, r), r); +} + +assertArray(gCL(), []); +assertArray(gCL(undefined), []); +assertArray(gCL(false), []); +assertArray(gCL(true), []); +assertArray(gCL(Symbol("foo")), []); +assertArray(gCL(NaN), []); +assertArray(gCL(1), []); + +Number.prototype[0] = "en-US"; +Number.prototype.length = 1; +assertArray(gCL(NaN), ["en-US"]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/main.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/main.js new file mode 100644 index 0000000000..6e27ca6a5e --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/main.js @@ -0,0 +1,34 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests for existance and behavior of Intl.getCanonicalLocales +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [compareArray.js] +---*/ + +var gCL = Intl.getCanonicalLocales; + +function assertArray(l, r) { + assert(compareArray(l, r), r); +} + +assertArray(gCL(), []); + +assertArray(gCL('ab-cd'), ['ab-CD']); + +assertArray(gCL(['ab-cd']), ['ab-CD']); + +assertArray(gCL(['ab-cd', 'FF']), ['ab-CD', 'ff']); + +assertArray(gCL({'a': 0}), []); + +assertArray(gCL({}), []); + +assertArray(gCL(['th-th-u-nu-thai']), ['th-TH-u-nu-thai']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/name.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/name.js new file mode 100644 index 0000000000..23034b2764 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/name.js @@ -0,0 +1,22 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Intl.getCanonicalLocales.name value and descriptor. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.getCanonicalLocales.name, 'getCanonicalLocales', + 'The value of `Intl.getCanonicalLocales.name` is `"getCanonicalLocales"`' +); + +verifyNotEnumerable(Intl.getCanonicalLocales, 'name'); +verifyNotWritable(Intl.getCanonicalLocales, 'name'); +verifyConfigurable(Intl.getCanonicalLocales, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/non-iana-canon.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/non-iana-canon.js new file mode 100644 index 0000000000..5afd34591a --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/non-iana-canon.js @@ -0,0 +1,81 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +// Slip from intl402/Locale/constructor-non-iana-canon.js +/*--- +esid: sec-intl.getcanonicallocales +description: > + Verifies canonicalization, of specific tags. +info: | + ApplyOptionsToTag( tag, options ) + 10. Return CanonicalizeLanguageTag(tag). +---*/ + +// Test some language tags where we know that either CLDR or ICU produce +// different results compared to the canonicalization specified in RFC 5646. +var testData = [ + { + tag: "mo", + canonical: "ro", + }, + { + tag: "es-ES-preeuro", + }, + { + tag: "uz-UZ-cyrillic", + }, + { + tag: "posix", + }, + { + tag: "hi-direct", + }, + { + tag: "zh-pinyin", + }, + { + tag: "zh-stroke", + }, + { + tag: "aar-x-private", + // "aar" should be canonicalized into "aa" because "aar" matches the type attribute of + // a languageAlias element in + // https://www.unicode.org/repos/cldr/trunk/common/supplemental/supplementalMetadata.xml + canonical: "aa-x-private", + }, + { + tag: "heb-x-private", + // "heb" should be canonicalized into "he" because "heb" matches the type attribute of + // a languageAlias element in + // https://www.unicode.org/repos/cldr/trunk/common/supplemental/supplementalMetadata.xml + canonical: "he-x-private", + }, + { + tag: "de-u-kf", + }, + { + tag: "ces", + // "ces" should be canonicalized into "cs" because "ces" matches the type attribute of + // a languageAlias element in + // https://www.unicode.org/repos/cldr/trunk/common/supplemental/supplementalMetadata.xml + canonical: "cs", + }, + { + tag: "hy-arevela", + canonical: "hy", + }, + { + tag: "hy-arevmda", + canonical: "hyw", + }, +]; + +for (const {tag, canonical = tag} of testData) { + assert.sameValue( + Intl.getCanonicalLocales(tag)[0], + canonical, + 'The value of Intl.getCanonicalLocales(tag)[0] equals the value of `canonical`' + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-arg-length.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-arg-length.js new file mode 100644 index 0000000000..12d4e8c567 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-arg-length.js @@ -0,0 +1,91 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Test Intl.getCanonicalLocales for step 5. +info: | + 9.2.1 CanonicalizeLocaleList (locales) + 5. Let len be ? ToLength(? Get(O, "length")). +includes: [compareArray.js] +features: [Symbol] +---*/ + +var locales = { + '0': 'en-US', +}; + +Object.defineProperty(locales, "length", { + get: function() { throw new Test262Error() } +}); + +assert.throws(Test262Error, function() { + Intl.getCanonicalLocales(locales); +}, "should throw if locales.length throws"); + +var locales = { + '0': 'en-US', + '1': 'pt-BR', +}; + +Object.defineProperty(locales, "length", { + get: function() { return "1" } +}); + +assert(compareArray(Intl.getCanonicalLocales(locales), ['en-US']), + "should return one element if locales.length is '1'"); + +var locales = { + '0': 'en-US', + '1': 'pt-BR', +}; + +Object.defineProperty(locales, "length", { + get: function() { return 1.3 } +}); + +assert(compareArray(Intl.getCanonicalLocales(locales), ['en-US']), + "should return one element if locales.length is 1.3"); + +var locales = { + '0': 'en-US', + '1': 'pt-BR', +}; + +Object.defineProperty(locales, "length", { + get: function() { return Symbol("1.8") } +}); + +assert.throws(TypeError, function() { + Intl.getCanonicalLocales(locales); +}, "should throw if locales.length is a Symbol"); + +var locales = { + '0': 'en-US', + '1': 'pt-BR', +}; + +Object.defineProperty(locales, "length", { + get: function() { return -Infinity } +}); + +assert(compareArray(Intl.getCanonicalLocales(locales), []), + "should return empty array if locales.length is -Infinity"); + +var locales = { + length: -Math.pow(2, 32) + 1 +}; + +Object.defineProperty(locales, "0", { + get: function() { throw new Error("must not be gotten!"); } +}) + +assert(compareArray(Intl.getCanonicalLocales(locales), []), + "should return empty array if locales.length is a negative value"); + +var count = 0; +var locs = { get length() { if (count++ > 0) throw 42; return 0; } }; +var locales = Intl.getCanonicalLocales(locs); // shouldn't throw 42 +assert.sameValue(locales.length, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-push.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-push.js new file mode 100644 index 0000000000..c2e2938be1 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/overriden-push.js @@ -0,0 +1,21 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests the getCanonicalLocales function for overridden Array.push(). +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [compareArray.js] +---*/ + +Array.prototype.push = function() { throw 42; }; + +// must not throw 42, might if push is used +var arr = Intl.getCanonicalLocales(["en-US"]); + +assert(compareArray(arr, ["en-US"])); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/preferred-grandfathered.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/preferred-grandfathered.js new file mode 100644 index 0000000000..51a536bbfc --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/preferred-grandfathered.js @@ -0,0 +1,98 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Call Intl.getCanonicalLocales function with grandfathered language tags. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. Let canonicalizedTag be CanonicalizeLanguageTag(tag). + ... + + 6.2.3 CanonicalizeLanguageTag ( locale ) + The CanonicalizeLanguageTag abstract operation returns the canonical and case-regularized form + of the locale argument (which must be a String value that is a structurally valid Unicode + BCP 47 Locale Identifier as verified by the IsStructurallyValidLanguageTag abstract operation). + A conforming implementation shall take the steps specified in the “BCP 47 Language Tag to + Unicode BCP 47 Locale Identifier” algorithm, from Unicode Technical Standard #35 LDML + § 3.3.1 BCP 47 Language Tag Conversion. + +includes: [testIntl.js] +---*/ + +// Generated from http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry +// File-Date: 2017-08-15 + +var irregularGrandfathered = [ + "en-gb-oed", + "i-ami", + "i-bnn", + "i-default", + "i-enochian", + "i-hak", + "i-klingon", + "i-lux", + "i-mingo", + "i-navajo", + "i-pwn", + "i-tao", + "i-tay", + "i-tsu", + "sgn-be-fr", + "sgn-be-nl", + "sgn-ch-de", +]; + +var regularGrandfatheredNonUTS35 = [ + "no-bok", + "no-nyn", + "zh-min", + "zh-min-nan", +]; + +var regularGrandfatheredUTS35 = { + "art-lojban": "jbo", + "cel-gaulish": "xtg", + "zh-guoyu": "zh", + "zh-hakka": "hak", + "zh-xiang": "hsn", +}; + +// make sure the data above is correct +irregularGrandfathered.forEach(function (tag) { + assert.sameValue( + isCanonicalizedStructurallyValidLanguageTag(tag), false, + "Test data \"" + tag + "\" is not a structurally valid language tag." + ); +}); +regularGrandfatheredNonUTS35.forEach(function (tag) { + assert.sameValue( + isCanonicalizedStructurallyValidLanguageTag(tag), false, + "Test data \"" + tag + "\" is not a structurally valid language tag." + ); +}); +Object.getOwnPropertyNames(regularGrandfatheredUTS35).forEach(function (tag) { + var canonicalizedTag = regularGrandfatheredUTS35[tag]; + assert( + isCanonicalizedStructurallyValidLanguageTag(canonicalizedTag), + "Test data \"" + canonicalizedTag + "\" is a canonicalized and structurally valid language tag." + ); +}); + +Object.getOwnPropertyNames(regularGrandfatheredUTS35).forEach(function (tag) { + var canonicalLocales = Intl.getCanonicalLocales(tag); + assert.sameValue(canonicalLocales.length, 1); + assert.sameValue(canonicalLocales[0], regularGrandfatheredUTS35[tag]); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/preferred-variant.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/preferred-variant.js new file mode 100644 index 0000000000..e1d8f028cc --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/preferred-variant.js @@ -0,0 +1,60 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Call Intl.getCanonicalLocales function with grandfathered language tags. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. Let canonicalizedTag be CanonicalizeLanguageTag(tag). + ... + + 6.2.3 CanonicalizeLanguageTag ( locale ) + The CanonicalizeLanguageTag abstract operation returns the canonical and case-regularized + form of the locale argument (which must be a String value that is a structurally valid + BCP 47 language tag as verified by the IsStructurallyValidLanguageTag abstract operation). + A conforming implementation shall take the steps specified in RFC 5646 section 4.5, or + successor, to bring the language tag into canonical form, and to regularize the case of + the subtags. Furthermore, a conforming implementation shall not take the steps to bring + a language tag into "extlang form", nor shall it reorder variant subtags. + + The specifications for extensions to BCP 47 language tags, such as RFC 6067, may include + canonicalization rules for the extension subtag sequences they define that go beyond the + canonicalization rules of RFC 5646 section 4.5. Implementations are allowed, but not + required, to apply these additional rules. + +includes: [testIntl.js] +---*/ + +// https://github.com/unicode-org/cldr/blame/master/common/supplemental/supplementalMetadata.xml#L531 +// http://unicode.org/reports/tr35/#LocaleId_Canonicalization +var canonicalizedTags = { + "ja-latn-hepburn-heploc": "ja-Latn-alalc97", +}; + +// make sure the data above is correct +Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) { + var canonicalizedTag = canonicalizedTags[tag]; + assert( + isCanonicalizedStructurallyValidLanguageTag(canonicalizedTag), + "Test data \"" + canonicalizedTag + "\" is not canonicalized and structurally valid language tag." + ); +}); + +Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) { + var canonicalLocales = Intl.getCanonicalLocales(tag); + assert.sameValue(canonicalLocales.length, 1); + assert.sameValue(canonicalLocales[0], canonicalizedTags[tag]); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/returned-object-is-an-array.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/returned-object-is-an-array.js new file mode 100644 index 0000000000..193393484d --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/returned-object-is-an-array.js @@ -0,0 +1,24 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests that the value returned by getCanonicalLocales is an Array. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +---*/ + +var locales = ['en-US']; +var result = Intl.getCanonicalLocales(['en-US']); + +assert.sameValue(Object.getPrototypeOf(result), Array.prototype, 'prototype is Array.prototype'); +assert.sameValue(result.constructor, Array); + +assert.notSameValue(result, locales, "result is a new array instance"); +assert.sameValue(result.length, 1, "result.length"); +assert(result.hasOwnProperty("0"), "result an own property `0`"); +assert.sameValue(result[0], "en-US", "result[0]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/returned-object-is-mutable.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/returned-object-is-mutable.js new file mode 100644 index 0000000000..90c75daa99 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/returned-object-is-mutable.js @@ -0,0 +1,37 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-intl.getcanonicallocales +description: > + Tests that the value returned by getCanonicalLocales is a mutable array. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [propertyHelper.js] +---*/ + +var locales = ['en-US', 'fr']; +var result = Intl.getCanonicalLocales(locales); + +verifyEnumerable(result, 0); +verifyWritable(result, 0); +verifyConfigurable(result, 0); + +result = Intl.getCanonicalLocales(locales); +verifyEnumerable(result, 1); +verifyWritable(result, 1); +verifyConfigurable(result, 1); + +result = Intl.getCanonicalLocales(locales); +verifyNotEnumerable(result, 'length'); +verifyNotConfigurable(result, 'length'); + +assert.sameValue(result.length, 2); +result.length = 42; +assert.sameValue(result.length, 42); +assert.throws(RangeError, function() { + result.length = "Leo"; +}, "a non-numeric value can't be set to result.length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/shell.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/shell.js diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/to-string.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/to-string.js new file mode 100644 index 0000000000..ebc0a5ba3c --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/to-string.js @@ -0,0 +1,22 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Test Intl.getCanonicalLocales.name for step 7.c.iii +info: | + 9.2.1 CanonicalizeLocaleList (locales) + 7. Repeat, while k < len. + c. If kPresent is true, then + iii. Let tag be ? ToString(kValue). +includes: [compareArray.js] +---*/ + +var locales = { + '0': { toString: function() { locales[1] = 'pt-BR'; return 'en-US'; }}, + length: 2 +}; + +assert(compareArray(Intl.getCanonicalLocales(locales), [ "en-US", "pt-BR" ])); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-canonical.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-canonical.js new file mode 100644 index 0000000000..c6717a364b --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-canonical.js @@ -0,0 +1,56 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test canonicalisation within transformed extension subtags. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + +includes: [testIntl.js] +---*/ + +const testData = { + // Variant subtags are alphabetically ordered. + "sl-t-sl-rozaj-biske-1994": "sl-t-sl-1994-biske-rozaj", + + // tfield subtags are alphabetically ordered. + // (Also tests subtag case normalisation.) + "DE-T-M0-DIN-K0-QWERTZ": "de-t-k0-qwertz-m0-din", + + // "true" tvalue subtags aren't removed. + // (UTS 35 version 36, §3.2.1 claims otherwise, but tkey must be followed by + // tvalue, so that's likely a spec bug in UTS 35.) + "en-t-m0-true": "en-t-m0-true", + + // tlang subtags are canonicalised. + "en-t-iw": "en-t-he", + + // Deprecated tvalue subtags are replaced by their preferred value. + "und-Latn-t-und-hani-m0-names": "und-Latn-t-und-hani-m0-prprname", +}; + +for (let [tag, canonical] of Object.entries(testData)) { + // Make sure the test data is correct. + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-invalid.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-invalid.js new file mode 100644 index 0000000000..2a278ce2b3 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-invalid.js @@ -0,0 +1,80 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + A RangeError is thrown when a language tag includes an invalid transformed extension subtag. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + ... + +includes: [testIntl.js] +---*/ + +const invalid = [ + // empty + "en-t", + "en-t-a", + "en-t-x", + "en-t-0", + + // incomplete + "en-t-", + "en-t-en-", + "en-t-0x-", + + // tlang: unicode_language_subtag must be 2-3 or 5-8 characters and mustn't + // contain extlang subtags. + "en-t-root", + "en-t-abcdefghi", + "en-t-ar-aao", + + // tlang: unicode_script_subtag must be 4 alphabetical characters, can't + // be repeated. + "en-t-en-lat0", + "en-t-en-latn-latn", + + // tlang: unicode_region_subtag must either be 2 alpha characters or a three + // digit code. + "en-t-en-0", + "en-t-en-00", + "en-t-en-0x", + "en-t-en-x0", + "en-t-en-latn-0", + "en-t-en-latn-00", + "en-t-en-latn-xyz", + + // tlang: unicode_variant_subtag is either 5-8 alphanum characters or 4 + // characters starting with a digit. + "en-t-en-abcdefghi", + "en-t-en-latn-gb-ab", + "en-t-en-latn-gb-abc", + "en-t-en-latn-gb-abcd", + "en-t-en-latn-gb-abcdefghi", + + // tkey must be followed by tvalue. + "en-t-d0", + "en-t-d0-m0", + "en-t-d0-x-private", +]; + +for (let tag of invalid) { + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a structurally valid language tag."); + + assert.throws(RangeError, () => Intl.getCanonicalLocales(tag), `${tag}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-valid.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-valid.js new file mode 100644 index 0000000000..6668b94ad8 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/transformed-ext-valid.js @@ -0,0 +1,80 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + No RangeError is thrown when a language tag includes a valid transformed extension subtag. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + +includes: [testIntl.js] +---*/ + +const valid = [ + // tlang with unicode_language_subtag. + "en-t-en", + + // tlang with unicode_script_subtag. + "en-t-en-latn", + + // tlang with unicode_region_subtag. + "en-t-en-ca", + + // tlang with unicode_script_subtag and unicode_region_subtag. + "en-t-en-latn-ca", + + // tlang with unicode_variant_subtag. + "en-t-en-emodeng", + + // tlang with unicode_script_subtag and unicode_variant_subtag. + "en-t-en-latn-emodeng", + + // tlang with unicode_script_subtag and unicode_variant_subtag. + "en-t-en-ca-emodeng", + + // tlang with unicode_script_subtag, unicode_region_subtag, and unicode_variant_subtag. + "en-t-en-latn-ca-emodeng", + + // No tlang. (Must contain at least one tfield.) + "en-t-d0-ascii", +]; + +const extraFields = [ + // No extra tfield + "", + + // tfield with a tvalue consisting of a single subtag. + "-i0-handwrit", + + // tfield with a tvalue consisting of two subtags. + "-s0-accents-publish", +]; + +for (let tag of valid) { + for (let extra of extraFields) { + let actualTag = tag + extra; + + // Make sure the test data is correct. + assert(isCanonicalizedStructurallyValidLanguageTag(actualTag), + "\"" + actualTag + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(actualTag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], actualTag); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-calendar.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-calendar.js new file mode 100644 index 0000000000..736b8e7013 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-calendar.js @@ -0,0 +1,60 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test Unicode extension subtag canonicalisation for the "ca" extension key. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. + See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The + aliases are in the alias attribute value, while the canonical is in the name attribute value. +includes: [testIntl.js] +---*/ + +// <key name="ca" [...] alias="calendar"> +const testData = { + // <type name="ethioaa" [...] alias="ethiopic-amete-alem"/> + "ethiopic-amete-alem": "ethioaa", + + // <type name="islamic-civil" [...] /> + // <type name="islamicc" [...] deprecated="true" preferred="islamic-civil" alias="islamic-civil"/> + // + // "name" and "alias" for "islamic-civil" don't quite match of what's spec'ed in UTS 35, §3.2.1. + // Specifically following §3.2.1 to the letter means "islamicc" is the canonical value whereas + // "islamic-civil" is an alias value. Assume the definitions in + // https://unicode.org/reports/tr35/#Unicode_Locale_Extension_Data_Files overrule UTS 35, §3.2.1. + "islamicc": "islamic-civil", +}; + +for (let [alias, name] of Object.entries(testData)) { + let tag = "und-u-ca-" + alias; + let canonical = "und-u-ca-" + name; + + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a canonical language tag."); + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-col-strength.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-col-strength.js new file mode 100644 index 0000000000..48c033d7e1 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-col-strength.js @@ -0,0 +1,67 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test Unicode extension subtag canonicalisation for the "ks" extension key. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. + See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The + aliases are in the alias attribute value, while the canonical is in the name attribute value. +includes: [testIntl.js] +---*/ + +// <key name="ks" [...] alias="colStrength">/ +const testData = { + // <type name="level1" [...] alias="primary"/> + "primary": "level1", + + // "secondary" doesn't match |uvalue|, so we can skip it. + // <type name="level2" [...] alias="secondary"/> + // "secondary": "level2", + + // <type name="level3" [...] alias="tertiary"/> + "tertiary": "level3", + + // Neither "quaternary" nor "quarternary" match |uvalue|, so we can skip them. + // <type name="level4" [...] alias="quaternary quarternary"/> + // "quaternary": "level4", + // "quarternary": "level4", + + // "identical" doesn't match |uvalue|, so we can skip it. + // <type name="identic" [...] alias="identical"/> + // "identical": "identic", +}; + +for (let [alias, name] of Object.entries(testData)) { + let tag = "und-u-ks-" + alias; + let canonical = "und-u-ks-" + name; + + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a canonical language tag."); + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-measurement-system.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-measurement-system.js new file mode 100644 index 0000000000..28c587155b --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-measurement-system.js @@ -0,0 +1,51 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test Unicode extension subtag canonicalisation for the "ms" extension key. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. + See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The + aliases are in the alias attribute value, while the canonical is in the name attribute value. +includes: [testIntl.js] +---*/ + +// <key name="ms" [...] alias="measure" since="28"> +const testData = { + // <type name="uksystem" [...] alias="imperial" since="28" /> + "imperial": "uksystem", +}; + +for (let [alias, name] of Object.entries(testData)) { + let tag = "und-u-ms-" + alias; + let canonical = "und-u-ms-" + name; + + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a canonical language tag."); + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-region.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-region.js new file mode 100644 index 0000000000..34e1e95082 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-region.js @@ -0,0 +1,69 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test Unicode extension subtag canonicalisation for the "rg" extension key. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. + See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The + aliases are in the alias attribute value, while the canonical is in the name attribute value. + + Replace aliases in special key values: + If there is an 'sd' or 'rg' key, replace any subdivision alias in its value in the same way, + using subdivisionAlias data. +includes: [testIntl.js] +---*/ + +const testData = { + // <subdivisionAlias type="no23" replacement="no50" reason="deprecated"/> + "no23": "no50", + + // <subdivisionAlias type="cn11" replacement="cnbj" reason="deprecated"/> + "cn11": "cnbj", + + // <subdivisionAlias type="cz10a" replacement="cz110" reason="deprecated"/> + "cz10a": "cz110", + + // <subdivisionAlias type="fra" replacement="frges" reason="deprecated"/> + "fra": "frges", + + // <subdivisionAlias type="frg" replacement="frges" reason="deprecated"/> + "frg": "frges", + + // <subdivisionAlias type="lud" replacement="lucl ludi lurd luvd luwi" reason="deprecated"/> + "lud": "lucl", +}; + +for (let [alias, name] of Object.entries(testData)) { + let tag = "und-u-rg-" + alias; + let canonical = "und-u-rg-" + name; + + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a canonical language tag."); + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-subdivision.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-subdivision.js new file mode 100644 index 0000000000..d7f9f6ff4f --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-subdivision.js @@ -0,0 +1,74 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test Unicode extension subtag canonicalisation for the "sd" extension key. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. + See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The + aliases are in the alias attribute value, while the canonical is in the name attribute value. + + Replace aliases in special key values: + If there is an 'sd' or 'rg' key, replace any subdivision alias in its value in the same way, + using subdivisionAlias data. +includes: [testIntl.js] +---*/ + +const testData = { + // <subdivisionAlias type="no23" replacement="no50" reason="deprecated"/> + "no23": "no50", + + // <subdivisionAlias type="cn11" replacement="cnbj" reason="deprecated"/> + "cn11": "cnbj", + + // <subdivisionAlias type="cz10a" replacement="cz110" reason="deprecated"/> + "cz10a": "cz110", + + // <subdivisionAlias type="fra" replacement="frges" reason="deprecated"/> + "fra": "frges", + + // <subdivisionAlias type="frg" replacement="frges" reason="deprecated"/> + "frg": "frges", + + // <subdivisionAlias type="lud" replacement="lucl ludi lurd luvd luwi" reason="deprecated"/> + "lud": "lucl", +}; + +for (let [alias, name] of Object.entries(testData)) { + // Subdivision codes should always have a matching region subtag. This + // shouldn't actually matter for canonicalisation, but let's not push our + // luck and instead keep the language tag 'valid' per UTS 35, §3.6.5. + let region = name.substring(0, 2).toUpperCase(); + + let tag = `und-${region}-u-sd-${alias}`; + let canonical = `und-${region}-u-sd-${name}`; + + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a canonical language tag."); + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-timezone.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-timezone.js new file mode 100644 index 0000000000..8a6a780c83 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-timezone.js @@ -0,0 +1,74 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test Unicode extension subtag canonicalisation for the "tz" extension key. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. + See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The + aliases are in the alias attribute value, while the canonical is in the name attribute value. +includes: [testIntl.js] +---*/ + +// <key name="tz" [...] alias="timezone"> +const testData = { + // Similar to the "ca" extension key, assume "preferred" holds the canonical + // value and "name" the alias value. + + // <type name="cnckg" [...] deprecated="true" preferred="cnsha"/> + "cnckg": "cnsha", + + // NB: "Eire" matches the |uvalue| production. + // <type name="iedub" [...] alias="Europe/Dublin Eire"/> + "eire": "iedub", + + // NB: "EST" matches the |uvalue| production. + // <type name="utcw05" [...] alias="Etc/GMT+5 EST"/> + "est": "utcw05", + + // NB: "GMT0" matches the |uvalue| production. + // <type name="gmt" [...] alias="Etc/GMT Etc/GMT+0 Etc/GMT-0 Etc/GMT0 Etc/Greenwich GMT GMT+0 GMT-0 GMT0 Greenwich"/> + "gmt0": "gmt", + + // NB: "UCT" matches the |uvalue| production. + // <type name="utc" [...] alias="Etc/UTC Etc/UCT Etc/Universal Etc/Zulu UCT UTC Universal Zulu"/> + "uct": "utc", + + // NB: "Zulu" matches the |uvalue| production. + // <type name="utc" [...] alias="Etc/UTC Etc/UCT Etc/Universal Etc/Zulu UCT UTC Universal Zulu"/> + "zulu": "utc", +}; + +for (let [alias, name] of Object.entries(testData)) { + let tag = "und-u-tz-" + alias; + let canonical = "und-u-tz-" + name; + + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a canonical language tag."); + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-yes-to-true.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-yes-to-true.js new file mode 100644 index 0000000000..7ef23a3586 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-yes-to-true.js @@ -0,0 +1,88 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + "kb", "kc", "kh", "kk", and "kn" Unicode extension keys canonicalise "yes" to "true". +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Use the bcp47 data to replace keys, types, tfields, and tvalues by their canonical forms. + See Section 3.6.4 U Extension Data Files) and Section 3.7.1 T Extension Data Files. The + aliases are in the alias attribute value, while the canonical is in the name attribute value. + + UTS 35, §3.2.1 Canonical Unicode Locale Identifiers + Any type or tfield value "true" is removed. +includes: [testIntl.js] +---*/ + +const unicodeKeys = [ + // <key name="kb" [...] alias="colBackwards"> + // <type name="true" [...] alias="yes"/> + "kb", + + // <key name="kc" [...] alias="colCaseLevel"> + // <type name="true" [...] alias="yes"/> + "kc", + + // <key name="kh" [...] alias="colBackwards"> + // <type name="true" [...] alias="yes"/> + "kh", + + // <key name="kh" [...] alias="colHiraganaQuaternary"> + // <type name="true" [...] alias="yes"/> + "kk", + + // <key name="kn" [...] alias="colNumeric"> + // <type name="true" [...] alias="yes"/> + "kn", +]; + +for (let key of unicodeKeys) { + let tag = `und-u-${key}-yes`; + let canonical = `und-u-${key}`; + + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(tag), false, + "\"" + tag + "\" isn't a canonical language tag."); + assert(isCanonicalizedStructurallyValidLanguageTag(canonical), + "\"" + canonical + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], canonical); +} + +// Test some other Unicode extension keys which don't contain an alias entry to +// canonicalise "yes" to "true". +const otherUnicodeKeys = [ + "ka", "kf", "kr", "ks", "kv", +]; + +for (let key of otherUnicodeKeys) { + let tag = `und-u-${key}-yes`; + + // Make sure the test data is correct. + assert(isCanonicalizedStructurallyValidLanguageTag(tag), + "\"" + tag + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(tag); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], tag); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-key-with-digit.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-key-with-digit.js new file mode 100644 index 0000000000..9271e01f7a --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/unicode-ext-key-with-digit.js @@ -0,0 +1,56 @@ +// Copyright (C) 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: > + Test Unicode extension subtags where the ukey subtag contains a digit. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). + + 9.2.1 CanonicalizeLocaleList (locales) + ... + 7. Repeat, while k < len + ... + c. If kPresent is true, then + ... + v. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + vi. Let canonicalizedTag be CanonicalizeUnicodeLocaleId(tag). + ... + +includes: [testIntl.js] +---*/ + +// Unicode locale extension sequences don't allow keys with a digit as their +// second character. +const invalidCases = [ + "en-u-c0", + "en-u-00", +]; + +// The first character is allowed to be a digit. +const validCases = [ + "en-u-0c", +]; + +for (let invalid of invalidCases) { + // Make sure the test data is correct. + assert.sameValue(isCanonicalizedStructurallyValidLanguageTag(invalid), false, + "\"" + invalid + "\" isn't a structurally valid language tag."); + + assert.throws(RangeError, () => Intl.getCanonicalLocales(invalid)); +} + +for (let valid of validCases) { + // Make sure the test data is correct. + assert(isCanonicalizedStructurallyValidLanguageTag(valid), + "\"" + valid + "\" is a canonical and structurally valid language tag."); + + let result = Intl.getCanonicalLocales(valid); + assert.sameValue(result.length, 1); + assert.sameValue(result[0], valid); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/getCanonicalLocales/weird-cases.js b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/weird-cases.js new file mode 100644 index 0000000000..adf48ad404 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/getCanonicalLocales/weird-cases.js @@ -0,0 +1,26 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.getcanonicallocales +description: Tests the getCanonicalLocales function for weird tags. +info: | + 8.2.1 Intl.getCanonicalLocales (locales) + 1. Let ll be ? CanonicalizeLocaleList(locales). + 2. Return CreateArrayFromList(ll). +includes: [compareArray.js] +---*/ + +var weirdCases = + [ + "en-x-u-foo", + "en-a-bar-x-u-foo", + "en-x-u-foo-a-bar", + "en-a-bar-u-baz-x-u-foo", + ]; + +weirdCases.forEach(function (weird) { + assert(compareArray(Intl.getCanonicalLocales(weird), [weird])); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/shell.js b/js/src/tests/test262/intl402/Intl/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/shell.js diff --git a/js/src/tests/test262/intl402/Intl/toStringTag/browser.js b/js/src/tests/test262/intl402/Intl/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/Intl/toStringTag/shell.js b/js/src/tests/test262/intl402/Intl/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/Intl/toStringTag/toString.js b/js/src/tests/test262/intl402/Intl/toStringTag/toString.js new file mode 100644 index 0000000000..fdcd994990 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/toStringTag/toString.js @@ -0,0 +1,34 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl-toStringTag +description: > + Object.prototype.toString utilizes Intl[@@toStringTag] and doesn't special-case Intl namespace object. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". + + Intl [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl". +features: [Symbol.toStringTag] +---*/ + +assert.sameValue(Intl.toString(), "[object Intl]"); +assert.sameValue(Object.prototype.toString.call(Intl), "[object Intl]"); + +Object.defineProperty(Intl, Symbol.toStringTag, { value: "test262" }); +assert.sameValue(Intl.toString(), "[object test262]"); +assert.sameValue(Object.prototype.toString.call(Intl), "[object test262]"); + +assert(delete Intl[Symbol.toStringTag]); +assert.sameValue(Intl.toString(), "[object Object]"); +assert.sameValue(Object.prototype.toString.call(Intl), "[object Object]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Intl/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/Intl/toStringTag/toStringTag.js new file mode 100644 index 0000000000..0b5c250369 --- /dev/null +++ b/js/src/tests/test262/intl402/Intl/toStringTag/toStringTag.js @@ -0,0 +1,25 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl-toStringTag +description: > + Property descriptor of Intl[@@toStringTag]. +info: | + Intl [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.toStringTag] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl, Symbol.toStringTag, { + value: "Intl", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/browser.js b/js/src/tests/test262/intl402/ListFormat/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/browser.js b/js/src/tests/test262/intl402/ListFormat/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/browser.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/locales-invalid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/locales-invalid.js new file mode 100644 index 0000000000..8cb49d6243 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/locales-invalid.js @@ -0,0 +1,18 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks error cases for the locales argument to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) + 1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). +includes: [testIntl.js] +features: [Intl.ListFormat] +---*/ + +for (const [locales, expectedError] of getInvalidLocaleArguments()) { + assert.throws(expectedError, function() { new Intl.ListFormat(locales) }) +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/locales-valid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/locales-valid.js new file mode 100644 index 0000000000..4a63cec4c2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/locales-valid.js @@ -0,0 +1,45 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks various cases for the locales argument to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) + 1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). +features: [Intl.ListFormat] +---*/ + +const defaultLocale = new Intl.ListFormat().resolvedOptions().locale; + +const tests = [ + [undefined, defaultLocale, "undefined"], + ["EN", "en", "Single value"], + [[], defaultLocale, "Empty array"], + [["en", "EN"], "en", "Duplicate value (canonical first)"], + [["EN", "en"], "en", "Duplicate value (canonical last)"], + [{ 0: "DE", length: 0 }, defaultLocale, "Object with zero length"], + [{ 0: "DE", length: 1 }, "de", "Object with length"], +]; + +const errorTests = [ + [["en-GB-oed"], "Grandfathered"], + [["x-private"], "Private", ["lookup"]], +]; + +for (const [locales, expected, name, matchers = ["lookup", "best fit"]] of tests) { + for (const matcher of matchers) { + const rtf = new Intl.ListFormat(locales, {localeMatcher: matcher}); + assert.sameValue(rtf.resolvedOptions().locale, expected, name); + } +} + +for (const [locales, name, matchers = ["lookup", "best fit"]] of errorTests) { + for (const matcher of matchers) { + assert.throws(RangeError, function() { + new Intl.ListFormat(locales, {localeMatcher: matcher}) + }, name); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/newtarget-undefined.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/newtarget-undefined.js new file mode 100644 index 0000000000..48198c9a92 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/newtarget-undefined.js @@ -0,0 +1,29 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.ListFormat +description: > + Verifies the NewTarget check for Intl.ListFormat. +info: | + Intl.ListFormat ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat, "function"); + +assert.throws(TypeError, function() { + Intl.ListFormat(); +}); + +assert.throws(TypeError, function() { + Intl.ListFormat("en"); +}); + +assert.throws(TypeError, function() { + Intl.ListFormat("not-valid-tag"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-invalid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-invalid.js new file mode 100644 index 0000000000..681f5f1c96 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-invalid.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: sec-Intl.ListFormat +description: Checks handling of a null options argument to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) + 3. Else + a. Let options be ? ToObject(options). +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat, "function"); +assert.throws(TypeError, function() { + new Intl.ListFormat([], null); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-localeMatcher-invalid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-localeMatcher-invalid.js new file mode 100644 index 0000000000..19d643f2d9 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-localeMatcher-invalid.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of invalid value for the localeMatcher option to the ListFormat constructor. +info: | + Intl.ListFormat ( [ locales [ , options ] ] ) + 12. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). +features: [Intl.ListFormat] +---*/ + +const invalidOptions = [ + null, + 1, + "", + "Lookup", + "LOOKUP", + "lookup\0", + "Best fit", + "BEST FIT", + "best\u00a0fit", +]; + +for (const localeMatcher of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.ListFormat([], { localeMatcher }); + }, `${localeMatcher} is an invalid localeMatcher option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-order.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-order.js new file mode 100644 index 0000000000..3d6a9e11e6 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-order.js @@ -0,0 +1,59 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks the order of operations on the options argument to the ListFormat constructor. +info: | + Intl.ListFormat ( [ locales [ , options ] ] ) + 7. Let type be GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction"). + 9. Let style be GetOption(options, "style", "string", « "long", "short", "narrow" », "long"). + 12. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). +includes: [compareArray.js] +features: [Intl.ListFormat] +---*/ + +const callOrder = []; + +new Intl.ListFormat([], { + get localeMatcher() { + callOrder.push("localeMatcher"); + return { + toString() { + callOrder.push("localeMatcher toString"); + return "best fit"; + } + }; + }, + + get type() { + callOrder.push("type"); + return { + toString() { + callOrder.push("type toString"); + return "unit"; + } + }; + }, + + get style() { + callOrder.push("style"); + return { + toString() { + callOrder.push("style toString"); + return "short"; + } + }; + }, +}); + +assert.compareArray(callOrder, [ + "localeMatcher", + "localeMatcher toString", + "type", + "type toString", + "style", + "style toString", +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-style-invalid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-style-invalid.js new file mode 100644 index 0000000000..6701776cd7 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-style-invalid.js @@ -0,0 +1,34 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of invalid value for the style option to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) + 9. Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long"). +features: [Intl.ListFormat] +---*/ + +const invalidOptions = [ + null, + 1, + "", + "Long", + "LONG", + "long\0", + "Short", + "SHORT", + "short\0", + "Narrow", + "NARROW", + "narrow\0", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.ListFormat([], {"style": invalidOption}); + }, `${invalidOption} is an invalid style option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-style-valid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-style-valid.js new file mode 100644 index 0000000000..bc97773d33 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-style-valid.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of valid values for the style option to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) + InitializeListFormat (listFormat, locales, options) + 12. Let type be ? GetOption(options, "type", "string", « "conjunction", + "disjunction", "unit" », "conjunction"). + 13. Set listFormat.[[Type]] to type. + 14. Let style be ? GetOption(options, "style", "string", « "long", "short", + "narrow" », "long"). + 15. Set listFormat.[[Style]] to style. +features: [Intl.ListFormat] +---*/ + +const validOptions = [ + [undefined, "long"], + ["long", "long"], + ["short", "short"], + ["narrow", "narrow"], + [{ toString() { return "short"; } }, "short"], + [{ toString() { return "long"; } }, "long"], + [{ toString() { return "narrow"; } }, "narrow"], +]; + +for (const [validOption, expected] of validOptions) { + const lf = new Intl.ListFormat([], {"style": validOption}); + const resolvedOptions = lf.resolvedOptions(); + assert.sameValue(resolvedOptions.style, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-throwing-getters.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-throwing-getters.js new file mode 100644 index 0000000000..3da4b38e1a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-throwing-getters.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks the propagation of exceptions from the options for the ListFormat constructor. +features: [Intl.ListFormat] +---*/ + +function CustomError() {} + +const options = [ + "type", + "style", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.ListFormat("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-toobject-prototype.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-toobject-prototype.js new file mode 100644 index 0000000000..e503d27beb --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-toobject-prototype.js @@ -0,0 +1,37 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of non-object option arguments to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) +features: [Intl.ListFormat] +---*/ + +Object.defineProperties(Object.prototype, { + "type": { + value: "unit", + }, + "style": { + value: "short", + }, +}) + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), +]; + +for (const options of optionsArguments) { + const lf = new Intl.ListFormat([], options); + const resolvedOptions = lf.resolvedOptions(); + assert.sameValue(resolvedOptions.type, "unit", + `options argument ${String(options)} should yield the correct value for "type"`); + assert.sameValue(resolvedOptions.style, "short", + `options argument ${String(options)} should yield the correct value for "style"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-toobject.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-toobject.js new file mode 100644 index 0000000000..004723d1d6 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-toobject.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of non-object option arguments to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) +features: [Intl.ListFormat] +---*/ + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), +]; + +for (const options of optionsArguments) { + const lf = new Intl.ListFormat([], options); + const resolvedOptions = lf.resolvedOptions(); + assert.sameValue(resolvedOptions.type, "conjunction", + `options argument ${String(options)} should yield the correct value for "type"`); + assert.sameValue(resolvedOptions.style, "long", + `options argument ${String(options)} should yield the correct value for "style"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-type-invalid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-type-invalid.js new file mode 100644 index 0000000000..10f6fd599d --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-type-invalid.js @@ -0,0 +1,34 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of invalid value for the type option to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) + 7. Let type be GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction"). +features: [Intl.ListFormat] +---*/ + +const invalidOptions = [ + null, + 1, + "", + "Conjunction", + "CONJUNCTION", + "conjunction\0", + "Disjunction", + "DISJUNCTION", + "disjunction\0", + "Unit", + "UNIT", + "unit\0", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.ListFormat([], {"type": invalidOption}); + }, `${invalidOption} is an invalid type option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-type-valid.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-type-valid.js new file mode 100644 index 0000000000..e3ba4e1077 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-type-valid.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of valid values for the style option to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) + 7. Let type be GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction"). + 8. Set listFormat.[[Type]] to type. +features: [Intl.ListFormat] +---*/ + +const validOptions = [ + [undefined, "conjunction"], + ["conjunction", "conjunction"], + ["disjunction", "disjunction"], + ["unit", "unit"], + [{ toString() { return "unit"; } }, "unit"], +]; + +for (const [validOption, expected] of validOptions) { + const lf = new Intl.ListFormat([], {"type": validOption}); + const resolvedOptions = lf.resolvedOptions(); + assert.sameValue(resolvedOptions.type, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-undefined.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-undefined.js new file mode 100644 index 0000000000..56768c9053 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/options-undefined.js @@ -0,0 +1,40 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks handling of non-object option arguments to the ListFormat constructor. +info: | + InitializeListFormat (listFormat, locales, options) +features: [Intl.ListFormat] +---*/ + +Object.defineProperties(Object.prototype, { + "type": { + get() { + throw new Error("Should not call type getter"); + } + }, + "style": { + get() { + throw new Error("Should not call style getter"); + } + }, +}) + +const optionsArguments = [ + [], + [[]], + [[], undefined], +]; + +for (const args of optionsArguments) { + const lf = new Intl.ListFormat(...args); + const resolvedOptions = lf.resolvedOptions(); + assert.sameValue(resolvedOptions.type, "conjunction", + `Calling with ${args.length} empty arguments should yield the correct value for "type"`); + assert.sameValue(resolvedOptions.style, "long", + `Calling with ${args.length} empty arguments should yield the correct value for "style"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/proto-from-ctor-realm.js new file mode 100644 index 0000000000..44862fa12a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/proto-from-ctor-realm.js @@ -0,0 +1,60 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.ListFormat ( [ locales [ , options ] ] ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let listFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%ListFormatPrototype%", « ... »). + ... + 24. Return listFormat. + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.ListFormat, cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var lf; + +newTarget.prototype = undefined; +lf = Reflect.construct(Intl.ListFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(lf), other.Intl.ListFormat.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +lf = Reflect.construct(Intl.ListFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(lf), other.Intl.ListFormat.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = true; +lf = Reflect.construct(Intl.ListFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(lf), other.Intl.ListFormat.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = 'str'; +lf = Reflect.construct(Intl.ListFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(lf), other.Intl.ListFormat.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +lf = Reflect.construct(Intl.ListFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(lf), other.Intl.ListFormat.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = NaN; +lf = Reflect.construct(Intl.ListFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(lf), other.Intl.ListFormat.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/shell.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/constructor/subclassing.js b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/subclassing.js new file mode 100644 index 0000000000..1fd6553f9b --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/constructor/subclassing.js @@ -0,0 +1,41 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: Checks that ListFormat can be subclassed. +info: | + Intl.ListFormat ( [ locales [ , options ] ] ) + + 2. Let listFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%ListFormatPrototype%", « [[InitializedListFormat]], [[Locale]], [[Type]], [[Style]] »). + +features: [Intl.ListFormat] +---*/ + +class CustomListFormat extends Intl.ListFormat { + constructor(locales, options) { + super(locales, options); + this.isCustom = true; + } +} + +const locale = "de"; +const argument = ["foo", "bar"]; + +const real_lf = new Intl.ListFormat(locale); +assert.sameValue(real_lf.isCustom, undefined, "Custom property"); + +const custom_lf = new CustomListFormat(locale); +assert.sameValue(custom_lf.isCustom, true, "Custom property"); + +assert.sameValue(custom_lf.format(argument), + real_lf.format(argument), + "Direct call"); + +assert.sameValue(Intl.ListFormat.prototype.format.call(custom_lf, argument), + Intl.ListFormat.prototype.format.call(real_lf, argument), + "Indirect call"); + +assert.sameValue(Object.getPrototypeOf(custom_lf), CustomListFormat.prototype, "Prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/length.js b/js/src/tests/test262/intl402/ListFormat/constructor/length.js new file mode 100644 index 0000000000..19aa2852db --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: > + Checks the "length" property of the ListFormat 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 ListFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/name.js b/js/src/tests/test262/intl402/ListFormat/constructor/name.js new file mode 100644 index 0000000000..f498bb5e0f --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/name.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: sec-Intl.ListFormat +description: > + Checks the "name" property of the ListFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat, "name", { + value: "ListFormat", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/prop-desc.js b/js/src/tests/test262/intl402/ListFormat/constructor/prop-desc.js new file mode 100644 index 0000000000..3bf5b526fa --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/prop-desc.js @@ -0,0 +1,37 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat +description: > + "ListFormat" property of Intl. +info: | + Intl.ListFormat (...) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat, "function"); + +verifyProperty(Intl, "ListFormat", { + value: Intl.ListFormat, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/prototype.js b/js/src/tests/test262/intl402/ListFormat/constructor/prototype.js new file mode 100644 index 0000000000..a09c23e176 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/prototype.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: sec-Intl.ListFormat +description: The prototype of the Intl.ListFormat constructor is %FunctionPrototype%. +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. + Unless otherwise specified every built-in function object has the %FunctionPrototype% object as the initial value of its [[Prototype]] internal slot. +features: [Intl.ListFormat] +---*/ + +assert.sameValue( + Object.getPrototypeOf(Intl.ListFormat), + Function.prototype, + "Object.getPrototypeOf(Intl.ListFormat) equals the value of Function.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/shell.js b/js/src/tests/test262/intl402/ListFormat/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/basic.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/basic.js new file mode 100644 index 0000000000..81b7dbcf88 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/basic.js @@ -0,0 +1,23 @@ +// Copyright 2018 Google Inc., Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: > + Tests that Intl.ListFormat has a supportedLocalesOf property, + and it works as planned. +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat.supportedLocalesOf, "function", + "supportedLocalesOf should be supported."); + +const defaultLocale = new Intl.ListFormat().resolvedOptions().locale; +const notSupported = 'zxx'; // "no linguistic content" +const requestedLocales = [defaultLocale, notSupported]; + +const supportedLocales = Intl.ListFormat.supportedLocalesOf(requestedLocales); +assert.sameValue(supportedLocales.length, 1, 'The length of supported locales list is not 1.'); +assert.sameValue(supportedLocales[0], defaultLocale, 'The default locale is not returned in the supported list.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/branding.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/branding.js new file mode 100644 index 0000000000..dd28fcf8d6 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/branding.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: > + Verifies there's no branding check for Intl.ListFormat.supportedLocalesOf(). +info: | + Intl.ListFormat.supportedLocalesOf ( locales [, options ]) +features: [Intl.ListFormat] +---*/ + +const fn = Intl.ListFormat.supportedLocalesOf; +const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.ListFormat, + Intl.ListFormat.prototype, +]; + +for (const thisValue of thisValues) { + const result = fn.call(thisValue); + assert.sameValue(Array.isArray(result), true); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/length.js new file mode 100644 index 0000000000..344194999a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: > + Checks the "length" property of Intl.ListFormat.supportedLocalesOf(). +info: | + The value of the length property of the supportedLocalesOf method is 1. + 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, has a length property whose value is an integer. + Unless otherwise specified, the length property of a built-in function object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.supportedLocalesOf, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/locales-invalid.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/locales-invalid.js new file mode 100644 index 0000000000..f8d7769b84 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/locales-invalid.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: sec-Intl.ListFormat.supportedLocalesOf +description: Checks error cases for the locales argument to the supportedLocalesOf function. +info: | + Intl.ListFormat.supportedLocalesOf ( locales [, options ]) + + 2. Let requestedLocales be CanonicalizeLocaleList(locales). +includes: [testIntl.js] +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat.supportedLocalesOf, "function", + "Should support Intl.ListFormat.supportedLocalesOf."); + +for (const [locales, expectedError] of getInvalidLocaleArguments()) { + assert.throws(expectedError, () => Intl.ListFormat.supportedLocalesOf(locales)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/name.js new file mode 100644 index 0000000000..b4e3330d78 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/name.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: sec-Intl.ListFormat.supportedLocalesOf +description: > + Checks the "name" property of Intl.ListFormat.supportedLocalesOf(). +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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.supportedLocalesOf, "name", { + value: "supportedLocalesOf", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-localeMatcher-invalid.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-localeMatcher-invalid.js new file mode 100644 index 0000000000..99714f0967 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-localeMatcher-invalid.js @@ -0,0 +1,36 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: Checks handling of invalid values for the localeMatcher option to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + b. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat.supportedLocalesOf, "function", + "Should support Intl.ListFormat.supportedLocalesOf."); + +const invalidOptions = [ + null, + 1, + "", + "Lookup", + "LOOKUP", + "lookup\0", + "Best fit", + "BEST FIT", + "best\u00a0fit", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + Intl.ListFormat.supportedLocalesOf([], {"localeMatcher": invalidOption}); + }, `${invalidOption} is an invalid localeMatcher option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-null.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-null.js new file mode 100644 index 0000000000..dbc7036579 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-null.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: sec-Intl.ListFormat.supportedLocalesOf +description: Checks handling of a null options argument to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + a. Let options be ? ToObject(options). +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat.supportedLocalesOf, "function", + "Should support Intl.ListFormat.supportedLocalesOf."); + +assert.throws(TypeError, function() { + Intl.ListFormat.supportedLocalesOf([], null); +}, "Should throw when passing null as the options argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-toobject.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-toobject.js new file mode 100644 index 0000000000..811b1210b3 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-toobject.js @@ -0,0 +1,43 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: Checks handling of non-object options arguments to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + a. Let options be ? ToObject(options). +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat.supportedLocalesOf, "function", + "Should support Intl.ListFormat.supportedLocalesOf."); + +let called; +Object.defineProperties(Object.prototype, { + "localeMatcher": { + get() { + ++called; + return "best fit"; + } + } +}); + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), +]; + +for (const options of optionsArguments) { + called = 0; + const result = Intl.ListFormat.supportedLocalesOf([], options); + assert.sameValue(Array.isArray(result), true, `Expected array from ${String(options)}`); + assert.sameValue(called, 1, `Expected one call from ${String(options)}`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-undefined.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-undefined.js new file mode 100644 index 0000000000..3c9506163d --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/options-undefined.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: Checks handling of an undefined options argument to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + b. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.ListFormat] +---*/ + +assert.sameValue(typeof Intl.ListFormat.supportedLocalesOf, "function", + "Should support Intl.ListFormat.supportedLocalesOf."); + +Object.defineProperties(Object.prototype, { + "localeMatcher": { + get() { throw new Error("Should not call localeMatcher getter"); } + } +}); + +assert.sameValue(Array.isArray(Intl.ListFormat.supportedLocalesOf()), true, "No arguments"); +assert.sameValue(Array.isArray(Intl.ListFormat.supportedLocalesOf([])), true, "One argument"); +assert.sameValue(Array.isArray(Intl.ListFormat.supportedLocalesOf([], undefined)), true, "Two arguments"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/prop-desc.js new file mode 100644 index 0000000000..07455d691d --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: > + Checks the "supportedLocalesOf" property of the ListFormat prototype object. +info: | + Intl.ListFormat.supportedLocalesOf ( locales [, options ]) + + 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. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +assert.sameValue( + typeof Intl.ListFormat.supportedLocalesOf, + "function", + "typeof Intl.ListFormat.supportedLocalesOf is function" +); + +verifyProperty(Intl.ListFormat, "supportedLocalesOf", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/result-type.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/result-type.js new file mode 100644 index 0000000000..e6d25bbd95 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/result-type.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.supportedLocalesOf +description: Verifies the type of the return value of Intl.ListFormat.supportedLocalesOf(). +info: | + Intl.ListFormat.supportedLocalesOf ( locales [, options ]) +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +const result = Intl.ListFormat.supportedLocalesOf("en"); +assert.sameValue(Array.isArray(result), true, + "Array.isArray() should return true"); +assert.sameValue(Object.getPrototypeOf(result), Array.prototype, + "The prototype should be Array.prototype"); +assert.sameValue(Object.isExtensible(result), true, + "Object.isExtensible() should return true"); + +assert.notSameValue(result.length, 0); +for (let i = 0; i < result.length; ++i) { + verifyProperty(result, String(i), { + "writable": true, + "enumerable": true, + "configurable": true, + }); +} + +verifyProperty(result, "length", { + "enumerable": false, + "configurable": false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/constructor/supportedLocalesOf/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/instance/browser.js b/js/src/tests/test262/intl402/ListFormat/instance/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/instance/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/instance/extensibility.js b/js/src/tests/test262/intl402/ListFormat/instance/extensibility.js new file mode 100644 index 0000000000..b08bca5c69 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/instance/extensibility.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: sec-Intl.ListFormat +description: Intl.ListFormat instance object extensibility +info: | + 17 ECMAScript Standard Built-in Objects: + + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Intl.ListFormat] +---*/ + +assert.sameValue( + Object.isExtensible(new Intl.ListFormat()), + true, + "Object.isExtensible(new Intl.ListFormat()) returns true" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/instance/prototype.js b/js/src/tests/test262/intl402/ListFormat/instance/prototype.js new file mode 100644 index 0000000000..123fa04b38 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/instance/prototype.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: sec-Intl.ListFormat +description: Intl.ListFormat instance object is created from %ListFormatPrototype%. +info: | + Intl.ListFormat ([ locales [ , options ]]) + + 2. Let listFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%ListFormatPrototype%", « [[InitializedListFormat]], [[Locale]], [[Type]], [[Style]] »). +features: [Intl.ListFormat] +---*/ + +const value = new Intl.ListFormat(); +assert.sameValue( + Object.getPrototypeOf(value), + Intl.ListFormat.prototype, + "Object.getPrototypeOf(value) equals the value of Intl.ListFormat.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/instance/shell.js b/js/src/tests/test262/intl402/ListFormat/instance/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/instance/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/browser.js b/js/src/tests/test262/intl402/ListFormat/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/constructor/browser.js b/js/src/tests/test262/intl402/ListFormat/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/ListFormat/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..882657f4a2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/constructor/prop-desc.js @@ -0,0 +1,26 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.constructor +description: Checks the "constructor" property of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype.constructor + + The initial value of Intl.ListFormat.prototype.constructor is %ListFormat%. + + 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. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.prototype, "constructor", { + value: Intl.ListFormat, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/constructor/shell.js b/js/src/tests/test262/intl402/ListFormat/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/branding.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/branding.js new file mode 100644 index 0000000000..49fed5952f --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/branding.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Verifies the branding check for the "format" function of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype.format ([ list ]) + + 2. If Type(lf) is not Object, throw a TypeError exception. + 3. If lf does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. +features: [Intl.ListFormat] +---*/ + +const format = Intl.ListFormat.prototype.format; + +assert.sameValue(typeof format, "function"); + +assert.throws(TypeError, () => format.call(undefined), "undefined"); +assert.throws(TypeError, () => format.call(null), "null"); +assert.throws(TypeError, () => format.call(true), "true"); +assert.throws(TypeError, () => format.call(""), "empty string"); +assert.throws(TypeError, () => format.call(Symbol()), "symbol"); +assert.throws(TypeError, () => format.call(1), "1"); +assert.throws(TypeError, () => format.call({}), "plain object"); +assert.throws(TypeError, () => format.call(Intl.ListFormat), "Intl.ListFormat"); +assert.throws(TypeError, () => format.call(Intl.ListFormat.prototype), "Intl.ListFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/browser.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-default.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-default.js new file mode 100644 index 0000000000..788ba9594a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-default.js @@ -0,0 +1,54 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US"); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo and bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo, bar, and baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo, bar, baz, and quux"); +} + +assert.sameValue(lf.format("foo"), "f, o, and o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-disjunction.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-disjunction.js new file mode 100644 index 0000000000..fb1e941d9a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-disjunction.js @@ -0,0 +1,56 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { + "type": "disjunction", +}); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo or bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo, bar, or baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo, bar, baz, or quux"); +} + +assert.sameValue(lf.format("foo"), "f, o, or o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-narrow.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-narrow.js new file mode 100644 index 0000000000..ef9798b787 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-narrow.js @@ -0,0 +1,57 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { + "style": "narrow", + "type": "unit", +}); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo bar baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo bar baz quux"); +} + +assert.sameValue(lf.format("foo"), "f o o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-short.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-short.js new file mode 100644 index 0000000000..f56a9f23c4 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-short.js @@ -0,0 +1,56 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { + "style": "short", +}); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo & bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo, bar, & baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo, bar, baz, & quux"); +} + +assert.sameValue(lf.format("foo"), "f, o, & o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-unit.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-unit.js new file mode 100644 index 0000000000..da881123b8 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/en-us-unit.js @@ -0,0 +1,56 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { + "type": "unit", +}); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo, bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo, bar, baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo, bar, baz, quux"); +} + +assert.sameValue(lf.format("foo"), "f, o, o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-long.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-long.js new file mode 100644 index 0000000000..a4bfa6b425 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-long.js @@ -0,0 +1,57 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("es-ES", { + "style": "long", + "type": "unit", +}); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo y bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo, bar y baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo, bar, baz y quux"); +} + +assert.sameValue(lf.format("foo"), "f, o y o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-narrow.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-narrow.js new file mode 100644 index 0000000000..cfd3f7b545 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-narrow.js @@ -0,0 +1,57 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("es-ES", { + "style": "narrow", + "type": "unit", +}); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo bar baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo bar baz quux"); +} + +assert.sameValue(lf.format("foo"), "f o o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-short.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-short.js new file mode 100644 index 0000000000..b812906d1b --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/es-es-short.js @@ -0,0 +1,57 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Intl.ListFormat.prototype.format() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("es-ES", { + "style": "short", + "type": "unit", +}); + +assert.sameValue(typeof lf.format, "function", "format should be supported"); + +for (const f of transforms) { + assert.sameValue(lf.format(f([])), ""); + assert.sameValue(lf.format(f(["foo"])), "foo"); + assert.sameValue(lf.format(f(["foo", "bar"])), "foo y bar"); + assert.sameValue(lf.format(f(["foo", "bar", "baz"])), "foo, bar, baz"); + assert.sameValue(lf.format(f(["foo", "bar", "baz", "quux"])), "foo, bar, baz, quux"); +} + +assert.sameValue(lf.format("foo"), "f, o, o"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-getiterator-throw.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-getiterator-throw.js new file mode 100644 index 0000000000..88d701a832 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-getiterator-throw.js @@ -0,0 +1,29 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable called by Intl.ListFormat.prototype.format() while the GetIterator + throws error. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). +features: [Intl.ListFormat] +---*/ + +function CustomError() {} + +let lf = new Intl.ListFormat(); +// Test the failure case. +let get_iterator_throw_error = { + [Symbol.iterator]() { + throw new CustomError(); + } +}; +assert.throws(CustomError, + ()=> {lf.format(get_iterator_throw_error)}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-invalid.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-invalid.js new file mode 100644 index 0000000000..59f274d2d1 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-invalid.js @@ -0,0 +1,51 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.format(). +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let error be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, error). + iii. Append nextValue to the end of the List list. + 6. Return list. +features: [Intl.ListFormat] +---*/ + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterable_of_strings_and_number = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++; + if (this.count == 3) { + return {done:false, value: 3}; + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(TypeError, + ()=> {lf.format(iterable_of_strings_and_number)}, + "Iterable yielded 3 which is not a string"); +assert.sameValue(iterable_of_strings_and_number.count, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorclose.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorclose.js new file mode 100644 index 0000000000..f5fdc77d09 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorclose.js @@ -0,0 +1,58 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.format() and check the IteratorClose + calls return. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let error be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, error). + iii. Append nextValue to the end of the List list. + 6. Return list. +features: [Intl.ListFormat] +---*/ + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterator_close_call_return = { + [Symbol.iterator]() { + return this; + }, + "return"() { + this.returnIsCalled = true; + assert.sameValue(this.count, 3); + }, + count: 0, + returnIsCalled: false, + next() { + this.count++; + if (this.count == 3) { + return {done:false, value: 3}; + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(TypeError, + ()=> {lf.format(iterator_close_call_return)}, + "Iterable yielded 3 which is not a string"); +assert.sameValue(iterator_close_call_return.count, 3); +assert.sameValue(iterator_close_call_return.returnIsCalled, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorstep-throw.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorstep-throw.js new file mode 100644 index 0000000000..3a6f1fc5ca --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorstep-throw.js @@ -0,0 +1,44 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.format() while iteratorStep throws error. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). +features: [Intl.ListFormat] +---*/ +function CustomError() {} + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterator_step_throw = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++; + if (this.count == 3) { + throw new CustomError(); + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(CustomError, + ()=> {lf.format(iterator_step_throw)}); +assert.sameValue(iterator_step_throw.count, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorvalue-throw.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorvalue-throw.js new file mode 100644 index 0000000000..3164b68630 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-iteratorvalue-throw.js @@ -0,0 +1,47 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.format() while iteratorValue throws error. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). +features: [Intl.ListFormat] +---*/ + +function CustomError() {} + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterator_value_throw = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++; + if (this.count == 3) { + return {done: false, get value() { throw new CustomError() }}; + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(CustomError, + ()=> {lf.format(iterator_value_throw)}); +assert.sameValue(iterator_value_throw.count, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-undefined.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-undefined.js new file mode 100644 index 0000000000..9c922eb499 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable-undefined.js @@ -0,0 +1,20 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.format(undefined). +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. +features: [Intl.ListFormat] +---*/ + +let lf = new Intl.ListFormat(); + +assert.sameValue("", lf.format(undefined)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable.js new file mode 100644 index 0000000000..8b34bcb16c --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/iterable.js @@ -0,0 +1,47 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.format(). +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let error be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, error). + iii. Append nextValue to the end of the List list. + 6. Return list. +features: [Intl.ListFormat] +---*/ + +let lf = new Intl.ListFormat(); + +// Test the success case. +let iterable_of_strings = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++ + if (this.count < 4) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +lf.format(iterable_of_strings); +assert.sameValue(iterable_of_strings.count, 4); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/length.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/length.js new file mode 100644 index 0000000000..d4432129d6 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the "length" property of Intl.ListFormat.prototype.format(). +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 ListFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.prototype.format, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/name.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/name.js new file mode 100644 index 0000000000..fe190330c9 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/name.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: sec-Intl.ListFormat.prototype.format +description: > + Checks the "name" property of Intl.ListFormat.prototype.format(). +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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.prototype.format, "name", { + value: "format", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/prop-desc.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/prop-desc.js new file mode 100644 index 0000000000..0df402136f --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the "format" property of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype.format ([ list ]) + + 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. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +assert.sameValue( + typeof Intl.ListFormat.prototype.format, + "function", + "typeof Intl.ListFormat.prototype.format is function" +); + +verifyProperty(Intl.ListFormat.prototype, "format", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/format/shell.js b/js/src/tests/test262/intl402/ListFormat/prototype/format/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/format/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/branding.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/branding.js new file mode 100644 index 0000000000..6b7473cb0e --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/branding.js @@ -0,0 +1,29 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Verifies the branding check for the "formatToParts" function of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype.formatToParts([ list ]) + + 2. If Type(lf) is not Object, throw a TypeError exception. + 3. If lf does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. +features: [Intl.ListFormat] +---*/ + +const formatToParts = Intl.ListFormat.prototype.formatToParts; + +assert.sameValue(typeof formatToParts, "function"); +assert.throws(TypeError, () => formatToParts.call(undefined), "undefined"); +assert.throws(TypeError, () => formatToParts.call(null), "null"); +assert.throws(TypeError, () => formatToParts.call(true), "true"); +assert.throws(TypeError, () => formatToParts.call(""), "empty string"); +assert.throws(TypeError, () => formatToParts.call(Symbol()), "symbol"); +assert.throws(TypeError, () => formatToParts.call(1), "1"); +assert.throws(TypeError, () => formatToParts.call({}), "plain object"); +assert.throws(TypeError, () => formatToParts.call(Intl.ListFormat), "Intl.ListFormat"); +assert.throws(TypeError, () => formatToParts.call(Intl.ListFormat.prototype), "Intl.ListFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/browser.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-default.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-default.js new file mode 100644 index 0000000000..fc0cb7e7d4 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-default.js @@ -0,0 +1,89 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US"); + +assert.sameValue(typeof lf.formatToParts, "function", "formatToParts should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " and " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", and " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": ", and " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": ", and " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-disjunction.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-disjunction.js new file mode 100644 index 0000000000..10756cb443 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-disjunction.js @@ -0,0 +1,89 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { "type": "disjunction", }); + +assert.sameValue(typeof lf.formatToParts, "function", "formatToParts should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " or " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", or " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": ", or " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": ", or " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-narrow.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-narrow.js new file mode 100644 index 0000000000..405559e49b --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-narrow.js @@ -0,0 +1,92 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { + "style": "narrow", + "type": "unit", +}); + +assert.sameValue(typeof lf.formatToParts, "function", "formatToParts should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-short.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-short.js new file mode 100644 index 0000000000..8934cda502 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-short.js @@ -0,0 +1,91 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { + "style": "short", +}); + +assert.sameValue(typeof lf.formatToParts, "function", "format should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " & " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", & " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": ", & " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": ", & " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-unit.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-unit.js new file mode 100644 index 0000000000..2abe64951a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/en-us-unit.js @@ -0,0 +1,91 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("en-US", { + "type": "unit", +}); + +assert.sameValue(typeof lf.formatToParts, "function", "format should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-long.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-long.js new file mode 100644 index 0000000000..f6332de215 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-long.js @@ -0,0 +1,92 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("es-ES", { + "style": "long", + "type": "unit", +}); + +assert.sameValue(typeof lf.formatToParts, "function", "format should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " y " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": " y " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": " y " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": " y " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-narrow.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-narrow.js new file mode 100644 index 0000000000..ffd14fe622 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-narrow.js @@ -0,0 +1,92 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("es-ES", { + "style": "narrow", + "type": "unit", +}); + +assert.sameValue(typeof lf.formatToParts, "function", "format should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": " " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-short.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-short.js new file mode 100644 index 0000000000..bc996bbcae --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/es-es-short.js @@ -0,0 +1,92 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Intl.ListFormat.prototype.formatToParts() in English. +features: [Intl.ListFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +function CustomIterator(array) { + this.i = 0; + this.array = array; +} + +CustomIterator.prototype[Symbol.iterator] = function() { + return this; +} + +CustomIterator.prototype.next = function() { + if (this.i >= this.array.length) { + return { + "done": true, + }; + } + + return { + "value": this.array[this.i++], + "done": false, + }; +} + +const transforms = [ + a => a, + a => a[Symbol.iterator](), + a => new CustomIterator(a), +]; + +const lf = new Intl.ListFormat("es-ES", { + "style": "short", + "type": "unit", +}); + +assert.sameValue(typeof lf.formatToParts, "function", "format should be supported"); + +for (const f of transforms) { + verifyFormatParts(lf.formatToParts(f([])), []); + verifyFormatParts(lf.formatToParts(f(["foo"])), [ + { "type": "element", "value": "foo" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": " y " }, + { "type": "element", "value": "bar" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + ]); + verifyFormatParts(lf.formatToParts(f(["foo", "bar", "baz", "quux"])), [ + { "type": "element", "value": "foo" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "bar" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "baz" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "quux" }, + ]); +} + +verifyFormatParts(lf.formatToParts("foo"), [ + { "type": "element", "value": "f" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, + { "type": "literal", "value": ", " }, + { "type": "element", "value": "o" }, +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-getiterator-throw.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-getiterator-throw.js new file mode 100644 index 0000000000..2d3583018d --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-getiterator-throw.js @@ -0,0 +1,30 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.formatToParts() while the GetIterator + throws error. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). +features: [Intl.ListFormat] +---*/ + +function CustomError() {} + +let lf = new Intl.ListFormat(); +// Test the failure case. +let get_iterator_throw_error = { + [Symbol.iterator]() { + throw new CustomError(); + } +}; +assert.throws(CustomError, + ()=> {lf.formatToParts(get_iterator_throw_error)}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-invalid.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-invalid.js new file mode 100644 index 0000000000..71e286608b --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-invalid.js @@ -0,0 +1,51 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.formatToParts(). +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let error be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, error). + iii. Append nextValue to the end of the List list. + 6. Return list. +features: [Intl.ListFormat] +---*/ + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterable_of_strings_and_number = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++; + if (this.count == 3) { + return {done:false, value: 3}; + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(TypeError, + ()=> {lf.formatToParts(iterable_of_strings_and_number)}, + "Iterable yielded 3 which is not a string"); +assert.sameValue(iterable_of_strings_and_number.count, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorclose.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorclose.js new file mode 100644 index 0000000000..07912d085a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorclose.js @@ -0,0 +1,58 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.formatToParts() and check the IteratorClose + calls return. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let error be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, error). + iii. Append nextValue to the end of the List list. + 6. Return list. +features: [Intl.ListFormat] +---*/ + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterator_close_call_return = { + [Symbol.iterator]() { + return this; + }, + "return"() { + this.returnIsCalled = true; + assert.sameValue(this.count, 3); + }, + count: 0, + returnIsCalled: false, + next() { + this.count++; + if (this.count == 3) { + return {done:false, value: 3}; + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(TypeError, + ()=> {lf.formatToParts(iterator_close_call_return)}, + "Iterable yielded 3 which is not a string"); +assert.sameValue(iterator_close_call_return.count, 3); +assert.sameValue(iterator_close_call_return.returnIsCalled, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorstep-throw.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorstep-throw.js new file mode 100644 index 0000000000..7edbce28da --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorstep-throw.js @@ -0,0 +1,45 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.formatToParts() while iteratorStep throws error. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). +features: [Intl.ListFormat] +---*/ + +function CustomError() {} + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterator_step_throw = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++; + if (this.count == 3) { + throw new CustomError(); + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(CustomError, + ()=> {lf.formatToParts(iterator_step_throw)}); +assert.sameValue(iterator_step_throw.count, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorvalue-throw.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorvalue-throw.js new file mode 100644 index 0000000000..000da967e1 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-iteratorvalue-throw.js @@ -0,0 +1,47 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.formatToParts() while iteratorValue throws error. +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). +features: [Intl.ListFormat] +---*/ + +function CustomError() {} + +let lf = new Intl.ListFormat(); +// Test the failure case. +let iterator_value_throw = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++; + if (this.count == 3) { + return {done: false, get value() { throw new CustomError() }}; + } + if (this.count < 5) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +assert.throws(CustomError, + ()=> {lf.formatToParts(iterator_value_throw)}); +assert.sameValue(iterator_value_throw.count, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-undefined.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-undefined.js new file mode 100644 index 0000000000..b5b66041f4 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable-undefined.js @@ -0,0 +1,21 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.format +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.formatToParts(undefined). +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. +features: [Intl.ListFormat] +includes: [compareArray.js] +---*/ + +let lf = new Intl.ListFormat(); + +assert(compareArray([], lf.formatToParts(undefined))); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable.js new file mode 100644 index 0000000000..053a30c2b9 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/iterable.js @@ -0,0 +1,47 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the behavior of Abstract Operation StringListFromIterable + called by Intl.ListFormat.prototype.formatToParts(). +info: | + StringListFromIterable + 1. If iterable is undefined, then + a. Return a new empty List. + 2. Let iteratorRecord be ? GetIterator(iterable). + 3. Let list be a new empty List. + 4. Let next be true. + 5. Repeat, while next is not false + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let error be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, error). + iii. Append nextValue to the end of the List list. + 6. Return list. +features: [Intl.ListFormat] +---*/ + +let lf = new Intl.ListFormat(); + +// Test the success case. +let iterable_of_strings = { + [Symbol.iterator]() { + return this; + }, + count: 0, + next() { + this.count++ + if (this.count < 4) { + return {done: false, value: String(this.count)}; + } + return {done:true} + } +}; +lf.formatToParts(iterable_of_strings); +assert.sameValue(iterable_of_strings.count, 4); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/length.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/length.js new file mode 100644 index 0000000000..fe1298ea4a --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the "length" property of Intl.ListFormat.prototype.formatToParts(). +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 ListFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.prototype.formatToParts, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/name.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/name.js new file mode 100644 index 0000000000..f63e7662d4 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/name.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: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the "name" property of Intl.ListFormat.prototype.formatToParts(). +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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.prototype.formatToParts, "name", { + value: "formatToParts", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/prop-desc.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/prop-desc.js new file mode 100644 index 0000000000..4e94bd8a27 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.formatToParts +description: > + Checks the "formatToParts" property of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype.formatToParts () + + 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. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +assert.sameValue( + typeof Intl.ListFormat.prototype.formatToParts, + "function", + "typeof Intl.ListFormat.prototype.formatToParts is function" +); + +verifyProperty(Intl.ListFormat.prototype, "formatToParts", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/shell.js b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/formatToParts/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/prop-desc.js b/js/src/tests/test262/intl402/ListFormat/prototype/prop-desc.js new file mode 100644 index 0000000000..ee5b1cc868 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/prop-desc.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype +description: > + Checks the "prototype" property of the ListFormat constructor. +info: | + Intl.ListFormat.prototype + + The value of Intl.ListFormat.prototype is %ListFormatPrototype%. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/branding.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/branding.js new file mode 100644 index 0000000000..bec62d5492 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/branding.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.resolvedOptions +description: Verifies the branding check for the "resolvedOptions" function of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype.resolvedOptions() + + 2. If Type(pr) is not Object, throw a TypeError exception. + 3. If pr does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. +features: [Intl.ListFormat] +---*/ + +const resolvedOptions = Intl.ListFormat.prototype.resolvedOptions; + +assert.sameValue(typeof resolvedOptions, "function"); +assert.throws(TypeError, () => resolvedOptions.call(undefined), "undefined"); +assert.throws(TypeError, () => resolvedOptions.call(null), "null"); +assert.throws(TypeError, () => resolvedOptions.call(true), "true"); +assert.throws(TypeError, () => resolvedOptions.call(""), "empty string"); +assert.throws(TypeError, () => resolvedOptions.call(Symbol()), "symbol"); +assert.throws(TypeError, () => resolvedOptions.call(1), "1"); +assert.throws(TypeError, () => resolvedOptions.call({}), "plain object"); +assert.throws(TypeError, () => resolvedOptions.call(Intl.ListFormat), "Intl.ListFormat"); +assert.throws(TypeError, () => resolvedOptions.call(Intl.ListFormat.prototype), "Intl.ListFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/caching.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/caching.js new file mode 100644 index 0000000000..7570e6eb66 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/caching.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: sec-Intl.ListFormat.prototype.resolvedOptions +description: Verifies that the return value of Intl.ListFormat.prototype.resolvedOptions() is not cached. +info: | + Intl.ListFormat.prototype.resolvedOptions () + + 4. Let options be ! ObjectCreate(%ObjectPrototype%). +features: [Intl.ListFormat] +---*/ + +const lf = new Intl.ListFormat("en-us"); +const options1 = lf.resolvedOptions(); +const options2 = lf.resolvedOptions(); +assert.notSameValue(options1, options2, "Should create a new object each time."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..e613f177d8 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/length.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: sec-Intl.ListFormat.prototype.resolvedOptions +description: Checks the "length" property of Intl.ListFormat.prototype.resolvedOptions(). +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 ListFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.prototype.resolvedOptions, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..22303e2d66 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/name.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: sec-Intl.ListFormat.prototype.resolvedOptions +description: Checks the "name" property of Intl.ListFormat.prototype.resolvedOptions(). +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 }. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +verifyProperty(Intl.ListFormat.prototype.resolvedOptions, "name", { + value: "resolvedOptions", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/order.js new file mode 100644 index 0000000000..f71c0489b3 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/order.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: sec-Intl.ListFormat.prototype.resolvedOptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [compareArray.js] +features: [Intl.ListFormat] +---*/ + +const options = new Intl.ListFormat().resolvedOptions(); + +const expected = [ + "locale", + "type", + "style", +]; + +assert.compareArray(Object.getOwnPropertyNames(options), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..59592c918d --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.resolvedOptions +description: Checks the "resolvedOptions" property of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype.resolvedOptions () + + 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. +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +assert.sameValue( + typeof Intl.ListFormat.prototype.resolvedOptions, + "function", + "typeof Intl.ListFormat.prototype.resolvedOptions is function" +); + +verifyProperty(Intl.ListFormat.prototype, "resolvedOptions", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/type.js b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/type.js new file mode 100644 index 0000000000..e7ee1bd377 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/resolvedOptions/type.js @@ -0,0 +1,42 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.ListFormat.prototype.resolvedOptions +description: Checks the properties of the result of Intl.ListFormat.prototype.resolvedOptions(). +info: | + Intl.ListFormat.prototype.resolvedOptions () + + 4. Let options be ! ObjectCreate(%ObjectPrototype%). + 5. For each row of Table 1, except the header row, do + d. Perform ! CreateDataPropertyOrThrow(options, p, v). +includes: [propertyHelper.js] +features: [Intl.ListFormat] +---*/ + +const lf = new Intl.ListFormat("en-us", { "style": "short", "type": "unit" }); +const options = lf.resolvedOptions(); +assert.sameValue(Object.getPrototypeOf(options), Object.prototype, "Prototype"); + +verifyProperty(options, "locale", { + value: "en-US", + writable: true, + enumerable: true, + configurable: true, +}); + +verifyProperty(options, "type", { + value: "unit", + writable: true, + enumerable: true, + configurable: true, +}); + +verifyProperty(options, "style", { + value: "short", + writable: true, + enumerable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/shell.js b/js/src/tests/test262/intl402/ListFormat/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/toString.js new file mode 100644 index 0000000000..ee0a3b462b --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/toString.js @@ -0,0 +1,18 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.ListFormat.prototype-@@tostringtag +description: > + Checks Object.prototype.toString with Intl.ListFormat objects. +info: | + Intl.ListFormat.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.ListFormat". +features: [Intl.ListFormat] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.ListFormat.prototype), "[object Intl.ListFormat]"); +assert.sameValue(Object.prototype.toString.call(new Intl.ListFormat()), "[object Intl.ListFormat]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/toStringTag.js new file mode 100644 index 0000000000..af1303f1c5 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/prototype/toStringTag/toStringTag.js @@ -0,0 +1,25 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.ListFormat.prototype-@@tostringtag +description: > + Checks the @@toStringTag property of the ListFormat prototype object. +info: | + Intl.ListFormat.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.ListFormat". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.ListFormat, Symbol.toStringTag] +---*/ + +verifyProperty(Intl.ListFormat.prototype, Symbol.toStringTag, { + value: "Intl.ListFormat", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/ListFormat/shell.js b/js/src/tests/test262/intl402/ListFormat/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/ListFormat/shell.js diff --git a/js/src/tests/test262/intl402/Locale/browser.js b/js/src/tests/test262/intl402/Locale/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/browser.js diff --git a/js/src/tests/test262/intl402/Locale/canonicalize-locale-list-take-locale.js b/js/src/tests/test262/intl402/Locale/canonicalize-locale-list-take-locale.js new file mode 100644 index 0000000000..1f20ba61fb --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/canonicalize-locale-list-take-locale.js @@ -0,0 +1,55 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies CanonicalizeLocaleList will take Intl.Locale as locales. +info: | + CanonicalizeLocaleList ( locales ) + 3. If Type(locales) is String or locales has an [[InitializedLocale]] internal slot, then + a. Let O be CreateArrayFromList(« locales »). + + c. iii. If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then + 1. Let tag be kValue.[[Locale]]. + iv. Else, + 1. Let tag be ? ToString(kValue). +features: [Intl.Locale] +---*/ + +const tag = "ar"; +const tag2 = "fa"; +const tag3 = "zh"; +const loc = new Intl.Locale(tag); + +// Monkey-patching Intl.Locale +class PatchedLocale extends Intl.Locale { + constructor(tag, options) { + super(tag, options); + } + toString() { + // this should NOT get called. + assert(false, "toString should not be called") + } +} +const ploc = new PatchedLocale(tag2); + +// Test Intl.Locale as the only argument +let res = Intl.getCanonicalLocales(loc); +assert.sameValue(res.length, 1); +assert.sameValue(res[0], tag); + +// Test Monkey-patched Intl.Locale as the only argument +res = Intl.getCanonicalLocales(ploc); +assert.sameValue(res.length, 1); +assert.sameValue(res[0], tag2); + +// Test Intl.Locale and the Monkey-patched one are in +// array. +res = Intl.getCanonicalLocales([loc, tag3, ploc]); +assert.sameValue(res.length, 3); +assert.sameValue(res[0], tag); +assert.sameValue(res[1], tag3); +assert.sameValue(res[2], tag2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-apply-options-canonicalizes-twice.js b/js/src/tests/test262/intl402/Locale/constructor-apply-options-canonicalizes-twice.js new file mode 100644 index 0000000000..e6d3f9a8b4 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-apply-options-canonicalizes-twice.js @@ -0,0 +1,28 @@ +// Copyright 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-apply-options-to-tag +description: > + ApplyOptionsToTag canonicalises the language tag two times. +info: | + 10.1.1 ApplyOptionsToTag( tag, options ) + + ... + 9. Set tag to CanonicalizeUnicodeLocaleId(tag). + 10. If language is not undefined, + ... + b. Set tag to tag with the substring corresponding to the unicode_language_subtag + production of the unicode_language_id replaced by the string language. + ... + 13. Return CanonicalizeUnicodeLocaleId(tag). +features: [Intl.Locale] +---*/ + +// ApplyOptionsToTag canonicalises the locale identifier before applying the +// options. That means "und-Armn-SU" is first canonicalised to "und-Armn-AM", +// then the language is changed to "ru". If "ru" were applied first, the result +// would be "ru-Armn-RU" instead. +assert.sameValue(new Intl.Locale("und-Armn-SU", {language: "ru"}).toString(), "ru-Armn-AM"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-getter-order.js b/js/src/tests/test262/intl402/Locale/constructor-getter-order.js new file mode 100644 index 0000000000..4948f22480 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-getter-order.js @@ -0,0 +1,127 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the order of evaluations of arguments and options for the Locale + constructor. +features: [Intl.Locale] +includes: [compareArray.js] +---*/ + +const order = []; +new Intl.Locale( + { toString() { order.push("tag toString"); return "en"; } }, + { + get language() { + order.push("get language"); + return { + toString() { + order.push("toString language"); + return "de"; + } + } + }, + + get script() { + order.push("get script"); + return { + toString() { + order.push("toString script"); + return "Latn"; + } + } + }, + + get region() { + order.push("get region"); + return { + toString() { + order.push("toString region"); + return "DE"; + } + } + }, + + get calendar() { + order.push("get calendar"); + return { + toString() { + order.push("toString calendar"); + return "gregory"; + } + } + }, + + get collation() { + order.push("get collation"); + return { + toString() { + order.push("toString collation"); + return "zhuyin"; + } + } + }, + + get hourCycle() { + order.push("get hourCycle"); + return { + toString() { + order.push("toString hourCycle"); + return "h24"; + } + } + }, + + get caseFirst() { + order.push("get caseFirst"); + return { + toString() { + order.push("toString caseFirst"); + return "upper"; + } + } + }, + + get numeric() { + order.push("get numeric"); + return false; + }, + + get numberingSystem() { + order.push("get numberingSystem"); + return { + toString() { + order.push("toString numberingSystem"); + return "latn"; + } + } + }, + } +); + +const expected_order = [ + "tag toString", + "get language", + "toString language", + "get script", + "toString script", + "get region", + "toString region", + "get calendar", + "toString calendar", + "get collation", + "toString collation", + "get hourCycle", + "toString hourCycle", + "get caseFirst", + "toString caseFirst", + "get numeric", + "get numberingSystem", + "toString numberingSystem" +]; + +assert.compareArray(order, expected_order); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-locale-object.js b/js/src/tests/test262/intl402/Locale/constructor-locale-object.js new file mode 100644 index 0000000000..11760b13c8 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-locale-object.js @@ -0,0 +1,39 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies canonicalization of specific tags. +info: | + ApplyOptionsToTag( tag, options ) + 10. Return CanonicalizeLanguageTag(tag). +features: [Intl.Locale] +---*/ + +// Pass Intl.Locale object and replace subtag. +const enUS = new Intl.Locale("en-US"); +const enGB = new Intl.Locale(enUS, {region: "GB"}); + +assert.sameValue(enUS.toString(), "en-US", 'enUS.toString() returns "en-US"'); +assert.sameValue(enGB.toString(), "en-GB", 'enGB.toString() returns "en-GB"'); + +// Pass Intl.Locale object and replace Unicode extension keyword. +const zhUnihan = new Intl.Locale("zh-u-co-unihan"); +const zhZhuyin = new Intl.Locale(zhUnihan, {collation: "zhuyin"}); + +assert.sameValue( + zhUnihan.toString(), + "zh-u-co-unihan", + 'zhUnihan.toString() returns "zh-u-co-unihan"' +); +assert.sameValue( + zhZhuyin.toString(), + "zh-u-co-zhuyin", + 'zhZhuyin.toString() returns "zh-u-co-zhuyin"' +); + +assert.sameValue(zhUnihan.collation, "unihan", 'The value of zhUnihan.collation is "unihan"'); +assert.sameValue(zhZhuyin.collation, "zhuyin", 'The value of zhZhuyin.collation is "zhuyin"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-newtarget-undefined.js b/js/src/tests/test262/intl402/Locale/constructor-newtarget-undefined.js new file mode 100644 index 0000000000..c63fc1c044 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-newtarget-undefined.js @@ -0,0 +1,25 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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.sameValue(typeof Intl.Locale, "function"); + +assert.throws(TypeError, function() { + Intl.Locale(); +}, 'Intl.Locale() throws TypeError'); + +assert.throws(TypeError, function() { + Intl.Locale("en"); +}, 'Intl.Locale("en") throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-non-iana-canon.js b/js/src/tests/test262/intl402/Locale/constructor-non-iana-canon.js new file mode 100644 index 0000000000..cb4444885d --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-non-iana-canon.js @@ -0,0 +1,111 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies canonicalization, minimization and maximization of specific tags. +info: | + ApplyOptionsToTag( tag, options ) + 10. Return CanonicalizeLanguageTag(tag). + + Intl.Locale.prototype.maximize () + 3. Let maximal be the result of the Add Likely Subtags algorithm applied to loc.[[Locale]]. + + Intl.Locale.prototype.minimize () + 3. Let minimal be the result of the Remove Likely Subtags algorithm applied to loc.[[Locale]]. +features: [Intl.Locale] +---*/ + +// Test some language tags where we know that either CLDR or ICU produce +// different results compared to the canonicalization specified in RFC 5646. +var testData = [ + { + tag: "mo", + canonical: "ro", + maximized: "ro-Latn-RO", + }, + { + tag: "es-ES-preeuro", + maximized: "es-Latn-ES-preeuro", + minimized: "es-preeuro", + }, + { + tag: "uz-UZ-cyrillic", + maximized: "uz-Latn-UZ-cyrillic", + minimized: "uz-cyrillic", + }, + { + tag: "posix", + }, + { + tag: "hi-direct", + maximized: "hi-Deva-IN-direct", + }, + { + tag: "zh-pinyin", + maximized: "zh-Hans-CN-pinyin", + }, + { + tag: "zh-stroke", + maximized: "zh-Hans-CN-stroke", + }, + { + tag: "aar-x-private", + // "aar" should be canonicalized into "aa" because "aar" matches the type attribute of + // a languageAlias element in + // https://www.unicode.org/repos/cldr/trunk/common/supplemental/supplementalMetadata.xml + canonical: "aa-x-private", + maximized: "aa-Latn-ET-x-private", + }, + { + tag: "heb-x-private", + // "heb" should be canonicalized into "he" because "heb" matches the type attribute of + // a languageAlias element in + // https://www.unicode.org/repos/cldr/trunk/common/supplemental/supplementalMetadata.xml + canonical: "he-x-private", + maximized: "he-Hebr-IL-x-private", + }, + { + tag: "de-u-kf", + maximized: "de-Latn-DE-u-kf", + }, + { + tag: "ces", + // "ces" should be canonicalized into "cs" because "ces" matches the type attribute of + // a languageAlias element in + // https://www.unicode.org/repos/cldr/trunk/common/supplemental/supplementalMetadata.xml + canonical: "cs", + maximized: "cs-Latn-CZ", + }, + { + tag: "hy-arevela", + canonical: "hy", + maximized: "hy-Armn-AM", + }, + { + tag: "hy-arevmda", + canonical: "hyw", + }, +]; + +for (const {tag, canonical = tag, maximized = canonical, minimized = canonical} of testData) { + const loc = new Intl.Locale(tag); + assert.sameValue( + new Intl.Locale(tag).toString(), + canonical, + `new Intl.Locale("${tag}").toString() returns "${canonical}"` + ); + assert.sameValue( + new Intl.Locale(tag).maximize().toString(), + maximized, + `new Intl.Locale("${tag}").maximize().toString() returns "${maximized}"` + ); + assert.sameValue( + new Intl.Locale(tag).minimize().toString(), + minimized, + `new Intl.Locale("${tag}").minimize().toString() returns "${minimized}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-calendar-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-calendar-invalid.js new file mode 100644 index 0000000000..0ac2861b99 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-calendar-invalid.js @@ -0,0 +1,38 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale + constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 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. + +features: [Intl.Locale] +---*/ + + +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + calendar = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidCalendarOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", +]; +for (const calendar of invalidCalendarOptions) { + assert.throws(RangeError, function() { + new Intl.Locale("en", {calendar}); + }, `new Intl.Locale("en", {calendar: "${calendar}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-calendar-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-calendar-valid.js new file mode 100644 index 0000000000..4a1049bf7a --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-calendar-valid.js @@ -0,0 +1,43 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale + constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 14. Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined). + ... + +features: [Intl.Locale] +---*/ + +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 [calendar, expected] of validCalendarOptions) { + assert.sameValue( + new Intl.Locale('en', { calendar }).toString(), + expected, + `new Intl.Locale('en', { calendar: "${calendar}" }).toString() returns "${expected}"` + ); + assert.sameValue( + new Intl.Locale('en-u-ca-gregory', { calendar }).toString(), + expected, + `new Intl.Locale('en-u-ca-gregory', { calendar: "${calendar}" }).toString() returns "${expected}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-canonicalized.js b/js/src/tests/test262/intl402/Locale/constructor-options-canonicalized.js new file mode 100644 index 0000000000..6019635f15 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-canonicalized.js @@ -0,0 +1,71 @@ +// Copyright 2020 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-resolvelocale +description: > + Values provided as properties of the options-argument to the Locale + constructor are converted to canonical form. +info: | + ResolveLocale ( availableLocales, requestedLocales, options, relevantExtensionKeys, localeData ) + + ... + 9.i.iii.1. Let optionsValue be the string optionsValue after performing the algorithm steps to transform Unicode extension values to canonical syntax per Unicode Technical Standard #35 LDML § 3.2.1 Canonical Unicode Locale Identifiers, treating key as ukey and optionsValue as uvalue productions. + 9.i.iii.2. Let optionsValue be the string optionsValue after performing the algorithm steps to replace Unicode extension values with their canonical form per Unicode Technical Standard #35 LDML § 3.2.1 Canonical Unicode Locale Identifiers, treating key as ukey and optionsValue as uvalue productions. + ... + +features: [Intl.Locale] +---*/ + +const keyValueTests = [ + { + key: "ca", + option: "calendar", + tests: [ + ["islamicc", "islamic-civil"], + ["ethiopic-amete-alem", "ethioaa"], + ], + }, +]; + +for (const { key, option, tests } of keyValueTests) { + for (const [noncanonical, canonical] of tests) { + let canonicalInLocale = + new Intl.Locale(`en-u-${key}-${canonical}`); + + assert.sameValue( + canonicalInLocale[option], + canonical, + `new Intl.Locale("en-u-${key}-${canonical}").${option} returns ${canonical}` + ); + + let canonicalInOption = + new Intl.Locale(`en`, { [option]: canonical }); + + assert.sameValue( + canonicalInOption[option], + canonical, + `new Intl.Locale("en", { ${option}: "${canonical}" }).${option} returns ${canonical}` + ); + + let noncanonicalInLocale = + new Intl.Locale(`en-u-${key}-${noncanonical}`); + + assert.sameValue( + noncanonicalInLocale[option], + canonical, + `new Intl.Locale("en-u-${key}-${noncanonical}").${option} returns ${canonical}` + ); + + let noncanonicalInOption = + new Intl.Locale(`en`, { [option]: noncanonical }); + + assert.sameValue( + noncanonicalInOption[option], + canonical, + `new Intl.Locale("en", { ${option}: "${noncanonical}" }).${option} returns ${canonical}` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-casefirst-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-casefirst-invalid.js new file mode 100644 index 0000000000..e15c14c45c --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-casefirst-invalid.js @@ -0,0 +1,39 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 22. Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined). + ... + + GetOption ( options, property, type, values, fallback ) + ... + 2. d. If values is not undefined, then + i. If values does not contain an element equal to value, throw a RangeError exception. + ... +features: [Intl.Locale] +---*/ + + +const invalidCaseFirstOptions = [ + "", + "u", + "Upper", + "upper\0", + "uppercase", + "true", + { valueOf() { return false; } }, +]; +for (const caseFirst of invalidCaseFirstOptions) { + assert.throws(RangeError, function() { + new Intl.Locale("en", {caseFirst}); + }, `new Intl.Locale("en", {caseFirst: "${caseFirst}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-casefirst-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-casefirst-valid.js new file mode 100644 index 0000000000..fc5b837c64 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-casefirst-valid.js @@ -0,0 +1,68 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks valid cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 22. Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined). + 23. Set opt.[[kf]] to kf. + ... + 30. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). + ... + + ApplyUnicodeExtensionToTag( tag, options, relevantExtensionKeys ) + + ... + 8. Let locale be the String value that is tag with all Unicode locale extension sequences removed. + 9. Let newExtension be ! CanonicalizeUnicodeExtension(attributes, keywords). + 10. If newExtension is not the empty String, then + a. Let locale be ! InsertUnicodeExtension(locale, newExtension). + ... + + CanonicalizeUnicodeExtension( attributes, keywords ) + ... + 4. Repeat for each element entry of keywords in List order, + a. Let keyword be entry.[[Key]]. + b. If entry.[[Value]] is not the empty String, then + i. Let keyword be the string-concatenation of keyword, "-", and entry.[[Value]]. + c. Append keyword to fullKeywords. + ... +features: [Intl.Locale] +---*/ + +const validCaseFirstOptions = [ + "upper", + "lower", + "false", + false, + { toString() { return false; } }, +]; +for (const caseFirst of validCaseFirstOptions) { + const expected = String(caseFirst); + let expect = "en-u-kf-" + expected; + assert.sameValue( + new Intl.Locale('en', { caseFirst }).toString(), + expect, + `new Intl.Locale("en", { caseFirst: "${caseFirst}" }).toString() returns "${expect}"` + ); + + expect = "en-u-kf-" + expected; + assert.sameValue( + new Intl.Locale('en-u-kf-lower', { caseFirst }).toString(), + expect, + `new Intl.Locale("en-u-kf-lower", { caseFirst: "${caseFirst}" }).toString() returns "${expect}"` + ); + + assert.sameValue( + new Intl.Locale('en-u-kf-lower', { caseFirst }).caseFirst, + expected, + `new Intl.Locale("en-u-kf-lower", { caseFirst }).caseFirst equals "${expected}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-collation-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-collation-invalid.js new file mode 100644 index 0000000000..d256093257 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-collation-invalid.js @@ -0,0 +1,36 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 18. If collation is not undefined, then + a. If collation does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception. + +features: [Intl.Locale] +---*/ + + +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + collation = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidCollationOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", +]; +for (const invalidCollationOption of invalidCollationOptions) { + assert.throws(RangeError, function() { + new Intl.Locale("en", {collation: invalidCollationOption}); + }, '`new Intl.Locale("en", {collation: invalidCollationOption})` throws RangeError'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-collation-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-collation-valid.js new file mode 100644 index 0000000000..e9bf3077a2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-collation-valid.js @@ -0,0 +1,64 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks valid cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 17. Let collation be ? GetOption(options, "collation", "string", undefined, undefined). + ... + 19. Set opt.[[co]] to collation. + ... + 30. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). + ... + + ApplyUnicodeExtensionToTag( tag, options, relevantExtensionKeys ) + + ... + 8. Let locale be the String value that is tag with all Unicode locale extension sequences removed. + 9. Let newExtension be ! CanonicalizeUnicodeExtension(attributes, keywords). + 10. If newExtension is not the empty String, then + a. Let locale be ! InsertUnicodeExtension(locale, newExtension). + ... + + CanonicalizeUnicodeExtension( attributes, keywords ) + ... + 4. Repeat for each element entry of keywords in List order, + a. Let keyword be entry.[[Key]]. + b. If entry.[[Value]] is not the empty String, then + i. Let keyword be the string-concatenation of keyword, "-", and entry.[[Value]]. + c. Append keyword to fullKeywords. + ... +features: [Intl.Locale] +---*/ + +const validCollationOptions = [ + ["abc", "en-u-co-abc"], + ["abcd", "en-u-co-abcd"], + ["abcde", "en-u-co-abcde"], + ["abcdef", "en-u-co-abcdef"], + ["abcdefg", "en-u-co-abcdefg"], + ["abcdefgh", "en-u-co-abcdefgh"], + ["12345678", "en-u-co-12345678"], + ["1234abcd", "en-u-co-1234abcd"], + ["1234abcd-abc123", "en-u-co-1234abcd-abc123"], +]; +for (const [collation, expected] of validCollationOptions) { + assert.sameValue( + new Intl.Locale('en', {collation}).toString(), + expected, + `new Intl.Locale('en', {collation: "${collation}"}).toString() returns "${expected}"` + ); + + assert.sameValue( + new Intl.Locale('en-u-co-gregory', {collation}).toString(), + expected, + `new Intl.Locale('en-u-co-gregory', {collation: "${collation}"}).toString() returns "${expected}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-hourcycle-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-hourcycle-invalid.js new file mode 100644 index 0000000000..a266bbb7b1 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-hourcycle-invalid.js @@ -0,0 +1,45 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 20. Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined). + ... + + GetOption ( options, property, type, values, fallback ) + ... + 2. d. If values is not undefined, then + i. If values does not contain an element equal to value, throw a RangeError exception. + ... +features: [Intl.Locale] +---*/ + + +const invalidHourCycleOptions = [ + "", + "h", + "h00", + "h01", + "h10", + "h13", + "h22", + "h25", + "h48", + "h012", + "h120", + "h12\0", + "H12", +]; +for (const hourCycle of invalidHourCycleOptions) { + assert.throws(RangeError, function() { + new Intl.Locale("en", {hourCycle}); + }, `new Intl.Locale("en", {hourCycle: "${hourCycle}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-hourcycle-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-hourcycle-valid.js new file mode 100644 index 0000000000..f314ce23ff --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-hourcycle-valid.js @@ -0,0 +1,74 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks valid cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 20. Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined). + 21. Set opt.[[hc]] to hc. + ... + 30. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). + ... + + ApplyUnicodeExtensionToTag( tag, options, relevantExtensionKeys ) + + ... + 8. Let locale be the String value that is tag with all Unicode locale extension sequences removed. + 9. Let newExtension be ! CanonicalizeUnicodeExtension(attributes, keywords). + 10. If newExtension is not the empty String, then + a. Let locale be ! InsertUnicodeExtension(locale, newExtension). + ... + + CanonicalizeUnicodeExtension( attributes, keywords ) + ... + 4. Repeat for each element entry of keywords in List order, + a. Let keyword be entry.[[Key]]. + b. If entry.[[Value]] is not the empty String, then + i. Let keyword be the string-concatenation of keyword, "-", and entry.[[Value]]. + c. Append keyword to fullKeywords. + ... +features: [Intl.Locale] +---*/ + +const validHourCycleOptions = [ + 'h11', + 'h12', + 'h23', + 'h24', + { toString() { return 'h24'; } }, +]; +for (const hourCycle of validHourCycleOptions) { + const expected = String(hourCycle); + let expect = 'en-u-hc-' + expected; + + assert.sameValue( + new Intl.Locale('en', {hourCycle}).toString(), + expect, + `new Intl.Locale("en", {hourCycle: "${hourCycle}"}).toString() returns "${expect}"` + ); + + assert.sameValue( + new Intl.Locale('en-u-hc-h00', {hourCycle}).toString(), + expect, + `new Intl.Locale("en-u-hc-h00", {hourCycle: "${hourCycle}"}).toString() returns "${expect}"` + ); + + assert.sameValue( + new Intl.Locale('en-u-hc-h12', {hourCycle}).toString(), + expect, + `new Intl.Locale("en-u-hc-h12", {hourCycle: "${hourCycle}"}).toString() returns "${expect}"` + ); + + assert.sameValue( + new Intl.Locale('en-u-hc-h00', {hourCycle}).hourCycle, + expected, + `new Intl.Locale("en-u-hc-h00", {hourCycle: "${hourCycle}"}).hourCycle equals "${expected}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-language-grandfathered.js b/js/src/tests/test262/intl402/Locale/constructor-options-language-grandfathered.js new file mode 100644 index 0000000000..0d73349aa2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-language-grandfathered.js @@ -0,0 +1,35 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale + constructor. +info: | + ApplyOptionsToTag( tag, options ) + ... + 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. + b. If language matches the grandfathered production, throw a RangeError exception. + ... + +features: [Intl.Locale] +---*/ + +assert.throws(RangeError, function() { + new Intl.Locale("nb", { + language: "no-bok", + }); +}, `new Intl.Locale("nb", {language: "no-bok"}) throws RangeError`); + +assert.throws(RangeError, function() { + new Intl.Locale("nb", { + language: "no-bok", + region: "NO", + }); +}, `new Intl.Locale("nb", {language: "no-bok", region: "NO"}) throws RangeError`); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-language-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-language-invalid.js new file mode 100644 index 0000000000..512cf1d67e --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-language-invalid.js @@ -0,0 +1,71 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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). + + ApplyOptionsToTag( tag, options ) + ... + 4. If language is not undefined, then + a. If language does not match the language production, throw a RangeError exception. + ... + +features: [Intl.Locale] +---*/ + +/* + 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-min", + "zh-min-nan", + + // Reserved with extended language subtag + "abcd-US", + "abcde-US", + "abcdef-US", + "abcdefg-US", + "abcdefgh-US", + + 7, +]; +for (const language of invalidLanguageOptions) { + assert.throws(RangeError, function() { + new Intl.Locale("en", {language}); + }, `new Intl.Locale("en", {language: "${language}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-language-valid-undefined.js b/js/src/tests/test262/intl402/Locale/constructor-options-language-valid-undefined.js new file mode 100644 index 0000000000..c1ef7ef355 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-language-valid-undefined.js @@ -0,0 +1,45 @@ +// Copyright 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verify valid language option values (undefined) +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). + + ApplyOptionsToTag( tag, options ) + + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + ... + + IsStructurallyValidLanguageTag ( locale ) + + The IsStructurallyValidLanguageTag abstract operation verifies that the + locale argument (which must be a String value) + + represents a well-formed Unicode BCP 47 Locale Identifier" as specified in + Unicode Technical Standard 35 section 3.2, or successor, + +features: [Intl.Locale] +---*/ + +assert.sameValue( + new Intl.Locale('en', {language: undefined}).toString(), + 'en', + `new Intl.Locale('en', {language: undefined}).toString() returns "en"` +); + +assert.sameValue( + new Intl.Locale('en-US', {language: undefined}).toString(), + 'en-US', + `new Intl.Locale('en-US', {language: undefined}).toString() returns "en-US"` +); + +assert.throws(RangeError, () => new Intl.Locale('en-els', {language: undefined})); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-language-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-language-valid.js new file mode 100644 index 0000000000..0f1f0b1e32 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-language-valid.js @@ -0,0 +1,68 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verify valid language option values (various) +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). + + 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 unicode_language_subtag production, throw a RangeError exception. + + IsStructurallyValidLanguageTag ( locale ) + + The IsStructurallyValidLanguageTag abstract operation verifies that the + locale argument (which must be a String value) + + represents a well-formed Unicode BCP 47 Locale Identifier" as specified in + Unicode Technical Standard 35 section 3.2, or successor, + +features: [Intl.Locale] +---*/ + +const validLanguageOptions = [ + [{ toString() { return 'de' } }, 'de'], +]; +for (const [language, expected] of validLanguageOptions) { + let expect = expected || 'en'; + + assert.sameValue( + new Intl.Locale('en', {language}).toString(), + expect, + `new Intl.Locale('en', {language: "${language}"}).toString() returns "${expect}"` + ); + + expect = (expected || 'en') + '-US'; + assert.sameValue( + new Intl.Locale('en-US', {language}).toString(), + expect, + `new Intl.Locale('en-US', {language: "${language}"}).toString() returns "${expect}"` + ); + + assert.throws(RangeError, () => new Intl.Locale('en-els', {language})); + +} + +const invalidLanguageOptions = [ + null, + 'zh-cmn', + 'ZH-CMN', + 'abcd', +]; +for (const language of invalidLanguageOptions) { + assert.throws(RangeError, () => new Intl.Locale('en', {language})); + assert.throws(RangeError, () => new Intl.Locale('en-US', {language})); + assert.throws(RangeError, () => new Intl.Locale('en-els', {language})); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-numberingsystem-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-numberingsystem-invalid.js new file mode 100644 index 0000000000..e3e147447d --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-numberingsystem-invalid.js @@ -0,0 +1,43 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 28. If numberingSystem is not undefined, then + a. If numberingSystem does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception. + +features: [Intl.Locale] +---*/ + + +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + numberingSystem = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidNumberingSystemOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", + "!invalid!", + "-latn-", + "latn-", + "latn--", + "latn-ca", + "latn-ca-", + "latn-ca-gregory", +]; +for (const numberingSystem of invalidNumberingSystemOptions) { + assert.throws(RangeError, function() { + new Intl.Locale('en', {numberingSystem}); + }, `new Intl.Locale("en", {numberingSystem: "${numberingSystem}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-numberingsystem-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-numberingsystem-valid.js new file mode 100644 index 0000000000..6b9cef0c29 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-numberingsystem-valid.js @@ -0,0 +1,63 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks valid cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 27. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined). + ... + 29. Set opt.[[nu]] to numberingSystem. + ... + 30. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). + ... + + ApplyUnicodeExtensionToTag( tag, options, relevantExtensionKeys ) + + ... + 8. Let locale be the String value that is tag with all Unicode locale extension sequences removed. + 9. Let newExtension be ! CanonicalizeUnicodeExtension(attributes, keywords). + 10. If newExtension is not the empty String, then + a. Let locale be ! InsertUnicodeExtension(locale, newExtension). + ... + + CanonicalizeUnicodeExtension( attributes, keywords ) + ... + 4. Repeat for each element entry of keywords in List order, + a. Let keyword be entry.[[Key]]. + b. If entry.[[Value]] is not the empty String, then + i. Let keyword be the string-concatenation of keyword, "-", and entry.[[Value]]. + c. Append keyword to fullKeywords. + ... +features: [Intl.Locale] +---*/ + +const validNumberingSystemOptions = [ + ["abc", "en-u-nu-abc"], + ["abcd", "en-u-nu-abcd"], + ["abcde", "en-u-nu-abcde"], + ["abcdef", "en-u-nu-abcdef"], + ["abcdefg", "en-u-nu-abcdefg"], + ["abcdefgh", "en-u-nu-abcdefgh"], + ["12345678", "en-u-nu-12345678"], + ["1234abcd", "en-u-nu-1234abcd"], + ["1234abcd-abc123", "en-u-nu-1234abcd-abc123"], +]; +for (const [numberingSystem, expected] of validNumberingSystemOptions) { + assert.sameValue( + new Intl.Locale('en', { numberingSystem }).toString(), + expected, + `new Intl.Locale("en", { numberingSystem: ${numberingSystem} }).toString() returns "${expected}"` + ); + assert.sameValue( + new Intl.Locale('en-u-nu-latn', { numberingSystem }).toString(), + expected, + `new Intl.Locale("en-u-nu-latn", { numberingSystem: ${numberingSystem} }).toString() returns "${expected}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-numeric-undefined.js b/js/src/tests/test262/intl402/Locale/constructor-options-numeric-undefined.js new file mode 100644 index 0000000000..d51f2513e4 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-numeric-undefined.js @@ -0,0 +1,56 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: Verifies the behavior of an undefined numeric option to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 24. Let kn be ? GetOption(options, "numeric", "boolean", undefined, undefined). + 25. If kn is not undefined, set kn to ! ToString(kn). + ... + 30. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). + ... + + ApplyUnicodeExtensionToTag( tag, options, relevantExtensionKeys ) + + ... + 8. Let locale be the String value that is tag with all Unicode locale extension sequences removed. + 9. Let newExtension be ! CanonicalizeUnicodeExtension(attributes, keywords). + 10. If newExtension is not the empty String, then + a. Let locale be ! InsertUnicodeExtension(locale, newExtension). + ... + + CanonicalizeUnicodeExtension( attributes, keywords ) + ... + 4. Repeat for each element entry of keywords in List order, + a. Let keyword be entry.[[Key]]. + b. If entry.[[Value]] is not the empty String, then + i. Let keyword be the string-concatenation of keyword, "-", and entry.[[Value]]. + c. Append keyword to fullKeywords. + ... +features: [Intl.Locale] +---*/ + +const options = { numeric: undefined }; +assert.sameValue( + new Intl.Locale('en', options).toString(), + "en", + 'new Intl.Locale("en", {numeric: undefined}).toString() returns "en"' +); + +assert.sameValue( + new Intl.Locale('en-u-kn-true', options).toString(), + "en-u-kn", + 'new Intl.Locale("en-u-kn-true", {numeric: undefined}).toString() returns "en-u-kn"' +); + +assert.sameValue( + new Intl.Locale('en-u-kf-lower', options).numeric, + false, + 'The value of new Intl.Locale("en-u-kf-lower", {numeric: undefined}).numeric equals `false`' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-numeric-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-numeric-valid.js new file mode 100644 index 0000000000..eaa1351961 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-numeric-valid.js @@ -0,0 +1,70 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks valid cases for the options argument to the Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 24. Let kn be ? GetOption(options, "numeric", "boolean", undefined, undefined). + 25. If kn is not undefined, set kn to ! ToString(kn). + ... + 30. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). + ... + + ApplyUnicodeExtensionToTag( tag, options, relevantExtensionKeys ) + + ... + 8. Let locale be the String value that is tag with all Unicode locale extension sequences removed. + 9. Let newExtension be ! CanonicalizeUnicodeExtension(attributes, keywords). + 10. If newExtension is not the empty String, then + a. Let locale be ! InsertUnicodeExtension(locale, newExtension). + ... + + CanonicalizeUnicodeExtension( attributes, keywords ) + ... + 4. Repeat for each element entry of keywords in List order, + a. Let keyword be entry.[[Key]]. + b. If entry.[[Value]] is not the empty String, then + i. Let keyword be the string-concatenation of keyword, "-", and entry.[[Value]]. + c. Append keyword to fullKeywords. + ... +features: [Intl.Locale] +---*/ + +const validNumericOptions = [ + [false, false], + [true, true], + [null, false], + [0, false], + [0.5, true], + ["true", true], + ["false", true], + [{ valueOf() { return false; } }, true], +]; +for (const [numeric, expected] of validNumericOptions) { + let expect = expected ? "en-u-kn" : "en-u-kn-false"; + + assert.sameValue( + new Intl.Locale('en', {numeric}).toString(), + expect, + `new Intl.Locale("en", {numeric: ${numeric}}).toString() returns "${expected}"` + ); + + assert.sameValue( + new Intl.Locale('en-u-kn-true', {numeric}).toString(), + expect, + `new Intl.Locale("en-u-kn-true", {numeric: ${numeric}}).toString() returns "${expected}"` + ); + + assert.sameValue( + new Intl.Locale('en-u-kf-lower', {numeric}).numeric, + expected, + `new Intl.Locale("en-u-kf-lower", {numeric: ${numeric}}).numeric equals "${expected}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-region-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-region-invalid.js new file mode 100644 index 0000000000..5f5444b6b5 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-region-invalid.js @@ -0,0 +1,58 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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). + + ApplyOptionsToTag( tag, options ) + ... + 8. If region is not undefined, then + a. If region does not match the region production, throw a RangeError exception. + ... + +features: [Intl.Locale] +---*/ + +/* + 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 region of invalidRegionOptions) { + assert.throws(RangeError, function() { + new Intl.Locale("en", {region}); + }, `new Intl.Locale("en", {region: "${region}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-region-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-region-valid.js new file mode 100644 index 0000000000..f57fec2226 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-region-valid.js @@ -0,0 +1,69 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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). + + ApplyOptionsToTag( tag, options ) + ... + 7. Let region be ? GetOption(options, "region", "string", undefined, undefined). + ... + 9. If tag matches neither the privateuse nor the grandfathered production, then + ... + d. 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. + +features: [Intl.Locale] +---*/ + +const validRegionOptions = [ + [undefined, undefined], + ['FR', 'en-FR'], + ['554', 'en-NZ'], + [554, 'en-NZ'], +]; +for (const [region, expected] of validRegionOptions) { + let options = { region }; + let expect = expected || 'en'; + + assert.sameValue( + new Intl.Locale('en', options).toString(), + expect, + `new Intl.Locale('en', {region: "${region}"}).toString() returns "${expect}"` + ); + + expect = expected || 'en-US'; + assert.sameValue( + new Intl.Locale('en-US', options).toString(), + expect, + `new Intl.Locale('en-US', {region: "${region}"}).toString() returns "${expect}"` + ); + + expect = (expected || 'en') + '-u-ca-gregory'; + assert.sameValue( + new Intl.Locale('en-u-ca-gregory', options).toString(), + expect, + `new Intl.Locale('en-u-ca-gregory', {region: "${region}"}).toString() returns "${expect}"` + ); + + expect = (expected || 'en-US') + '-u-ca-gregory'; + assert.sameValue( + new Intl.Locale('en-US-u-ca-gregory', options).toString(), + expect, + `new Intl.Locale('en-US-u-ca-gregory', {region: "${region}"}).toString() returns "${expect}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-script-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-options-script-invalid.js new file mode 100644 index 0000000000..01141210d5 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-script-invalid.js @@ -0,0 +1,54 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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). + + ApplyOptionsToTag( tag, options ) + ... + 6. If script is not undefined, then + a. If script does not match the script production, throw a RangeError exception. + ... + +features: [Intl.Locale] +---*/ + +/* + 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 script of invalidScriptOptions) { + assert.throws(RangeError, function() { + new Intl.Locale("en", {script}); + }, `new Intl.Locale("en", {script: "${script}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-script-valid-undefined.js b/js/src/tests/test262/intl402/Locale/constructor-options-script-valid-undefined.js new file mode 100644 index 0000000000..470d865d26 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-script-valid-undefined.js @@ -0,0 +1,50 @@ +// Copyright 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verify valid script option values (undefined) +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). + + ApplyOptionsToTag( tag, options ) + ... + 5. Let script be ? GetOption(options, "script", "string", undefined, undefined). + ... + 9. If tag matches neither the privateuse nor the grandfathered production, then + ... + c. 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. + + +features: [Intl.Locale] +---*/ + +assert.sameValue( + new Intl.Locale('en', {script: undefined}).toString(), + 'en', + `new Intl.Locale('en', {script: undefined}).toString() returns "en"` +); + +assert.sameValue( + new Intl.Locale('en-DK', {script: undefined}).toString(), + 'en-DK', + `new Intl.Locale('en-DK', {script: undefined}).toString() returns "en-DK"` +); + +assert.sameValue( + new Intl.Locale('en-Cyrl', {script: undefined}).toString(), + 'en-Cyrl', + `new Intl.Locale('en-Cyrl', {script: undefined}).toString() returns "en-Cyrl"` +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-script-valid.js b/js/src/tests/test262/intl402/Locale/constructor-options-script-valid.js new file mode 100644 index 0000000000..43fb26ff62 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-script-valid.js @@ -0,0 +1,64 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verify valid language option values (various) +info: | + Intl.Locale( tag [, options] ) + 9. Else, + a. Let tag be ? ToString(tag). + 10. If options is undefined, then + 11. Else + a. Let options be ? ToObject(options). + 12. Set tag to ? ApplyOptionsToTag(tag, options). + + ApplyOptionsToTag( tag, options ) + ... + 5. Let script be ? GetOption(options, "script", "string", undefined, undefined). + ... + 9. If tag matches neither the privateuse nor the grandfathered production, then + ... + c. 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. + + +features: [Intl.Locale] +---*/ + +const validScriptOptions = [ + [null, 'Null'], + ['bali', 'Bali'], + ['Bali', 'Bali'], + ['bALI', 'Bali'], + [{ toString() { return 'Brai' } }, 'Brai'], +]; +for (const [script, expected] of validScriptOptions) { + let expect = expected ? 'en-' + expected : 'en'; + + assert.sameValue( + new Intl.Locale('en', { script }).toString(), + expect, + `new Intl.Locale("en", {script: "${script}"}).toString() returns "${expect}"` + ); + + expect = (expected ? ('en-' + expected) : 'en') + '-DK'; + assert.sameValue( + new Intl.Locale('en-DK', { script }).toString(), + expect, + `new Intl.Locale("en-DK", {script: "${script}"}).toString() returns "${expect}"` + ); + + expect = expected ? ('en-' + expected) : 'en-Cyrl'; + assert.sameValue( + new Intl.Locale('en-Cyrl', { script }).toString(), + expect, + `new Intl.Locale("en-Cyrl", {script: "${script}"}).toString() returns "${expect}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-options-throwing-getters.js b/js/src/tests/test262/intl402/Locale/constructor-options-throwing-getters.js new file mode 100644 index 0000000000..92418505ad --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-options-throwing-getters.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale +description: Checks the propagation of exceptions from the options for the Locale constructor. +features: [Intl.Locale] +---*/ + +function CustomError() {} + +const options = [ + "language", + "script", + "region", + "calendar", + "collation", + "hourCycle", + "caseFirst", + "numeric", + "numberingSystem", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.Locale("en", { + get [option]() { + throw new CustomError(); + } + }); + }, + `new Intl.Locale("en", {get ${option}() {throw new CustomError();}}) throws CustomError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-parse-twice.js b/js/src/tests/test262/intl402/Locale/constructor-parse-twice.js new file mode 100644 index 0000000000..361c2d107d --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-parse-twice.js @@ -0,0 +1,60 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies the handling of options with grandfathered tags. +info: | + Intl.Locale( tag [, options] ) + 12. Set tag to ? ApplyOptionsToTag(tag, options). + 14. Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined). + 16. Set opt.[[ca]] to calendar. + 30. Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys). + + ApplyOptionsToTag( tag, options ) + ... + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + + IsStructurallyValidLanguageTag ( locale ) + + The IsStructurallyValidLanguageTag abstract operation verifies that the + locale argument (which must be a String value) + + represents a well-formed Unicode BCP 47 Locale Identifier" as specified in + Unicode Technical Standard 35 section 3.2, or successor, + +features: [Intl.Locale] +---*/ + +const testData = [ + // Canonicalized version of "en-GB-oed", which we can add "US" to right away. + { + tag: "en-GB-oxendict", + options: { + region: "US", + calendar: "gregory", + }, + canonical: "en-US-oxendict-u-ca-gregory", + }, +]; + +for (const {tag, options, canonical} of testData) { + assert.sameValue( + new Intl.Locale(tag, options).toString(), + canonical, + `new Intl.Locale("${tag}", ${options}).toString() returns "${canonical}"` + ); +} + +assert.throws(RangeError, () => + new Intl.Locale("no-bok", {region: "NO", calendar: "gregory"})); +assert.throws(RangeError, () => + new Intl.Locale("no-bok", {region: "SE", calendar: "gregory"})); +assert.throws(RangeError, () => + new Intl.Locale("no-bok-NO", {region: "SE", calendar: "gregory"})); +assert.throws(RangeError, () => + new Intl.Locale("no-bok-SE", {region: "NO", calendar: "gregory"})); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-tag-tostring.js b/js/src/tests/test262/intl402/Locale/constructor-tag-tostring.js new file mode 100644 index 0000000000..21472ca467 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-tag-tostring.js @@ -0,0 +1,39 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the string conversion of the locale argument to the + Locale constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 8. If Type(tag) is Object and tag has an [[InitializedLocale]] internal slot, then + 9. Else, + a. Let tag be ? ToString(tag). +features: [Intl.Locale] +---*/ + +function CustomError() {} +function WrongCustomError() {} + +const errors = [ + { get [Symbol.toPrimitive]() { throw new CustomError(); } }, + { [Symbol.toPrimitive](hint) { assert.sameValue(hint, "string"); throw new CustomError(); } }, + { get toString() { throw new CustomError(); }, get valueOf() { throw new WrongCustomError(); } }, + { toString() { throw new CustomError(); }, get valueOf() { throw new WrongCustomError(); } }, + { toString: undefined, get valueOf() { throw new CustomError(); } }, + { toString: undefined, valueOf() { throw new CustomError(); } }, + { toString() { return {} }, get valueOf() { throw new CustomError(); } }, + { toString() { return {} }, valueOf() { throw new CustomError(); } }, +]; + +for (const input of errors) { + assert.throws(CustomError, function() { + new Intl.Locale(input); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-tag.js b/js/src/tests/test262/intl402/Locale/constructor-tag.js new file mode 100644 index 0000000000..e84fcdbfb5 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-tag.js @@ -0,0 +1,59 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies canonicalization of specific tags. +info: | + ApplyOptionsToTag( tag, options ) + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + ... + 13. Return CanonicalizeLanguageTag(tag). +features: [Intl.Locale] +---*/ + +const validLanguageTags = { + "eN": "en", + "en-gb": "en-GB", + "IT-LATN-iT": "it-Latn-IT", + "th-th-u-nu-thai": "th-TH-u-nu-thai", + "en-x-u-foo": "en-x-u-foo", + "en-a-bar-x-u-foo": "en-a-bar-x-u-foo", + "en-x-u-foo-a-bar": "en-x-u-foo-a-bar", + "en-u-baz-a-bar-x-u-foo": "en-a-bar-u-baz-x-u-foo", + "DE-1996": "de-1996", // unicode_language_subtag sep unicode_variant_subtag + + // unicode_language_subtag (sep unicode_variant_subtag)* + "sl-ROZAJ-BISKE-1994": "sl-1994-biske-rozaj", + "zh-latn-pinyin-pinyin2": "zh-Latn-pinyin-pinyin2", +}; + +for (const [langtag, canonical] of Object.entries(validLanguageTags)) { + assert.sameValue( + new Intl.Locale(canonical).toString(), + canonical, + `new Intl.Locale("${canonical}").toString() returns "${canonical}"` + ); + assert.sameValue( + new Intl.Locale(langtag).toString(), + canonical, + `new Intl.Locale("${langtag}").toString() returns "${canonical}"` + ); +} + +// unicode_language_subtag = alpha{2,3} | alpha{5,8}; +const invalidLanguageTags = [ + "X-u-foo", + "Flob", + "ZORK", + "Blah-latn", + "QuuX-latn-us", + "SPAM-gb-x-Sausages-BACON-eggs", +]; + +for (const langtag of invalidLanguageTags) { + assert.throws(RangeError, () => new Intl.Locale(langtag)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-unicode-ext-invalid.js b/js/src/tests/test262/intl402/Locale/constructor-unicode-ext-invalid.js new file mode 100644 index 0000000000..e069053dc5 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-unicode-ext-invalid.js @@ -0,0 +1,33 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies treatment of specific structurally invalid tags. +info: | + ApplyOptionsToTag( tag, options ) + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. +features: [Intl.Locale] +---*/ + +const invalidLanguageTags = [ + // Unicode extension sequence is incomplete. + "da-u", + "da-u-", + "da-u--", + "da-u-t-latn", + "da-u-x-priv", + + // Duplicate 'u' singleton. + "da-u-ca-gregory-u-ca-buddhist" +]; + +for (const langtag of invalidLanguageTags) { + assert.throws(RangeError, function() { + new Intl.Locale(langtag) + }, + `new Intl.Locale("${langtag}") throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/constructor-unicode-ext-valid.js b/js/src/tests/test262/intl402/Locale/constructor-unicode-ext-valid.js new file mode 100644 index 0000000000..20c37c7981 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/constructor-unicode-ext-valid.js @@ -0,0 +1,40 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies canonicalization of specific tags. +info: | + ApplyOptionsToTag( tag, options ) + 10. Return CanonicalizeLanguageTag(tag). +features: [Intl.Locale] +---*/ + +const validLanguageTags = { + // Duplicate keywords are removed. + "da-u-ca-gregory-ca-buddhist": "da-u-ca-gregory", + + // Keywords currently used in Intl specs are reordered in US-ASCII order. + "zh-u-nu-hans-ca-chinese": "zh-u-ca-chinese-nu-hans", + "zh-u-ca-chinese-nu-hans": "zh-u-ca-chinese-nu-hans", + + // Even keywords currently not used in Intl specs are reordered in US-ASCII order. + "de-u-cu-eur-nu-latn": "de-u-cu-eur-nu-latn", + "de-u-nu-latn-cu-eur": "de-u-cu-eur-nu-latn", + + // Attributes in Unicode extensions are reordered in US-ASCII order. + "pt-u-attr-ca-gregory": "pt-u-attr-ca-gregory", + "pt-u-attr1-attr2-ca-gregory": "pt-u-attr1-attr2-ca-gregory", + "pt-u-attr2-attr1-ca-gregory": "pt-u-attr1-attr2-ca-gregory", +}; + +for (const [langtag, canonical] of Object.entries(validLanguageTags)) { + assert.sameValue( + new Intl.Locale(langtag).toString(), + canonical, + `new Intl.Locale("${langtag}").toString() returns "${canonical}"` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/extensions-grandfathered.js b/js/src/tests/test262/intl402/Locale/extensions-grandfathered.js new file mode 100644 index 0000000000..af4f9e0abc --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/extensions-grandfathered.js @@ -0,0 +1,69 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies handling of options with grandfathered tags. +info: | + ApplyOptionsToTag( tag, options ) + ... + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + + IsStructurallyValidLanguageTag ( locale ) + + The IsStructurallyValidLanguageTag abstract operation verifies that the + locale argument (which must be a String value) + + represents a well-formed Unicode BCP 47 Locale Identifier" as specified in + Unicode Technical Standard 35 section 3.2, or successor, + +features: [Intl.Locale] +---*/ + +const testData = [ + // Regular grandfathered without modern replacement. + { + tag: "cel-gaulish", + options: { + language: "fr", + script: "Cyrl", + region: "FR", + numberingSystem: "latn", + }, + canonical: "fr-Cyrl-FR-u-nu-latn", + }, + + // Regular grandfathered with modern replacement. + { + tag: "art-lojban", + options: { + language: "fr", + script: "Cyrl", + region: "ZZ", + numberingSystem: "latn", + }, + canonical: "fr-Cyrl-ZZ-u-nu-latn", + }, +]; + +for (const {tag, options, canonical} of testData) { + const loc = new Intl.Locale(tag, options); + assert.sameValue(loc.toString(), canonical); + + for (const [name, value] of Object.entries(options)) { + assert.sameValue(loc[name], value); + } +} + +assert.throws(RangeError, () => + new Intl.Locale("i-default", + {language: "fr", script: "Cyrl", region: "DE", numberingSystem: "latn"} + )); + +assert.throws(RangeError, () => + new Intl.Locale("en-gb-oed", + {language: "fr", script: "Cyrl", region: "US", numberingSystem: "latn"} + )); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/extensions-private.js b/js/src/tests/test262/intl402/Locale/extensions-private.js new file mode 100644 index 0000000000..cd3771b57f --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/extensions-private.js @@ -0,0 +1,26 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies handling of options with privateuse tags. +info: | + ApplyOptionsToTag( tag, options ) + + + ... + 9. If tag matches neither the privateuse nor the grandfathered production, then + ... + +features: [Intl.Locale] +---*/ + +assert.throws(RangeError, () => new Intl.Locale("x-default", { + language: "fr", + script: "Cyrl", + region: "DE", + numberingSystem: "latn", +})); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/function-prototype.js b/js/src/tests/test262/intl402/Locale/function-prototype.js new file mode 100644 index 0000000000..6127b8d129 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/function-prototype.js @@ -0,0 +1,18 @@ +// Copyright 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + The value of the [[Prototype]] internal slot of the Intl.Locale constructor is the + intrinsic object %FunctionPrototype%. +features: [Intl.Locale] +---*/ + +assert.sameValue( + Object.getPrototypeOf(Intl.Locale), + Function.prototype, + "Object.getPrototypeOf(Intl.Locale) equals the value of Function.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/getters-grandfathered.js b/js/src/tests/test262/intl402/Locale/getters-grandfathered.js new file mode 100644 index 0000000000..9df709545b --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/getters-grandfathered.js @@ -0,0 +1,41 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies getters with grandfathered tags. +info: | + get Intl.Locale.prototype.baseName + 5. Return the substring of locale corresponding to the + language ["-" script] ["-" region] *("-" variant) + subsequence of the unicode_language_id grammar. + + get Intl.Locale.prototype.language + 5. Return the substring of locale corresponding to the + unicode_language_subtag production. + + get Intl.Locale.prototype.script + 6. Return the substring of locale corresponding to the + unicode_script_subtag production. + + get Intl.Locale.prototype.region + 6. Return the substring of locale corresponding to the unicode_region_subtag + production. +features: [Intl.Locale] +---*/ + +// Regular grandfathered language tag. +var loc = new Intl.Locale("cel-gaulish"); +assert.sameValue(loc.baseName, "xtg"); +assert.sameValue(loc.language, "xtg"); +assert.sameValue(loc.script, undefined); +assert.sameValue(loc.region, undefined); + +// Regular grandfathered language tag. +assert.throws(RangeError, () => new Intl.Locale("zh-min")); + +assert.throws(RangeError, () => new Intl.Locale("i-default")); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/getters-missing.js b/js/src/tests/test262/intl402/Locale/getters-missing.js new file mode 100644 index 0000000000..2eaaec7282 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/getters-missing.js @@ -0,0 +1,55 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies getters with missing tags. +info: | + get Intl.Locale.prototype.baseName + 5. Return the substring of locale corresponding to the + language ["-" script] ["-" region] *("-" variant) + subsequence of the langtag grammar. + + get Intl.Locale.prototype.language + 4. Return the substring of locale corresponding to the language production. + + get Intl.Locale.prototype.script + 6. If locale does not contain the ["-" script] sequence, return undefined. + 7. Return the substring of locale corresponding to the script production. + + get Intl.Locale.prototype.region + 6. If locale does not contain the ["-" region] sequence, return undefined. + 7. Return the substring of locale corresponding to the region production. +features: [Intl.Locale] +---*/ + +// 'script' and 'region' subtags not present. +var loc = new Intl.Locale("sv"); +assert.sameValue(loc.baseName, "sv"); +assert.sameValue(loc.language, "sv"); +assert.sameValue(loc.script, undefined); +assert.sameValue(loc.region, undefined); + +// 'region' subtag not present. +var loc = new Intl.Locale("sv-Latn"); +assert.sameValue(loc.baseName, "sv-Latn"); +assert.sameValue(loc.language, "sv"); +assert.sameValue(loc.script, "Latn"); +assert.sameValue(loc.region, undefined); + +// 'script' subtag not present. +var loc = new Intl.Locale("sv-SE"); +assert.sameValue(loc.baseName, "sv-SE"); +assert.sameValue(loc.language, "sv"); +assert.sameValue(loc.script, undefined); +assert.sameValue(loc.region, "SE"); + +// 'variant' subtag present. +var loc = new Intl.Locale("de-1901"); +assert.sameValue(loc.baseName, "de-1901"); +assert.sameValue(loc.language, "de"); +assert.sameValue(loc.script, undefined); +assert.sameValue(loc.region, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/getters.js b/js/src/tests/test262/intl402/Locale/getters.js new file mode 100644 index 0000000000..6454fb1460 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/getters.js @@ -0,0 +1,124 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies getters with normal tags. +info: | + Intl.Locale.prototype.toString () + 3. Return loc.[[Locale]]. + + get Intl.Locale.prototype.baseName + 5. Return the substring of locale corresponding to the + language ["-" script] ["-" region] *("-" variant) + subsequence of the langtag grammar. + + get Intl.Locale.prototype.language + 4. Return the substring of locale corresponding to the language production. + + get Intl.Locale.prototype.script + 7. Return the substring of locale corresponding to the script production. + + get Intl.Locale.prototype.region + 7. Return the substring of locale corresponding to the region production. + + get Intl.Locale.prototype.calendar + 3. Return loc.[[Calendar]]. + + get Intl.Locale.prototype.collation + 3. Return loc.[[Collation]]. + + get Intl.Locale.prototype.hourCycle + 3. Return loc.[[HourCycle]]. + + get Intl.Locale.prototype.caseFirst + This property only exists if %Locale%.[[RelevantExtensionKeys]] contains "kf". + 3. Return loc.[[CaseFirst]]. + + get Intl.Locale.prototype.numeric + This property only exists if %Locale%.[[RelevantExtensionKeys]] contains "kn". + 3. Return loc.[[Numeric]]. + + get Intl.Locale.prototype.numberingSystem + 3. Return loc.[[NumberingSystem]]. + +features: [Intl.Locale] +---*/ + +// Test all getters return the expected results. +var langtag = "de-latn-de-u-ca-gregory-co-phonebk-hc-h23-kf-true-kn-false-nu-latn"; +var loc = new Intl.Locale(langtag); + +assert.sameValue(loc.toString(), "de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-kn-false-nu-latn"); +assert.sameValue(loc.baseName, "de-Latn-DE"); +assert.sameValue(loc.language, "de"); +assert.sameValue(loc.script, "Latn"); +assert.sameValue(loc.region, "DE"); +assert.sameValue(loc.calendar, "gregory"); +assert.sameValue(loc.collation, "phonebk"); +assert.sameValue(loc.hourCycle, "h23"); +if ("caseFirst" in loc) { + assert.sameValue(loc.caseFirst, ""); +} +if ("numeric" in loc) { + assert.sameValue(loc.numeric, false); +} +assert.sameValue(loc.numberingSystem, "latn"); + +// Replace all components through option values and validate the getters still +// return the expected results. +var loc = new Intl.Locale(langtag, { + language: "ja", + script: "jpan", + region: "jp", + calendar: "japanese", + collation: "search", + hourCycle: "h24", + caseFirst: "false", + numeric: "true", + numberingSystem: "jpanfin", +}); + +assert.sameValue(loc.toString(), "ja-Jpan-JP-u-ca-japanese-co-search-hc-h24-kf-false-kn-nu-jpanfin"); +assert.sameValue(loc.baseName, "ja-Jpan-JP"); +assert.sameValue(loc.language, "ja"); +assert.sameValue(loc.script, "Jpan"); +assert.sameValue(loc.region, "JP"); +assert.sameValue(loc.calendar, "japanese"); +assert.sameValue(loc.collation, "search"); +assert.sameValue(loc.hourCycle, "h24"); +if ("caseFirst" in loc) { + assert.sameValue(loc.caseFirst, "false"); +} +if ("numeric" in loc) { + assert.sameValue(loc.numeric, true); +} +assert.sameValue(loc.numberingSystem, "jpanfin"); + +// Replace only some components through option values and validate the getters +// return the expected results. +var loc = new Intl.Locale(langtag, { + language: "fr", + region: "ca", + collation: "standard", + hourCycle: "h11", +}); + +assert.sameValue(loc.toString(), "fr-Latn-CA-u-ca-gregory-co-standard-hc-h11-kf-kn-false-nu-latn"); +assert.sameValue(loc.baseName, "fr-Latn-CA"); +assert.sameValue(loc.language, "fr"); +assert.sameValue(loc.script, "Latn"); +assert.sameValue(loc.region, "CA"); +assert.sameValue(loc.calendar, "gregory"); +assert.sameValue(loc.collation, "standard"); +assert.sameValue(loc.hourCycle, "h11"); +if ("caseFirst" in loc) { + assert.sameValue(loc.caseFirst, ""); +} +if ("numeric" in loc) { + assert.sameValue(loc.numeric, false); +} +assert.sameValue(loc.numberingSystem, "latn"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/instance-extensibility.js b/js/src/tests/test262/intl402/Locale/instance-extensibility.js new file mode 100644 index 0000000000..99a10021cb --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/instance-extensibility.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: sec-intl.locale +description: > + Intl.Locale instance object extensibility +info: | + 17 ECMAScript Standard Built-in Objects: + + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Intl.Locale] +---*/ + +assert.sameValue( + Object.isExtensible(new Intl.Locale('en')), + true, + "Object.isExtensible(new Intl.Locale('en')) returns true" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/instance.js b/js/src/tests/test262/intl402/Locale/instance.js new file mode 100644 index 0000000000..24d1c2c5f5 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/instance.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Intl.Locale instance object created from %LocalePrototype%. +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, + "Object.getPrototypeOf(value) equals the value of Intl.Locale.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/invalid-tag-throws-boolean.js b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-boolean.js new file mode 100644 index 0000000000..a8ea22421d --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-boolean.js @@ -0,0 +1,24 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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.sameValue(typeof Intl.Locale, "function"); + +assert.throws(TypeError, function() { + new Intl.Locale(true); +}, "true is an invalid tag value"); +assert.throws(TypeError, function() { + new Intl.Locale(false); +}, "false is an invalid tag value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/invalid-tag-throws-null.js b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-null.js new file mode 100644 index 0000000000..9078819cd4 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-null.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: sec-intl.locale +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.sameValue(typeof Intl.Locale, "function"); + +assert.throws(TypeError, function() { + new Intl.Locale(null); +}, "null is an invalid tag value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/invalid-tag-throws-number.js b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-number.js new file mode 100644 index 0000000000..28b1672f31 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-number.js @@ -0,0 +1,34 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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.sameValue(typeof Intl.Locale, "function"); + +assert.throws(TypeError, function() { + new Intl.Locale(0); +}, "0 is an invalid tag value"); + +assert.throws(TypeError, function() { + new Intl.Locale(1); +}, "1 is an invalid tag value"); + +assert.throws(TypeError, function() { + new Intl.Locale(Infinity); +}, "Infinity is an invalid tag value"); + +assert.throws(TypeError, function() { + new Intl.Locale(NaN); +}, "NaN is an invalid tag value"); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/invalid-tag-throws-symbol.js b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-symbol.js new file mode 100644 index 0000000000..887bd46da1 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-symbol.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: sec-intl.locale +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, Symbol] +---*/ + +assert.sameValue(typeof Intl.Locale, "function"); + +assert.throws(TypeError, function() { + new Intl.Locale(Symbol()); +}, "Symbol() is an invalid tag value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/invalid-tag-throws-undefined.js b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-undefined.js new file mode 100644 index 0000000000..f8184c5a29 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/invalid-tag-throws-undefined.js @@ -0,0 +1,25 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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.sameValue(typeof Intl.Locale, "function"); + +assert.throws(TypeError, function() { + new Intl.Locale(); +}, "(empty) is an invalid tag value"); + +assert.throws(TypeError, function() { + new Intl.Locale(undefined) +}, "undefined is an invalid tag value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/invalid-tag-throws.js b/js/src/tests/test262/intl402/Locale/invalid-tag-throws.js new file mode 100644 index 0000000000..7b16250812 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/invalid-tag-throws.js @@ -0,0 +1,41 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks error cases for the options argument to the Locale + constructor. +info: | + Intl.Locale( tag [, options] ) + + ... + 11. Else + a. Let options be ? ToObject(options). + 12. Set tag to ? ApplyOptionsToTag(tag, options). + ... + + ApplyOptionsToTag( tag, options ) + + ... + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + ... +includes: [testIntl.js] +features: [Intl.Locale] +---*/ + +assert.sameValue(typeof Intl.Locale, "function"); + +// 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); + }, `${invalidTag} is an invalid tag value`); +} + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/length.js b/js/src/tests/test262/intl402/Locale/length.js new file mode 100644 index 0000000000..34ad67c28e --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/likely-subtags-grandfathered.js b/js/src/tests/test262/intl402/Locale/likely-subtags-grandfathered.js new file mode 100644 index 0000000000..56c3fe493a --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/likely-subtags-grandfathered.js @@ -0,0 +1,200 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies canonicalization, minimization and maximization of specific tags. +info: | + ApplyOptionsToTag( tag, options ) + + 2. If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception. + + 9. Set tag to CanonicalizeLanguageTag(tag). + + CanonicalizeLanguageTag( tag ) + + The CanonicalizeLanguageTag abstract operation returns the canonical and + case-regularized form of the locale argument (which must be a String value + that is a structurally valid Unicode BCP 47 Locale Identifier as verified by + the IsStructurallyValidLanguageTag abstract operation). + + IsStructurallyValidLanguageTag ( locale ) + + The IsStructurallyValidLanguageTag abstract operation verifies that the + locale argument (which must be a String value) + + represents a well-formed Unicode BCP 47 Locale Identifier" as specified in + Unicode Technical Standard 35 section 3.2, or successor, + + + Intl.Locale.prototype.maximize () + 3. Let maximal be the result of the Add Likely Subtags algorithm applied to loc.[[Locale]]. + + Intl.Locale.prototype.minimize () + 3. Let minimal be the result of the Remove Likely Subtags algorithm applied to loc.[[Locale]]. +features: [Intl.Locale] +---*/ + +const irregularGrandfathered = [ + "en-GB-oed", + "i-ami", + "i-bnn", + "i-default", + "i-enochian", + "i-hak", + "i-klingon", + "i-lux", + "i-mingo", + "i-navajo", + "i-pwn", + "i-tao", + "i-tay", + "i-tsu", + "sgn-BE-FR", + "sgn-BE-NL", + "sgn-CH-DE", +]; + +for (const tag of irregularGrandfathered) { + assert.throws(RangeError, () => new Intl.Locale(tag)); +} + +const regularGrandfathered = [ + { + tag: "art-lojban", + canonical: "jbo", + maximized: "jbo-Latn-001", + }, + { + tag: "cel-gaulish", + canonical: "xtg", + }, + { + tag: "zh-guoyu", + canonical: "zh", + maximized: "zh-Hans-CN", + }, + { + tag: "zh-hakka", + canonical: "hak", + maximized: "hak-Hans-CN", + }, + { + tag: "zh-xiang", + canonical: "hsn", + maximized: "hsn-Hans-CN", + }, +]; + +for (const {tag, canonical, maximized = canonical, minimized = canonical} of regularGrandfathered) { + const loc = new Intl.Locale(tag); + assert.sameValue(loc.toString(), canonical); + + assert.sameValue(loc.maximize().toString(), maximized); + assert.sameValue(loc.maximize().maximize().toString(), maximized); + + assert.sameValue(loc.minimize().toString(), minimized); + assert.sameValue(loc.minimize().minimize().toString(), minimized); + + assert.sameValue(loc.maximize().minimize().toString(), minimized); + assert.sameValue(loc.minimize().maximize().toString(), maximized); +} + +const regularGrandfatheredWithExtLang = [ + "no-bok", + "no-nyn", + "zh-min", + "zh-min-nan", +]; + +for (const tag of regularGrandfatheredWithExtLang) { + assert.throws(RangeError, () => new Intl.Locale(tag)); +} + +// Add variants, extensions, and privateuse subtags to regular grandfathered +// language tags and ensure it produces the "expected" result. +const extras = [ + "fonipa", + "a-not-assigned", + "u-attr", + "u-co", + "u-co-phonebk", + "x-private", +]; + +for (const {tag, canonical} of regularGrandfathered) { + const priv = "-x-0"; + const tagMax = new Intl.Locale(canonical + priv).maximize().toString().slice(0, -priv.length); + const tagMin = new Intl.Locale(canonical + priv).minimize().toString().slice(0, -priv.length); + + for (const extra of extras) { + const loc = new Intl.Locale(tag + "-" + extra); + + let canonicalWithExtra = canonical + "-" + extra; + let canonicalMax = tagMax + "-" + extra; + let canonicalMin = tagMin + "-" + extra; + + // Ensure the added variant subtag is correctly sorted in the canonical tag. + if (/^[a-z0-9]{5,8}|[0-9][a-z0-9]{3}$/i.test(extra)) { + const sorted = s => s.replace(/(-([a-z0-9]{5,8}|[0-9][a-z0-9]{3}))+$/i, + m => m.split("-").sort().join("-")); + canonicalWithExtra = sorted(canonicalWithExtra); + canonicalMax = sorted(canonicalMax); + canonicalMin = sorted(canonicalMin); + } + + // Adding extra subtags to grandfathered tags can have "interesting" results. Take for + // example "art-lojban" when "fonipa" is added, so we get "art-lojban-fonipa". The first + // step when canonicalising the language tag is to bring it in 'canonical syntax', that + // means among other things sorting variants in alphabetical order. So "art-lojban-fonipa" + // is transformed to "art-fonipa-lojban", because "fonipa" is sorted before "lojban". And + // only after that has happened, we replace aliases with their preferred form. + // + // Now the usual problems arise when doing silly things like adding subtags to + // grandfathered subtags, nobody, neither RFC 5646 nor UTS 35, provides a clear description + // what needs to happen next. + // + // From <http://unicode.org/reports/tr35/#Language_Tag_to_Locale_Identifier>: + // + // > A valid [BCP47] language tag can be converted to a valid Unicode BCP 47 locale + // > identifier according to Annex C. LocaleId Canonicalization + // + // From <http://unicode.org/reports/tr35/#LocaleId_Canonicalization> + // > The languageAlias, scriptAlias, territoryAlias, and variantAlias elements are used + // > as rules to transform an input source localeId. The first step is to transform the + // > languageId portion of the localeId. + // + // For regular grandfathered tags, "lojban", "gaulish", "guoyu", "hakka", and "xiang" will + // therefore be considered as the "variant" subtag and be replaced by rules in languageAlias. + // + // Not all language tag processor will pass this test, for example because they don't order + // variant subtags in alphabetical order or they're too eager when detecting grandfathered + // tags. For example "zh-hakka-hakka" is accepted in some language tag processors, because + // the language tag starts with a prefix which matches a grandfathered tag, and that prefix + // is then canonicalised to "hak" and the second "hakka" is simply appended to it, so the + // resulting tag is "hak-hakka". This is clearly wrong as far as ECMA-402 compliance is + // concerned, because language tags are parsed and validated before any canonicalisation + // happens. And during the validation step an error should be emitted, because the input + // "zh-hakka-hakka" contains two identical variant subtags. + // + // From <https://tc39.es/ecma402/#sec-isstructurallyvalidlanguagetag>: + // + // > does not include duplicate variant subtags + // + // So, if your implementation fails this assertion, but you still like to test the rest of + // this file, a pull request to split this file seems the way to go! + assert.sameValue(loc.toString(), canonicalWithExtra); + + assert.sameValue(loc.maximize().toString(), canonicalMax); + assert.sameValue(loc.maximize().maximize().toString(), canonicalMax); + + assert.sameValue(loc.minimize().toString(), canonicalMin); + assert.sameValue(loc.minimize().minimize().toString(), canonicalMin); + + assert.sameValue(loc.maximize().minimize().toString(), canonicalMin); + assert.sameValue(loc.minimize().maximize().toString(), canonicalMax); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/likely-subtags.js b/js/src/tests/test262/intl402/Locale/likely-subtags.js new file mode 100644 index 0000000000..17f990adbb --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/likely-subtags.js @@ -0,0 +1,114 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Verifies canonicalization, minimization and maximization of specific tags. +info: | + Intl.Locale.prototype.maximize () + 3. Let maximal be the result of the Add Likely Subtags algorithm applied to loc.[[Locale]]. + + Intl.Locale.prototype.minimize () + 3. Let minimal be the result of the Remove Likely Subtags algorithm applied to loc.[[Locale]]. +features: [Intl.Locale] +---*/ + +const testDataMaximal = { + // Language subtag is present. + "en": "en-Latn-US", + + // Language and script subtags are present. + "en-Latn": "en-Latn-US", + "en-Shaw": "en-Shaw-GB", + "en-Arab": "en-Arab-US", + + // Language and region subtags are present. + "en-US": "en-Latn-US", + "en-GB": "en-Latn-GB", + "en-FR": "en-Latn-FR", + + // Language, script, and region subtags are present. + "it-Kana-CA": "it-Kana-CA", + + // Undefined primary language. + "und": "en-Latn-US", + "und-Thai": "th-Thai-TH", + "und-419": "es-Latn-419", + "und-150": "ru-Cyrl-RU", + "und-AT": "de-Latn-AT", + "und-Cyrl-RO": "bg-Cyrl-RO", + + // Undefined primary language not required to change in all cases. + "und-AQ": "und-Latn-AQ", +}; + +const testDataMinimal = { + // Language subtag is present. + "en": "en", + + // Language and script subtags are present. + "en-Latn": "en", + "ar-Arab": "ar", + + // Language and region subtags are present. + "en-US": "en", + "en-GB": "en-GB", + + // Reverse cases from |testDataMaximal|. + "en-Latn-US": "en", + "en-Shaw-GB": "en-Shaw", + "en-Arab-US": "en-Arab", + "en-Latn-GB": "en-GB", + "en-Latn-FR": "en-FR", + "it-Kana-CA": "it-Kana-CA", + "th-Thai-TH": "th", + "es-Latn-419": "es-419", + "ru-Cyrl-RU": "ru", + "de-Latn-AT": "de-AT", + "bg-Cyrl-RO": "bg-RO", + "und-Latn-AQ": "und-AQ", +}; + +// Add variants, extensions, and privateuse subtags and ensure they don't +// modify the result of the likely subtags algorithms. +const extras = [ + "", + "-fonipa", + "-a-not-assigned", + "-u-attr", + "-u-co", + "-u-co-phonebk", + "-x-private", +]; + +for (const [tag, maximal] of Object.entries(testDataMaximal)) { + assert.sameValue(new Intl.Locale(maximal).maximize().toString(), maximal, + `"${maximal}" should be maximal`); + + for (const extra of extras) { + const input = tag + extra; + const output = maximal + extra; + assert.sameValue(new Intl.Locale(input).maximize().toString(), output, + `"${input}".maximize() should be "${output}"`); + } +} + +for (const [tag, minimal] of Object.entries(testDataMinimal)) { + assert.sameValue(new Intl.Locale(minimal).minimize().toString(), minimal, + `"${minimal}" should be minimal`); + + for (const extra of extras) { + const input = tag + extra; + const output = minimal + extra; + assert.sameValue(new Intl.Locale(input).minimize().toString(), output, + `"${input}".minimize() should be "${output}"`); + } +} + +// privateuse only. +// "x" in "x-private" does not match unicode_language_subtag +// unicode_language_subtag = alpha{2,3} | alpha{5,8}; +assert.throws(RangeError, () => new Intl.Locale("x-private")); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/name.js b/js/src/tests/test262/intl402/Locale/name.js new file mode 100644 index 0000000000..0def17d420 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/name.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: sec-intl.locale +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale, "name", { + value: "Locale", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prop-desc.js b/js/src/tests/test262/intl402/Locale/prop-desc.js new file mode 100644 index 0000000000..aab4c6aa7f --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prop-desc.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + "Locale" property of Intl. +info: | + Intl.Locale (...) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl, "Locale", { + value: Intl.Locale, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/Locale/proto-from-ctor-realm.js new file mode 100644 index 0000000000..3973759844 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/proto-from-ctor-realm.js @@ -0,0 +1,60 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.Locale ( tag [ , options] ) + + ... + 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget, %LocalePrototype%, internalSlotsList). + ... + 38. Return locale. + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.Locale, cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var locale; + +newTarget.prototype = undefined; +locale = Reflect.construct(Intl.Locale, ['de'], newTarget); +assert.sameValue(Object.getPrototypeOf(locale), other.Intl.Locale.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +locale = Reflect.construct(Intl.Locale, ['de'], newTarget); +assert.sameValue(Object.getPrototypeOf(locale), other.Intl.Locale.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = true; +locale = Reflect.construct(Intl.Locale, ['de'], newTarget); +assert.sameValue(Object.getPrototypeOf(locale), other.Intl.Locale.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = 'str'; +locale = Reflect.construct(Intl.Locale, ['de'], newTarget); +assert.sameValue(Object.getPrototypeOf(locale), other.Intl.Locale.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +locale = Reflect.construct(Intl.Locale, ['de'], newTarget); +assert.sameValue(Object.getPrototypeOf(locale), other.Intl.Locale.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = 0; +locale = Reflect.construct(Intl.Locale, ['de'], newTarget); +assert.sameValue(Object.getPrototypeOf(locale), other.Intl.Locale.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/baseName/branding.js b/js/src/tests/test262/intl402/Locale/prototype/baseName/branding.js new file mode 100644 index 0000000000..8c8264aa0f --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/baseName/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.baseName +description: > + Verifies the branding check for the "baseName" property of the Locale prototype object. +info: | + Intl.Locale.prototype.baseName + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "baseName"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/baseName/browser.js b/js/src/tests/test262/intl402/Locale/prototype/baseName/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/baseName/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/baseName/name.js b/js/src/tests/test262/intl402/Locale/prototype/baseName/name.js new file mode 100644 index 0000000000..f714d0a49a --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/baseName/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.baseName +description: > + Checks the "name" property of Intl.Locale.prototype.baseName. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "baseName").get; +verifyProperty(getter, "name", { + value: "get baseName", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/baseName/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/baseName/prop-desc.js new file mode 100644 index 0000000000..e9050e724c --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/baseName/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "baseName" property of the Locale prototype object. +info: | + Intl.Locale.prototype.baseName + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "baseName"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "baseName", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/baseName/shell.js b/js/src/tests/test262/intl402/Locale/prototype/baseName/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/baseName/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/browser.js b/js/src/tests/test262/intl402/Locale/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/calendar/branding.js b/js/src/tests/test262/intl402/Locale/prototype/calendar/branding.js new file mode 100644 index 0000000000..27ae523895 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/calendar/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.calendar +description: > + Verifies the branding check for the "calendar" property of the Locale prototype object. +info: | + Intl.Locale.prototype.calendar + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "calendar"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/calendar/browser.js b/js/src/tests/test262/intl402/Locale/prototype/calendar/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/calendar/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/calendar/name.js b/js/src/tests/test262/intl402/Locale/prototype/calendar/name.js new file mode 100644 index 0000000000..ea316300a7 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/calendar/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.calendar +description: > + Checks the "name" property of Intl.Locale.prototype.calendar. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "calendar").get; +verifyProperty(getter, "name", { + value: "get calendar", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/calendar/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/calendar/prop-desc.js new file mode 100644 index 0000000000..7e125216f2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/calendar/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "calendar" property of the Locale prototype object. +info: | + Intl.Locale.prototype.calendar + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "calendar"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "calendar", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/calendar/shell.js b/js/src/tests/test262/intl402/Locale/prototype/calendar/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/calendar/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/caseFirst/branding.js b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/branding.js new file mode 100644 index 0000000000..0506338c37 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/branding.js @@ -0,0 +1,34 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.caseFirst +description: > + Verifies the branding check for the "caseFirst" property of the Locale prototype object. +info: | + Intl.Locale.prototype.caseFirst + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "caseFirst"); +if (propdesc !== undefined) { + const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, + ]; + + for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/caseFirst/browser.js b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/caseFirst/name.js b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/name.js new file mode 100644 index 0000000000..6b1f6fcd64 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/name.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.caseFirst +description: > + Checks the "name" property of Intl.Locale.prototype.caseFirst. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "caseFirst"); +if (propdesc !== undefined) { + const getter = propdesc.get; + verifyProperty(getter, "name", { + value: "get caseFirst", + writable: false, + enumerable: false, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/caseFirst/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/prop-desc.js new file mode 100644 index 0000000000..d9528fab7f --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/prop-desc.js @@ -0,0 +1,29 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "caseFirst" property of the Locale prototype object. +info: | + Intl.Locale.prototype.caseFirst + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "caseFirst"); +if (propdesc) { + assert.sameValue(propdesc.set, undefined); + assert.sameValue(typeof propdesc.get, "function"); + + verifyProperty(Intl.Locale.prototype, "caseFirst", { + enumerable: false, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/caseFirst/shell.js b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/caseFirst/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/collation/branding.js b/js/src/tests/test262/intl402/Locale/prototype/collation/branding.js new file mode 100644 index 0000000000..e3e2eb5794 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/collation/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.collation +description: > + Verifies the branding check for the "collation" property of the Locale prototype object. +info: | + Intl.Locale.prototype.collation + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "collation"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/collation/browser.js b/js/src/tests/test262/intl402/Locale/prototype/collation/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/collation/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/collation/name.js b/js/src/tests/test262/intl402/Locale/prototype/collation/name.js new file mode 100644 index 0000000000..a45593e266 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/collation/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.collation +description: > + Checks the "name" property of Intl.Locale.prototype.collation. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "collation").get; +verifyProperty(getter, "name", { + value: "get collation", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/collation/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/collation/prop-desc.js new file mode 100644 index 0000000000..46de900d7b --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/collation/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "collation" property of the Locale prototype object. +info: | + Intl.Locale.prototype.collation + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "collation"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "collation", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/collation/shell.js b/js/src/tests/test262/intl402/Locale/prototype/collation/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/collation/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/constructor/browser.js b/js/src/tests/test262/intl402/Locale/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..e0cff7c1e4 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/constructor/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.constructor +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. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale.prototype, 'constructor', { + value: Intl.Locale, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/constructor/shell.js b/js/src/tests/test262/intl402/Locale/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/hourCycle/branding.js b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/branding.js new file mode 100644 index 0000000000..1716b0ff33 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.hourCycle +description: > + Verifies the branding check for the "hourCycle" property of the Locale prototype object. +info: | + Intl.Locale.prototype.hourCycle + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "hourCycle"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/hourCycle/browser.js b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/hourCycle/name.js b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/name.js new file mode 100644 index 0000000000..b40e2c6895 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.hourCycle +description: > + Checks the "name" property of Intl.Locale.prototype.hourCycle. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "hourCycle").get; +verifyProperty(getter, "name", { + value: "get hourCycle", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/hourCycle/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/prop-desc.js new file mode 100644 index 0000000000..1f96c725b8 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "hourCycle" property of the Locale prototype object. +info: | + Intl.Locale.prototype.hourCycle + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "hourCycle"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "hourCycle", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/hourCycle/shell.js b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/hourCycle/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/language/branding.js b/js/src/tests/test262/intl402/Locale/prototype/language/branding.js new file mode 100644 index 0000000000..b9da32ac87 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/language/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.language +description: > + Verifies the branding check for the "language" property of the Locale prototype object. +info: | + Intl.Locale.prototype.language + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "language"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/language/browser.js b/js/src/tests/test262/intl402/Locale/prototype/language/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/language/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/language/name.js b/js/src/tests/test262/intl402/Locale/prototype/language/name.js new file mode 100644 index 0000000000..089953cbda --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/language/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.language +description: > + Checks the "name" property of Intl.Locale.prototype.language. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "language").get; +verifyProperty(getter, "name", { + value: "get language", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/language/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/language/prop-desc.js new file mode 100644 index 0000000000..d2efe7ffa4 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/language/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "language" property of the Locale prototype object. +info: | + Intl.Locale.prototype.language + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "language"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "language", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/language/shell.js b/js/src/tests/test262/intl402/Locale/prototype/language/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/language/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/maximize/branding.js b/js/src/tests/test262/intl402/Locale/prototype/maximize/branding.js new file mode 100644 index 0000000000..38dbb77c52 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/maximize/branding.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.maximize +description: > + Verifies the branding check for the "maximize" function of the Locale prototype object. +info: | + Intl.Locale.prototype.maximize + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const maximize = Intl.Locale.prototype.maximize; + +assert.sameValue(typeof maximize, "function"); + +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => maximize.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/maximize/browser.js b/js/src/tests/test262/intl402/Locale/prototype/maximize/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/maximize/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/maximize/length.js b/js/src/tests/test262/intl402/Locale/prototype/maximize/length.js new file mode 100644 index 0000000000..add94c6696 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/maximize/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.maximize +description: > + Checks the "length" property of Intl.Locale.prototype.maximize(). +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale.prototype.maximize, 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/maximize/name.js b/js/src/tests/test262/intl402/Locale/prototype/maximize/name.js new file mode 100644 index 0000000000..259f91a34c --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/maximize/name.js @@ -0,0 +1,23 @@ +// Copyright 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.maximize +description: > + Checks the "name" property of Intl.Locale.prototype.maximize(). +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale.prototype.maximize, 'name', { + value: 'maximize', + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/maximize/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/maximize/prop-desc.js new file mode 100644 index 0000000000..990e8d4455 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/maximize/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.maximize +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. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +assert.sameValue( + typeof Intl.Locale.prototype.maximize, + 'function', + 'typeof Intl.Locale.prototype.maximize is function' +); + +verifyProperty(Intl.Locale.prototype, 'maximize', { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/maximize/shell.js b/js/src/tests/test262/intl402/Locale/prototype/maximize/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/maximize/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/minimize/branding.js b/js/src/tests/test262/intl402/Locale/prototype/minimize/branding.js new file mode 100644 index 0000000000..c86f491323 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/minimize/branding.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.minimize +description: > + Verifies the branding check for the "minimize" function of the Locale prototype object. +info: | + Intl.Locale.prototype.minimize + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const minimize = Intl.Locale.prototype.minimize; + +assert.sameValue(typeof minimize, "function"); + +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => minimize.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/minimize/browser.js b/js/src/tests/test262/intl402/Locale/prototype/minimize/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/minimize/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/minimize/length.js b/js/src/tests/test262/intl402/Locale/prototype/minimize/length.js new file mode 100644 index 0000000000..ad329cd3be --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/minimize/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.minimize +description: > + Checks the "length" property of Intl.Locale.prototype.minimize(). +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale.prototype.minimize, 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/minimize/name.js b/js/src/tests/test262/intl402/Locale/prototype/minimize/name.js new file mode 100644 index 0000000000..5a67ae8956 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/minimize/name.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: sec-intl.locale.prototype.minimize +description: > + Checks the "name" property of Intl.Locale.prototype.minimize(). +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale.prototype.minimize, 'name', { + value: 'minimize', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/minimize/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/minimize/prop-desc.js new file mode 100644 index 0000000000..f389b23797 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/minimize/prop-desc.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "minimize" property of the Locale prototype object. +info: | + Intl.Locale.prototype.minimize () + + 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. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +assert.sameValue( + typeof Intl.Locale.prototype.minimize, + 'function', + 'typeof Intl.Locale.prototype.minimize is function' +); + +verifyProperty(Intl.Locale.prototype, 'minimize', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/minimize/removing-likely-subtags-first-adds-likely-subtags.js b/js/src/tests/test262/intl402/Locale/prototype/minimize/removing-likely-subtags-first-adds-likely-subtags.js new file mode 100644 index 0000000000..641f08243f --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/minimize/removing-likely-subtags-first-adds-likely-subtags.js @@ -0,0 +1,51 @@ +// Copyright 2020 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.minimize +description: > + The "Remove Likely Subtags" algorithm adds likely subtags before processing the locale. +info: | + Intl.Locale.prototype.minimize () + 3. Let minimal be the result of the Remove Likely Subtags algorithm applied to loc.[[Locale]]. + If an error is signaled, set minimal to loc.[[Locale]]. + + UTS 35, §4.3 Likely Subtags + Remove Likely Subtags + + 1. First get max = AddLikelySubtags(inputLocale). If an error is signaled, return it. + 2. ... +features: [Intl.Locale] +---*/ + +var testDataMinimal = { + // Undefined primary language. + "und": "en", + "und-Thai": "th", + "und-419": "es-419", + "und-150": "ru", + "und-AT": "de-AT", + + // https://unicode-org.atlassian.net/browse/ICU-13786 + "aae-Latn-IT": "aae-Latn-IT", + "aae-Thai-CO": "aae-Thai-CO", + + // https://unicode-org.atlassian.net/browse/ICU-10220 + // https://unicode-org.atlassian.net/browse/ICU-12345 + "und-CW": "pap-CW", + "und-US": "en", + "zh-Hant": "zh-TW", + "zh-Hani": "zh-Hani", +}; + +for (const [tag, minimal] of Object.entries(testDataMinimal)) { + // Assert the |minimal| tag is indeed minimal. + assert.sameValue(new Intl.Locale(minimal).minimize().toString(), minimal, + `"${minimal}" should be minimal`); + + // Assert RemoveLikelySubtags(tag) returns |minimal|. + assert.sameValue(new Intl.Locale(tag).minimize().toString(), minimal, + `"${tag}".minimize() should be "${minimal}"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/minimize/shell.js b/js/src/tests/test262/intl402/Locale/prototype/minimize/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/minimize/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/branding.js b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/branding.js new file mode 100644 index 0000000000..6b736e9292 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.numberingSystem +description: > + Verifies the branding check for the "numberingSystem" property of the Locale prototype object. +info: | + Intl.Locale.prototype.numberingSystem + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "numberingSystem"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/browser.js b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/name.js b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/name.js new file mode 100644 index 0000000000..1e0b908694 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.numberingSystem +description: > + Checks the "name" property of Intl.Locale.prototype.numberingSystem. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "numberingSystem").get; +verifyProperty(getter, "name", { + value: "get numberingSystem", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/prop-desc.js new file mode 100644 index 0000000000..4f6f62a7c2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "numberingSystem" property of the Locale prototype object. +info: | + Intl.Locale.prototype.numberingSystem + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "numberingSystem"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "numberingSystem", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/shell.js b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numberingSystem/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/numeric/branding.js b/js/src/tests/test262/intl402/Locale/prototype/numeric/branding.js new file mode 100644 index 0000000000..df1354be4e --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numeric/branding.js @@ -0,0 +1,34 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.numeric +description: > + Verifies the branding check for the "numeric" property of the Locale prototype object. +info: | + Intl.Locale.prototype.numeric + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "numeric"); +if (propdesc !== undefined) { + const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, + ]; + + for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/numeric/browser.js b/js/src/tests/test262/intl402/Locale/prototype/numeric/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numeric/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/numeric/name.js b/js/src/tests/test262/intl402/Locale/prototype/numeric/name.js new file mode 100644 index 0000000000..db01e07741 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numeric/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.numeric +description: > + Checks the "name" property of Intl.Locale.prototype.numeric. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "numeric").get; +verifyProperty(getter, "name", { + value: "get numeric", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/numeric/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/numeric/prop-desc.js new file mode 100644 index 0000000000..d361b3e5a2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numeric/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "numeric" property of the Locale prototype object. +info: | + Intl.Locale.prototype.numeric + + 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 accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "numeric"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "numeric", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/numeric/shell.js b/js/src/tests/test262/intl402/Locale/prototype/numeric/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/numeric/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/prop-desc.js new file mode 100644 index 0000000000..f31eec1c25 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/prop-desc.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +verifyProperty(Intl.Locale, 'prototype', { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/region/branding.js b/js/src/tests/test262/intl402/Locale/prototype/region/branding.js new file mode 100644 index 0000000000..47b07ae9e8 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/region/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.region +description: > + Verifies the branding check for the "region" property of the Locale prototype object. +info: | + Intl.Locale.prototype.region + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "region"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/region/browser.js b/js/src/tests/test262/intl402/Locale/prototype/region/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/region/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/region/name.js b/js/src/tests/test262/intl402/Locale/prototype/region/name.js new file mode 100644 index 0000000000..5aabb93dda --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/region/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.region +description: > + Checks the "name" property of Intl.Locale.prototype.region. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "region").get; +verifyProperty(getter, "name", { + value: "get region", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/region/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/region/prop-desc.js new file mode 100644 index 0000000000..ca3a753cd7 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/region/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "region" property of the Locale prototype object. +info: | + Intl.Locale.prototype.region + + 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 ECMAregion objects in the ECMAregion 2019 region Specification, 10th edition, clause 17, or successor. + + Every accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "region"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "region", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/region/shell.js b/js/src/tests/test262/intl402/Locale/prototype/region/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/region/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/script/branding.js b/js/src/tests/test262/intl402/Locale/prototype/script/branding.js new file mode 100644 index 0000000000..ffa1e8f66d --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/script/branding.js @@ -0,0 +1,32 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.script +description: > + Verifies the branding check for the "script" property of the Locale prototype object. +info: | + Intl.Locale.prototype.script + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "script"); +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => propdesc.get.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/script/browser.js b/js/src/tests/test262/intl402/Locale/prototype/script/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/script/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/script/name.js b/js/src/tests/test262/intl402/Locale/prototype/script/name.js new file mode 100644 index 0000000000..a36f0fbbea --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/script/name.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype.script +description: > + Checks the "name" property of Intl.Locale.prototype.script. +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. Functions that are specified as get or set accessor functions of built-in properties have "get " or "set " prepended to the property name string. + Unless otherwise specified, the name property of a built-in function object, if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const getter = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "script").get; +verifyProperty(getter, "name", { + value: "get script", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/script/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/script/prop-desc.js new file mode 100644 index 0000000000..3a510e34c9 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/script/prop-desc.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "script" property of the Locale prototype object. +info: | + Intl.Locale.prototype.script + + 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 script Specification, 10th edition, clause 17, or successor. + + Every accessor property described in clauses 18 through 26 and in Annex B.2 has the attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. If only a get accessor function is described, the set accessor function is the default value, undefined. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +const propdesc = Object.getOwnPropertyDescriptor(Intl.Locale.prototype, "script"); +assert.sameValue(propdesc.set, undefined); +assert.sameValue(typeof propdesc.get, "function"); + +verifyProperty(Intl.Locale.prototype, "script", { + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/script/shell.js b/js/src/tests/test262/intl402/Locale/prototype/script/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/script/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/shell.js b/js/src/tests/test262/intl402/Locale/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/toString/branding.js b/js/src/tests/test262/intl402/Locale/prototype/toString/branding.js new file mode 100644 index 0000000000..8b14ec4fb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toString/branding.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale.prototype.toString +description: > + Verifies the branding check for the "toString" function of the Locale prototype object. +info: | + Intl.Locale.prototype.toString + + 2. If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then + a. Throw a TypeError exception. +features: [Intl.Locale] +---*/ + +const toString = Intl.Locale.prototype.toString; + +assert.sameValue(typeof toString, "function"); + +const invalidValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Locale.prototype, +]; + +for (const invalidValue of invalidValues) { + assert.throws(TypeError, () => toString.call(invalidValue)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/toString/browser.js b/js/src/tests/test262/intl402/Locale/prototype/toString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toString/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/toString/prop-desc.js b/js/src/tests/test262/intl402/Locale/prototype/toString/prop-desc.js new file mode 100644 index 0000000000..5ab7eaeac4 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toString/prop-desc.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale +description: > + Checks the "toString" property of the Locale prototype object. +info: | + Intl.Locale.prototype.toString () + + 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. +includes: [propertyHelper.js] +features: [Intl.Locale] +---*/ + +assert.sameValue( + typeof Intl.Locale.prototype.toString, + "function", + "typeof Intl.Locale.prototype.toString is function" +); + +verifyProperty(Intl.Locale.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/toString/shell.js b/js/src/tests/test262/intl402/Locale/prototype/toString/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toString/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toString-removed-tag.js b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toString-removed-tag.js new file mode 100644 index 0000000000..116caedeb7 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toString-removed-tag.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: sec-intl.locale.prototype-@@tostringtag +description: > + Checks Object.prototype.toString with Intl.Locale objects. +info: | + Intl.Locale.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.Locale". +features: [Intl.Locale, Symbol.toStringTag] +---*/ + +delete Intl.Locale.prototype[Symbol.toStringTag]; + +assert.sameValue(Object.prototype.toString.call(Intl.Locale.prototype), "[object Object]"); +assert.sameValue(Object.prototype.toString.call(new Intl.Locale("en")), "[object Object]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toString.js new file mode 100644 index 0000000000..42896406e3 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toString.js @@ -0,0 +1,18 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype-@@tostringtag +description: > + Checks Object.prototype.toString with Intl.Locale objects. +info: | + Intl.Locale.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.Locale". +features: [Intl.Locale, Symbol.toStringTag] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.Locale.prototype), "[object Intl.Locale]"); +assert.sameValue(Object.prototype.toString.call(new Intl.Locale("en")), "[object Intl.Locale]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toStringTag.js new file mode 100644 index 0000000000..d58a240de7 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/prototype/toStringTag/toStringTag.js @@ -0,0 +1,25 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.locale.prototype-@@tostringtag +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 }. +includes: [propertyHelper.js] +features: [Intl.Locale, Symbol.toStringTag] +---*/ + +verifyProperty(Intl.Locale.prototype, Symbol.toStringTag, { + value: 'Intl.Locale', + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/reject-duplicate-variants-in-tlang.js b/js/src/tests/test262/intl402/Locale/reject-duplicate-variants-in-tlang.js new file mode 100644 index 0000000000..c2d01bc0b9 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/reject-duplicate-variants-in-tlang.js @@ -0,0 +1,52 @@ +// Copyright 2020 Jeff Walden, Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-isstructurallyvalidlanguagetag +description: > + Verifies that just as duplicate variants in a tag ("en-emodeng-emodeng") make + the tag structurally invalid, so too do duplicate variants in the tlang + component of an otherwise structurally valid tag ("de-t-emodeng-emodeng"), + make it structurally invalid. +info: | + if a `transformed_extensions` component that contains a `tlang` component is + present, then + the `tlang` component contains no duplicate `unicode_variant_subtag` + subtags. +features: [Intl.Locale] +---*/ + +assert.sameValue(typeof Intl.Locale, "function"); + +function mustReject(tag) { + assert.throws(RangeError, () => { + // Direct matches are rejected. + new Intl.Locale(tag); + }, `tag "${tag}" must be considered structurally invalid`); +} + +// BCP47 since forever, and ECMA-402 as consequence, do not consider tags that +// contain duplicate variants to be structurally valid. This restriction also +// applies within the |tlang| component (indicating the source locale from which +// relevant content was transformed) of a broader language tag. + +// Direct matches are rejected. +mustReject("de-t-en-emodeng-emodeng"); +// Case-insensitive matches are also rejected. +mustReject("de-t-en-Emodeng-emodeng"); +// ...and in either order. +mustReject("de-t-en-emodeng-Emodeng"); + +// Repeat the above tests with additional variants interspersed at each point +// for completeness. +mustReject("de-t-en-variant-emodeng-emodeng"); +mustReject("de-t-en-variant-Emodeng-emodeng"); +mustReject("de-t-en-variant-emodeng-Emodeng"); +mustReject("de-t-en-emodeng-variant-emodeng"); +mustReject("de-t-en-Emodeng-variant-emodeng"); +mustReject("de-t-en-emodeng-variant-Emodeng"); +mustReject("de-t-en-emodeng-emodeng-variant"); +mustReject("de-t-en-Emodeng-emodeng-variant"); +mustReject("de-t-en-emodeng-Emodeng-variant"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/reject-duplicate-variants.js b/js/src/tests/test262/intl402/Locale/reject-duplicate-variants.js new file mode 100644 index 0000000000..cb6025388f --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/reject-duplicate-variants.js @@ -0,0 +1,46 @@ +// Copyright 2020 Jeff Walden, Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-isstructurallyvalidlanguagetag +description: > + Verifies that duplicate variants in a tag ("en-emodeng-emodeng") make the tag + structurally invalid. +info: | + the `unicode_language_id` within _locale_ contains no duplicate + `unicode_variant_subtag` subtags +features: [Intl.Locale] +---*/ + +assert.sameValue(typeof Intl.Locale, "function"); + +function mustReject(tag) { + assert.throws(RangeError, () => { + // Direct matches are rejected. + new Intl.Locale(tag); + }, `tag "${tag}" must be considered structurally invalid`); +} + +// BCP47 since forever, and ECMA-402 as consequence, do not consider tags that +// contain duplicate variants to be structurally valid. + +// Direct matches are rejected. +mustReject("en-emodeng-emodeng"); +// Case-insensitive matches are also rejected. +mustReject("en-Emodeng-emodeng"); +// ...and in either order. +mustReject("en-emodeng-Emodeng"); + +// Repeat the above tests with additional variants interspersed at each point +// for completeness. +mustReject("en-variant-emodeng-emodeng"); +mustReject("en-variant-Emodeng-emodeng"); +mustReject("en-variant-emodeng-Emodeng"); +mustReject("en-emodeng-variant-emodeng"); +mustReject("en-Emodeng-variant-emodeng"); +mustReject("en-emodeng-variant-Emodeng"); +mustReject("en-emodeng-emodeng-variant"); +mustReject("en-Emodeng-emodeng-variant"); +mustReject("en-emodeng-Emodeng-variant"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Locale/shell.js b/js/src/tests/test262/intl402/Locale/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/shell.js diff --git a/js/src/tests/test262/intl402/Locale/subclassing.js b/js/src/tests/test262/intl402/Locale/subclassing.js new file mode 100644 index 0000000000..4afc3a5a83 --- /dev/null +++ b/js/src/tests/test262/intl402/Locale/subclassing.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Locale +description: Checks that Locale can be subclassed. +info: | + Intl.Locale( tag [, options] ) + + 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget, %LocalePrototype%, internalSlotsList). + +features: [Intl.Locale] +---*/ + +class CustomLocale extends Intl.Locale { + constructor(locales, options) { + super(locales, options); + this.isCustom = true; + } +} + +var locale = new CustomLocale("de"); +assert.sameValue(locale.isCustom, true, "Custom property"); +assert.sameValue(locale.toString(), "de", "Direct call"); +assert.sameValue(Intl.Locale.prototype.toString.call(locale), "de", "Indirect call"); +assert.sameValue(Object.getPrototypeOf(locale), CustomLocale.prototype, "Prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/browser.js b/js/src/tests/test262/intl402/Number/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/browser.js diff --git a/js/src/tests/test262/intl402/Number/prototype/browser.js b/js/src/tests/test262/intl402/Number/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/browser.js diff --git a/js/src/tests/test262/intl402/Number/prototype/shell.js b/js/src/tests/test262/intl402/Number/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/shell.js diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/browser.js diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/builtin.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/builtin.js new file mode 100644 index 0000000000..cc3639f018 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.2.1_L15 +description: > + Tests that Number.prototype.toLocaleString meets the requirements + for built-in objects defined by the introduction of chapter 17 of + the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Number.prototype.toLocaleString), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Number.prototype.toLocaleString), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Number.prototype.toLocaleString), Function.prototype); + +assert.sameValue(Number.prototype.toLocaleString.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Number.prototype.toLocaleString), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/default-options-object-prototype.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/default-options-object-prototype.js new file mode 100644 index 0000000000..d6d1f0693c --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/default-options-object-prototype.js @@ -0,0 +1,21 @@ +// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Monkey-patching Object.prototype does not change the default + options for NumberFormat as a null prototype is used. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 1. If _options_ is *undefined*, then + 1. Let _options_ be ObjectCreate(*null*). +---*/ + +if (new Intl.NumberFormat("en").resolvedOptions().locale === "en") { + Object.prototype.maximumFractionDigits = 1; + assert.sameValue(1.23.toLocaleString("en"), "1.23"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/length.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/length.js new file mode 100644 index 0000000000..53286f8b64 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/length.js @@ -0,0 +1,34 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-number.prototype.tolocalestring +description: > + Number.prototype.toLocaleString.length is 0. +info: | + Number.prototype.toLocaleString ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +verifyProperty(Number.prototype.toLocaleString, 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/returns-same-results-as-NumberFormat.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/returns-same-results-as-NumberFormat.js new file mode 100644 index 0000000000..10c54d530b --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/returns-same-results-as-NumberFormat.js @@ -0,0 +1,40 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.2.1_5 +description: > + Tests that Number.prototype.toLocaleString produces the same + results as Intl.NumberFormat. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +var numbers = [0, -0, 1, -1, 5.5, 123, -123, -123.45, 123.44501, 0.001234, + -0.00000000123, 0.00000000000000000000000000000123, 1.2, 0.0000000012344501, + 123445.01, 12344501000000000000000000000000000, -12344501000000000000000000000000000, + Infinity, -Infinity, NaN]; +var locales = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]]; +var options = [ + undefined, + {style: "percent"}, + {style: "currency", currency: "EUR", currencyDisplay: "symbol"}, + {style: "currency", currency: "IQD", currencyDisplay: "symbol"}, + {style: "currency", currency: "KMF", currencyDisplay: "symbol"}, + {style: "currency", currency: "CLF", currencyDisplay: "symbol"}, + {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3} +]; + +locales.forEach(function (locales) { + options.forEach(function (options) { + var referenceNumberFormat = new Intl.NumberFormat(locales, options); + var referenceFormatted = numbers.map(referenceNumberFormat.format); + + var formatted = numbers.map(function (a) { return a.toLocaleString(locales, options); }); + assert.compareArray(formatted, referenceFormatted, + "(Testing with locales " + locales + "; options " + + (options ? JSON.stringify(options) : options) + ".)"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/taint-Intl-NumberFormat.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/taint-Intl-NumberFormat.js new file mode 100644 index 0000000000..ba9a755568 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/taint-Intl-NumberFormat.js @@ -0,0 +1,16 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.2.1_4_2 +description: > + Tests that Number.prototype.toLocaleString uses the standard + built-in Intl.NumberFormat constructor. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintDataProperty(Intl, "NumberFormat"); +(0.0).toLocaleString(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/this-number-value.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/this-number-value.js new file mode 100644 index 0000000000..86e68ef2ce --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/this-number-value.js @@ -0,0 +1,28 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.2.1_1 +description: Tests that toLocaleString handles "this Number value" correctly. +author: Norbert Lindenberg +---*/ + +var invalidValues = [undefined, null, "5", false, {valueOf: function () { return 5; }}]; +var validValues = [5, NaN, -1234567.89, -Infinity]; + +invalidValues.forEach(function (value) { + assert.throws(TypeError, function() { + var result = Number.prototype.toLocaleString.call(value); + }, "Number.prototype.toLocaleString did not reject this = " + value + "."); +}); + +// for valid values, just check that a Number value and the corresponding +// Number object get the same result. +validValues.forEach(function (value) { + var Constructor = Number; // to keep jshint happy + var valueResult = Number.prototype.toLocaleString.call(value); + var objectResult = Number.prototype.toLocaleString.call(new Constructor(value)); + assert.sameValue(valueResult, objectResult, "Number.prototype.toLocaleString produces different results for Number value " + value + " and corresponding Number object."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/prototype/toLocaleString/throws-same-exceptions-as-NumberFormat.js b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/throws-same-exceptions-as-NumberFormat.js new file mode 100644 index 0000000000..8dbb5b72a3 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/prototype/toLocaleString/throws-same-exceptions-as-NumberFormat.js @@ -0,0 +1,49 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.2.1_4_1 +description: > + Tests that Number.prototype.toLocaleString throws the same + exceptions as Intl.NumberFormat. +author: Norbert Lindenberg +---*/ + +var locales = [null, [NaN], ["i"], ["de_DE"]]; +var options = [ + {localeMatcher: null}, + {style: "invalid"}, + {style: "currency"}, + {style: "currency", currency: "ßP"}, + {maximumSignificantDigits: -Infinity} +]; + +locales.forEach(function (locales) { + var referenceError, error; + try { + var format = new Intl.NumberFormat(locales); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.NumberFormat for locales " + locales + "."); + + assert.throws(referenceError.constructor, function() { + var result = (0).toLocaleString(locales); + }, "Number.prototype.toLocaleString didn't throw exception for locales " + locales + "."); +}); + +options.forEach(function (options) { + var referenceError, error; + try { + var format = new Intl.NumberFormat([], options); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.NumberFormat for options " + JSON.stringify(options) + "."); + + assert.throws(referenceError.constructor, function() { + var result = (0).toLocaleString([], options); + }, "Number.prototype.toLocaleString didn't throw exception for options " + JSON.stringify(options) + "."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Number/shell.js b/js/src/tests/test262/intl402/Number/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Number/shell.js diff --git a/js/src/tests/test262/intl402/NumberFormat/browser.js b/js/src/tests/test262/intl402/NumberFormat/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/builtin.js b/js/src/tests/test262/intl402/NumberFormat/builtin.js new file mode 100644 index 0000000000..6848ae39e9 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/builtin.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.1_L15 +description: > + Tests that Intl.NumberFormat meets the requirements for built-in + objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.NumberFormat), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.NumberFormat), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/casing-numbering-system-options.js b/js/src/tests/test262/intl402/NumberFormat/casing-numbering-system-options.js new file mode 100644 index 0000000000..a4960f9cc2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/casing-numbering-system-options.js @@ -0,0 +1,28 @@ +// Copyright 2020 Google Inc, Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that the options numberingSystem are mapped to lower case. +author: Caio Lima +---*/ + +let defaultLocale = new Intl.NumberFormat().resolvedOptions().locale; + +let supportedNumberingSystems = ["latn", "arab"].filter(nu => + new Intl.NumberFormat(defaultLocale + "-u-nu-" + nu) + .resolvedOptions().numberingSystem === nu +); + +if (supportedNumberingSystems.includes("latn")) { + let numberFormat = new Intl.NumberFormat(defaultLocale + "-u-nu-lATn"); + assert.sameValue(numberFormat.resolvedOptions().numberingSystem, "latn", "Numbering system option should be in lower case"); +} + +if (supportedNumberingSystems.includes("arab")) { + let numberFormat = new Intl.NumberFormat(defaultLocale + "-u-nu-Arab"); + assert.sameValue(numberFormat.resolvedOptions().numberingSystem, "arab", "Numbering system option should be in lower case"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-compact.js b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-compact.js new file mode 100644 index 0000000000..ef5061b87d --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-compact.js @@ -0,0 +1,46 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 19. Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short"). + 20. If notation is "compact", then + a. Set numberFormat.[[CompactDisplay]] to compactDisplay. + +includes: [compareArray.js] +features: [Intl.NumberFormat-unified] +---*/ + +const values = [ + [undefined, "short"], + ["short"], + ["long"], +]; + +for (const [value, expected = value] of values) { + const callOrder = []; + const nf = new Intl.NumberFormat([], { + get notation() { + callOrder.push("notation"); + return "compact"; + }, + get compactDisplay() { + callOrder.push("compactDisplay"); + return value; + } + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue("compactDisplay" in resolvedOptions, true); + assert.sameValue(resolvedOptions.compactDisplay, expected); + + assert.compareArray(callOrder, [ + "notation", + "compactDisplay", + ]); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-no-compact.js b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-no-compact.js new file mode 100644 index 0000000000..9f5b1336ad --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-compactDisplay-no-compact.js @@ -0,0 +1,55 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 19. Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short"). + 20. If notation is "compact", then + a. Set numberFormat.[[CompactDisplay]] to compactDisplay. + +includes: [compareArray.js] +features: [Intl.NumberFormat-unified] +---*/ + +const values = [ + [undefined, "short"], + ["short"], + ["long"], +]; + +const notations = [ + undefined, + "standard", + "scientific", + "engineering", +]; + +for (const notation of notations) { + for (const [value, expected = value] of values) { + const callOrder = []; + const nf = new Intl.NumberFormat([], { + get notation() { + callOrder.push("notation"); + return notation; + }, + get compactDisplay() { + callOrder.push("compactDisplay"); + return value; + } + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue("compactDisplay" in resolvedOptions, false); + assert.sameValue(resolvedOptions.compactDisplay, undefined); + + assert.compareArray(callOrder, [ + "notation", + "compactDisplay", + ]); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-default-value.js b/js/src/tests/test262/intl402/NumberFormat/constructor-default-value.js new file mode 100644 index 0000000000..f92618543d --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-default-value.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that the constructor for Intl.NumberFormat uses appropriate default + values for its arguments (locales and options). +---*/ + +const actual = new Intl.NumberFormat().resolvedOptions(); +const expected = new Intl.NumberFormat([], Object.create(null)).resolvedOptions(); + +assert.sameValue(actual.locale, expected.locale); +assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits); +assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits); +assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits); +assert.sameValue(actual.numberingSystem, expected.numberingSystem); +assert.sameValue(actual.style, expected.style); +assert.sameValue(actual.useGrouping, expected.useGrouping); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-arraylike.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-arraylike.js new file mode 100644 index 0000000000..816bcd2096 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-arraylike.js @@ -0,0 +1,25 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that the Intl.NumberFormat constructor accepts Array-like values for the + locales argument and treats them well. +---*/ + +const actual = Intl.NumberFormat({ + length: 1, + 0: 'en-US' +}).resolvedOptions(); +const expected = Intl.NumberFormat(['en-US']).resolvedOptions(); + +assert.sameValue(actual.locale, expected.locale); +assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits); +assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits); +assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits); +assert.sameValue(actual.numberingSystem, expected.numberingSystem); +assert.sameValue(actual.style, expected.style); +assert.sameValue(actual.useGrouping, expected.useGrouping); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-get-tostring.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-get-tostring.js new file mode 100644 index 0000000000..d7bb6422c3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-get-tostring.js @@ -0,0 +1,43 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that Get(O, P) and ToString(arg) are properly called within the + constructor for Intl.NumberFormat +info: | + 9.2.1 CanonicalizeLocaleList ( locales ) + + 5. Let len be ? ToLength(? Get(O, "length")). + + 7.a. Let Pk be ToString(k). + + 7.c.i. Let kValue be ? Get(O, Pk). +---*/ + +const locales = { + length: 8, + 1: 'en-US', + 3: 'de-DE', + 5: 'en-IN', + 7: 'en-GB' +}; + +const actualLookups = []; +const expectedLookups = Object.keys(locales); + +const handlers = { + get(obj, prop) { + actualLookups.push(prop); + return Reflect.get(...arguments); + } +}; + +const proxyLocales = new Proxy(locales, handlers); + +const nf = new Intl.NumberFormat(proxyLocales); + +expectedLookups.forEach(lookup => assert(actualLookups.indexOf(lookup) != -1)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-hasproperty.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-hasproperty.js new file mode 100644 index 0000000000..93784924ae --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-hasproperty.js @@ -0,0 +1,41 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that HasProperty(O, Pk) is properly called within the constructor for + Intl.NumberFormat +info: | + 9.2.1 CanonicalizeLocaleList ( locales ) + + 7.b. Let kPresent be ? HasProperty(O, Pk). +---*/ + +const locales = { + length: 8, + 1: 'en-US', + 3: 'de-DE', + 5: 'en-IN', + 7: 'en-GB' +}; + +const actualLookups = []; + +const handlers = { + has(obj, prop) { + actualLookups.push(prop); + return Reflect.has(...arguments); + } +}; + +const proxyLocales = new Proxy(locales, handlers); + +const nf = new Intl.NumberFormat(proxyLocales); + +assert.sameValue(actualLookups.length, locales.length); +for (let index in actualLookups) { + assert.sameValue(actualLookups[index], String(index)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-string.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-string.js new file mode 100644 index 0000000000..b2703b1def --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-string.js @@ -0,0 +1,27 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that passing a string value to the Intl.NumberFormat constructor is + equivalent to passing an Array containing the same string value. +info: | + 9.2.1 CanonicalizeLocaleList ( locales ) + + 3 .If Type(locales) is String, then + a. Let O be CreateArrayFromList(« locales »). +---*/ + +const actual = Intl.NumberFormat('en-US').resolvedOptions(); +const expected = Intl.NumberFormat(['en-US']).resolvedOptions(); + +assert.sameValue(actual.locale, expected.locale); +assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits); +assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits); +assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits); +assert.sameValue(actual.numberingSystem, expected.numberingSystem); +assert.sameValue(actual.style, expected.style); +assert.sameValue(actual.useGrouping, expected.useGrouping); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-locales-toobject.js b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-toobject.js new file mode 100644 index 0000000000..08df0d0580 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-locales-toobject.js @@ -0,0 +1,41 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that Intl.NumberFormat contructor converts the locales argument + to an object using `ToObject` (7.1.13). +info: | + 9.2.1 CanonicalizeLocaleList + + 4.a. Let O be ? ToObject(locales). +---*/ + +const toObjectResults = [ + [true, new Boolean(true)], + [42, new Number(42)], + [{}, {}], + [Symbol(), Object(Symbol())] +]; + +// Test if ToObject is used to convert primitives to Objects. +toObjectResults.forEach(pair => { + const [value, result] = pair; + const actual = new Intl.NumberFormat(value).resolvedOptions(); + const expected = new Intl.NumberFormat(result).resolvedOptions() + + assert.sameValue(actual.locale, expected.locale); + assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits); + assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits); + assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits); + assert.sameValue(actual.numberingSystem, expected.numberingSystem); + assert.sameValue(actual.style, expected.style); + assert.sameValue(actual.useGrouping, expected.useGrouping); +}); + +// ToObject throws a TypeError for undefined and null, but it's not called +// when locales is undefined. +assert.throws(TypeError, () => new Intl.NumberFormat(null)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-notation.js b/js/src/tests/test262/intl402/NumberFormat/constructor-notation.js new file mode 100644 index 0000000000..91dc05937c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-notation.js @@ -0,0 +1,33 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks handling of the notation option to the NumberFormat constructor. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 16. Let notation be ? GetOption(options, "notation", "string", « "standard", "scientific", "engineering", "compact" », "standard"). + 17. Set numberFormat.[[Notation]] to notation. + +features: [Intl.NumberFormat-unified] +---*/ + +const values = [ + [undefined, "standard"], + ["standard"], + ["scientific"], + ["engineering"], + ["compact"], +]; + +for (const [value, expected = value] of values) { + const nf = new Intl.NumberFormat([], { + notation: value, + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue("notation" in resolvedOptions, true); + assert.sameValue(resolvedOptions.notation, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-numberingSystem-order.js b/js/src/tests/test262/intl402/NumberFormat/constructor-numberingSystem-order.js new file mode 100644 index 0000000000..67ec1db98a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-numberingSystem-order.js @@ -0,0 +1,46 @@ +// Copyright 2019 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Checks the order of getting "numberingSystem" option in the + NumberFormat is between "localeMatcher" and "style" options. +info: | + InitializeNumberFormat ( _numberFormat_, _locales_, _options_ ) + + 5. Let _matcher_ be ? GetOption(_options_, `"localeMatcher"`, `"string"`, « `"lookup"`, `"best fit"` », `"best fit"`). + ... + 7. Let _numberingSystem_ be ? GetOption(_options_, `"numberingSystem"`, `"string"`, *undefined*, *undefined*). + ... + 17. Let _style_ be ? GetOption(_options_, `"style"`, `"string"`, « `"decimal"`, `"percent"`, `"currency"` », `"decimal"`). +includes: [compareArray.js] +---*/ + +var actual = []; + +const options = { + get localeMatcher() { + actual.push("localeMatcher"); + return undefined; + }, + get numberingSystem() { + actual.push("numberingSystem"); + return undefined; + }, + get style() { + actual.push("style"); + return undefined; + }, +}; + +const expected = [ + "localeMatcher", + "numberingSystem", + "style" +]; + +let nf = new Intl.NumberFormat(undefined, options); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-numberingSystem-invalid.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-numberingSystem-invalid.js new file mode 100644 index 0000000000..40de2cd18d --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-numberingSystem-invalid.js @@ -0,0 +1,42 @@ +// Copyright 2020 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Checks error cases for the options argument to the NumberFormat constructor. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + ... + 8. If numberingSystem is not undefined, then + a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception. +---*/ + +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + numberingSystem = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidNumberingSystemOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", + "!invalid!", + "-latn-", + "latn-", + "latn--", + "latn-ca", + "latn-ca-", + "latn-ca-gregory", + "latné", + "latn编号", +]; +for (const numberingSystem of invalidNumberingSystemOptions) { + assert.throws(RangeError, function() { + new Intl.NumberFormat('en', {numberingSystem}); + }, `new Intl.NumberFormat("en", {numberingSystem: "${numberingSystem}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters.js new file mode 100644 index 0000000000..70dafd7d34 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-throwing-getters.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks the propagation of exceptions from the options for the NumberFormat constructor. +---*/ + +function CustomError() {} + +const options = [ + "localeMatcher", + "numberingSystem", + "style", + "currency", + "currencyDisplay", + "minimumIntegerDigits", + "minimumFractionDigits", + "maximumFractionDigits", + "minimumSignificantDigits", + "maximumSignificantDigits", + "useGrouping", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.NumberFormat("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-options-toobject.js b/js/src/tests/test262/intl402/NumberFormat/constructor-options-toobject.js new file mode 100644 index 0000000000..7544ad33fc --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-options-toobject.js @@ -0,0 +1,42 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that Intl.NumberFormat contructor converts the options argument + to an object using `ToObject` (7.1.13). +info: | + 11.1.2 InitializeNumberFormat + + 3.a. Let options be ? ToObject(options). +---*/ + +const toObjectResults = [ + [true, new Boolean(true)], + [42, new Number(42)], + ['foo', new String('foo')], + [{}, {}], + [Symbol(), Object(Symbol())] +]; + +// Test if ToObject is used to convert primitives to Objects. +toObjectResults.forEach(pair => { + const [value, result] = pair; + const actual = new Intl.NumberFormat(['en-US'], value).resolvedOptions(); + const expected = new Intl.NumberFormat(['en-US'], result).resolvedOptions(); + assert.sameValue(actual.locale, expected.locale); + assert.sameValue(actual.minimumIntegerDigits, expected.minimumIntegerDigits); + assert.sameValue(actual.minimumFractionDigits, expected.minimumFractionDigits); + assert.sameValue(actual.maximumFractionDigits, expected.maximumFractionDigits); + assert.sameValue(actual.numberingSystem, expected.numberingSystem); + assert.sameValue(actual.style, expected.style); + assert.sameValue(actual.useGrouping, expected.useGrouping); + +}); + +// ToObject throws a TypeError for undefined and null, but it's not called +// when options is undefined. +assert.throws(TypeError, () => new Intl.NumberFormat(['en-US'], null)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-order.js b/js/src/tests/test262/intl402/NumberFormat/constructor-order.js new file mode 100644 index 0000000000..92059305f7 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-order.js @@ -0,0 +1,30 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks handling of the unit option with the currency style. +info: | + SetNumberFormatUnitOptions ( intlObj, options ) + + 5. Let currency be ? GetOption(options, "currency", "string", undefined, undefined). + 6. If currency is not undefined, then + a. If the result of IsWellFormedCurrencyCode(currency) is false, throw a RangeError exception. + 7. If style is "currency" and currency is undefined, throw a TypeError exception. + ... + 10. Let unit be ? GetOption(options, "unit", "string", undefined, undefined). + 11. If unit is not undefined, then + a. If the result of IsWellFormedUnitIdentifier(unit) is false, throw a RangeError exception. + 12. If style is "unit" and unit is undefined, throw a TypeError exception. +features: [Intl.NumberFormat-unified] +---*/ + +assert.throws(TypeError, () => { + new Intl.NumberFormat([], { style: "currency", unit: "test" }) +}); + +assert.throws(RangeError, () => { + new Intl.NumberFormat([], { style: "unit", currency: "test" }) +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay.js b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay.js new file mode 100644 index 0000000000..2b458367c4 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-signDisplay.js @@ -0,0 +1,33 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 23. Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero" », "auto"). + 24. Set numberFormat.[[SignDisplay]] to signDisplay. + +features: [Intl.NumberFormat-unified] +---*/ + +const values = [ + [undefined, "auto"], + ["auto"], + ["never"], + ["always"], + ["exceptZero"], +]; + +for (const [value, expected = value] of values) { + const nf = new Intl.NumberFormat([], { + signDisplay: value, + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue("signDisplay" in resolvedOptions, true); + assert.sameValue(resolvedOptions.signDisplay, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js b/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js new file mode 100644 index 0000000000..b14981cf7a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-unit.js @@ -0,0 +1,108 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks handling of the unit style. +features: [Intl.NumberFormat-unified] +---*/ + +assert.throws(TypeError, () => { + new Intl.NumberFormat([], { + style: "unit", + }) +}); + +for (const unit of ["test", "MILE", "kB"]) { + // Throws RangeError for invalid unit identifier. + for (const style of [undefined, "decimal", "unit"]) { + assert.throws(RangeError, () => { + new Intl.NumberFormat([], { style, unit }) + }, `{ style: ${style}, unit: ${unit} }`); + } + + const style = "currency"; + + // Throws TypeError because "currency" option is missing. + assert.throws(TypeError, () => { + new Intl.NumberFormat([], { style, unit }) + }, `{ style: ${style}, unit: ${unit} }`); + + // Throws RangeError for invalid unit identifier. + assert.throws(RangeError, () => { + new Intl.NumberFormat([], { style, unit, currency: "USD" }) + }, `{ style: ${style}, unit: ${unit} }`); +} + +const nf = new Intl.NumberFormat([], { + style: "percent", +}); +assert.sameValue(nf.resolvedOptions().style, "percent"); +assert.sameValue("unit" in nf.resolvedOptions(), false); +assert.sameValue(nf.resolvedOptions().unit, undefined); + +function check(unit) { + const nf = new Intl.NumberFormat([], { + style: "unit", + unit, + }); + const options = nf.resolvedOptions(); + assert.sameValue(options.style, "unit"); + assert.sameValue(options.unit, unit); +} + +const units = [ + "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", + "mile", + "mile-scandinavian", + "millimeter", + "milliliter", + "millisecond", + "minute", + "month", + "ounce", + "percent", + "petabyte", + "pound", + "second", + "stone", + "terabit", + "terabyte", + "week", + "yard", + "year", +]; + +for (const simpleUnit of units) { + check(simpleUnit); + for (const simpleUnit2 of units) { + check(simpleUnit + "-per-" + simpleUnit2); + check(simpleUnit2 + "-per-" + simpleUnit); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/constructor-unitDisplay.js b/js/src/tests/test262/intl402/NumberFormat/constructor-unitDisplay.js new file mode 100644 index 0000000000..54b1594aa5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/constructor-unitDisplay.js @@ -0,0 +1,68 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 23. Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero" », "auto"). + 24. Set numberFormat.[[SignDisplay]] to signDisplay. + +features: [Intl.NumberFormat-unified] +---*/ + +const values = [ + [undefined, "short"], + ["short"], + ["narrow"], + ["long"], +]; + +for (const [value, expected = value] of values) { + const nf = new Intl.NumberFormat([], { + style: "unit", + unitDisplay: value, + unit: "hour", + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue("unitDisplay" in resolvedOptions, true); + assert.sameValue(resolvedOptions.unitDisplay, expected); +} + +for (const [value, expected = value] of values) { + const nf = new Intl.NumberFormat([], { + style: "unit", + unitDisplay: value, + unit: "percent", + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue("unitDisplay" in resolvedOptions, true); + assert.sameValue(resolvedOptions.unitDisplay, expected); +} + +for (const [value] of values) { + const nf = new Intl.NumberFormat([], { + style: "percent", + unitDisplay: value, + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue("unitDisplay" in resolvedOptions, false); + assert.sameValue(resolvedOptions.unitDisplay, undefined); +} + +const invalidValues = [ + "", + "Short", + "s", + "\u017Fhort", +]; + +for (const unitDisplay of invalidValues) { + assert.throws(RangeError, () => { + new Intl.NumberFormat([], { unitDisplay }); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/currency-code-invalid.js b/js/src/tests/test262/intl402/NumberFormat/currency-code-invalid.js new file mode 100644 index 0000000000..22c43ffb18 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/currency-code-invalid.js @@ -0,0 +1,29 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.3.1_b +description: Tests that invalid currency codes are not accepted. +author: Norbert Lindenberg +---*/ + +var invalidCurrencyCodes = [ + "", + "€", + "$", + "SFr.", + "DM", + "KR₩", + "702", + "ßP", + "ınr" +]; + +invalidCurrencyCodes.forEach(function (code) { + // this must throw an exception for an invalid currency code + assert.throws(RangeError, function() { + var format = new Intl.NumberFormat(["de-de"], {style: "currency", currency: code}); + }, "Invalid currency code '" + code + "' was not rejected."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/currency-code-well-formed.js b/js/src/tests/test262/intl402/NumberFormat/currency-code-well-formed.js new file mode 100644 index 0000000000..0b76772b1e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/currency-code-well-formed.js @@ -0,0 +1,24 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.3.1_a +description: Tests that well-formed currency codes are accepted. +author: Norbert Lindenberg +---*/ + +var wellFormedCurrencyCodes = [ + "BOB", + "EUR", + "usd", // currency codes are case-insensitive + "XdR", + "xTs" +]; + +wellFormedCurrencyCodes.forEach(function (code) { + // this must not throw an exception for a valid currency code + var format = new Intl.NumberFormat(["de-de"], {style: "currency", currency: code}); + assert.sameValue(format.resolvedOptions().currency, code.toUpperCase(), "Currency " + code + " was not correctly accepted."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/currency-digits.js b/js/src/tests/test262/intl402/NumberFormat/currency-digits.js new file mode 100644 index 0000000000..adba633083 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/currency-digits.js @@ -0,0 +1,191 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_20_c +description: > + Tests that the number of fractional digits is determined correctly + for currencies. +author: Norbert Lindenberg +---*/ + +// data from https://www.currency-iso.org/dam/downloads/lists/list_one.xml, 2017-09-22 +var currencyDigits = { + AED: 2, + AFN: 2, + ALL: 2, + AMD: 2, + ANG: 2, + AOA: 2, + ARS: 2, + AUD: 2, + AWG: 2, + AZN: 2, + BAM: 2, + BBD: 2, + BDT: 2, + BGN: 2, + BHD: 3, + BIF: 0, + BMD: 2, + BND: 2, + BOB: 2, + BOV: 2, + BRL: 2, + BSD: 2, + BTN: 2, + BWP: 2, + BYN: 2, + BZD: 2, + CAD: 2, + CDF: 2, + CHE: 2, + CHF: 2, + CHW: 2, + CLF: 4, + CLP: 0, + CNY: 2, + COP: 2, + COU: 2, + CRC: 2, + CUC: 2, + CUP: 2, + CVE: 2, + CZK: 2, + DJF: 0, + DKK: 2, + DOP: 2, + DZD: 2, + EGP: 2, + ERN: 2, + ETB: 2, + EUR: 2, + FJD: 2, + FKP: 2, + GBP: 2, + GEL: 2, + GHS: 2, + GIP: 2, + GMD: 2, + GNF: 0, + GTQ: 2, + GYD: 2, + HKD: 2, + HNL: 2, + HRK: 2, + HTG: 2, + HUF: 2, + IDR: 2, + ILS: 2, + INR: 2, + IQD: 3, + IRR: 2, + ISK: 0, + JMD: 2, + JOD: 3, + JPY: 0, + KES: 2, + KGS: 2, + KHR: 2, + KMF: 0, + KPW: 2, + KRW: 0, + KWD: 3, + KYD: 2, + KZT: 2, + LAK: 2, + LBP: 2, + LKR: 2, + LRD: 2, + LSL: 2, + LYD: 3, + MAD: 2, + MDL: 2, + MGA: 2, + MKD: 2, + MMK: 2, + MNT: 2, + MOP: 2, + MRO: 2, + MUR: 2, + MVR: 2, + MWK: 2, + MXN: 2, + MXV: 2, + MYR: 2, + MZN: 2, + NAD: 2, + NGN: 2, + NIO: 2, + NOK: 2, + NPR: 2, + NZD: 2, + OMR: 3, + PAB: 2, + PEN: 2, + PGK: 2, + PHP: 2, + PKR: 2, + PLN: 2, + PYG: 0, + QAR: 2, + RON: 2, + RSD: 2, + RUB: 2, + RWF: 0, + SAR: 2, + SBD: 2, + SCR: 2, + SDG: 2, + SEK: 2, + SGD: 2, + SHP: 2, + SLL: 2, + SOS: 2, + SRD: 2, + SSP: 2, + STD: 2, + SVC: 2, + SYP: 2, + SZL: 2, + THB: 2, + TJS: 2, + TMT: 2, + TND: 3, + TOP: 2, + TRY: 2, + TTD: 2, + TWD: 2, + TZS: 2, + UAH: 2, + UGX: 0, + USD: 2, + USN: 2, + UYI: 0, + UYU: 2, + UZS: 2, + VEF: 2, + VND: 0, + VUV: 0, + WST: 2, + XAF: 0, + XCD: 2, + XOF: 0, + XPF: 0, + YER: 2, + ZAR: 2, + ZMW: 2, + ZWL: 2, +}; + +Object.getOwnPropertyNames(currencyDigits).forEach(function (currency) { + var digits = currencyDigits[currency]; + var format = Intl.NumberFormat([], {style: "currency", currency: currency}); + var min = format.resolvedOptions().minimumFractionDigits; + var max = format.resolvedOptions().maximumFractionDigits; + assert.sameValue(min, digits, "Didn't get correct minimumFractionDigits for currency " + currency + "."); + assert.sameValue(max, digits, "Didn't get correct maximumFractionDigits for currency " + currency + "."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/currencyDisplay-unit.js b/js/src/tests/test262/intl402/NumberFormat/currencyDisplay-unit.js new file mode 100644 index 0000000000..bc760e490c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/currencyDisplay-unit.js @@ -0,0 +1,42 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-setnumberformatunitoptions +description: Checks handling of valid values for the numeric option to the NumberFormat constructor. +info: | + SetNumberFormatUnitOptions ( intlObj, options ) + + 6. Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol"). + 11. If style is "currency", then + f. Set intlObj.[[CurrencyDisplay]] to currencyDisplay. + +features: [Intl.NumberFormat-unified] +---*/ + +const validOptions = [ + [undefined, "symbol"], + ["narrowSymbol", "narrowSymbol"], + [{ toString() { return "narrowSymbol"; } }, "narrowSymbol"], +]; + +for (const [validOption, expected] of validOptions) { + const nf = new Intl.NumberFormat([], { + "style": "currency", + "currency": "EUR", + "currencyDisplay": validOption, + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue(resolvedOptions.currencyDisplay, expected); +} + +for (const [validOption] of validOptions) { + const nf = new Intl.NumberFormat([], { + "style": "percent", + "currencyDisplay": validOption, + }); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue(resolvedOptions.currencyDisplay, undefined); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/default-minimum-singificant-digits.js b/js/src/tests/test262/intl402/NumberFormat/default-minimum-singificant-digits.js new file mode 100644 index 0000000000..a9cab8c641 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/default-minimum-singificant-digits.js @@ -0,0 +1,23 @@ +// Copyright (C) 2017 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Tests that the default value of minimumSignificantDigits is 1. +esid: sec-setnfdigitoptions +---*/ + +// maximumSignificantDigits needs to be in range from minimumSignificantDigits +// to 21 (both inclusive). Setting maximumSignificantDigits to 0 will throw a +// RangeError if the (default) minimumSignificantDigits is at least 1. +assert.throws(RangeError, function() { + Intl.NumberFormat(undefined, {maximumSignificantDigits: 0}); +}); + +// If nothing is thrown, check that the options are resolved appropriately. +var res = Intl.NumberFormat(undefined, {maximumSignificantDigits: 1}) + +assert.sameValue(Object.getPrototypeOf(res), Intl.NumberFormat.prototype, 'result is an instance of NumberFormat') +assert.sameValue(res.resolvedOptions().minimumSignificantDigits, 1, 'default minimumSignificantDigits') +assert.sameValue(res.resolvedOptions().maximumSignificantDigits, 1, 'sets maximumSignificantDigits') + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/default-options-object-prototype.js b/js/src/tests/test262/intl402/NumberFormat/default-options-object-prototype.js new file mode 100644 index 0000000000..8f43d572f5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/default-options-object-prototype.js @@ -0,0 +1,24 @@ +// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Monkey-patching Object.prototype does not change the default + options for NumberFormat as a null prototype is used. +info: | + InitializeNumberFormat ( numberFormat, locales, options ) + + 1. If _options_ is *undefined*, then + 1. Let _options_ be ObjectCreate(*null*). +---*/ + +let defaultMaximumFractionDigits = + new Intl.NumberFormat("en").resolvedOptions().maximumFractionDigits; + +Object.prototype.maximumFractionDigits = 1; +let formatter = new Intl.NumberFormat("en"); +assert.sameValue(formatter.resolvedOptions().maximumFractionDigits, + defaultMaximumFractionDigits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/dft-currency-mnfd-range-check-mxfd.js b/js/src/tests/test262/intl402/NumberFormat/dft-currency-mnfd-range-check-mxfd.js new file mode 100644 index 0000000000..3db6686349 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/dft-currency-mnfd-range-check-mxfd.js @@ -0,0 +1,24 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-setnfdigitoptions +description: > + When a currency is used in Intl.NumberFormat and minimumFractionDigits is + not provided, maximumFractionDigits should be set as provided. +---*/ + +assert.sameValue((new Intl.NumberFormat('en', { + style: 'currency', + currency: 'USD', + maximumFractionDigits: 1 +})).resolvedOptions().maximumFractionDigits, 1); + +assert.sameValue((new Intl.NumberFormat('en', { + style: 'currency', + currency: 'CLF', + maximumFractionDigits: 3 +})).resolvedOptions().maximumFractionDigits, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/fraction-digit-options-read-once.js b/js/src/tests/test262/intl402/NumberFormat/fraction-digit-options-read-once.js new file mode 100644 index 0000000000..faf89e8f9d --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/fraction-digit-options-read-once.js @@ -0,0 +1,20 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-setnfdigitoptions +description: > + The maximum and minimum fraction digits properties should be read from + the options bag exactly once from the NumberFormat constructor. +info: Regression test for https://bugs.chromium.org/p/v8/issues/detail?id=6015 +---*/ + +var calls = []; + +new Intl.NumberFormat("en", { get minimumFractionDigits() { calls.push('minimumFractionDigits') }, + get maximumFractionDigits() { calls.push('maximumFractionDigits') } }); +assert.sameValue(calls.length, 2); +assert.sameValue(calls[0], 'minimumFractionDigits'); +assert.sameValue(calls[1], 'maximumFractionDigits'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/ignore-invalid-unicode-ext-values.js b/js/src/tests/test262/intl402/NumberFormat/ignore-invalid-unicode-ext-values.js new file mode 100644 index 0000000000..01ac841152 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/ignore-invalid-unicode-ext-values.js @@ -0,0 +1,38 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.2.3_b +description: > + Tests that Intl.NumberFormat does not accept Unicode locale + extension keys and values that are not allowed. +author: Norbert Lindenberg +---*/ + +var locales = ["ja-JP", "zh-Hans-CN", "zh-Hant-TW"]; +var input = 1234567.89; + +locales.forEach(function (locale) { + var defaultNumberFormat = new Intl.NumberFormat([locale]); + var defaultOptions = defaultNumberFormat.resolvedOptions(); + var defaultOptionsJSON = JSON.stringify(defaultOptions); + var defaultLocale = defaultOptions.locale; + var defaultFormatted = defaultNumberFormat.format(input); + + var keyValues = { + "cu": ["USD", "EUR", "JPY", "CNY", "TWD", "invalid"], + "nu": ["native", "traditio", "finance", "invalid"] + }; + + Object.getOwnPropertyNames(keyValues).forEach(function (key) { + keyValues[key].forEach(function (value) { + var numberFormat = new Intl.NumberFormat([locale + "-u-" + key + "-" + value]); + var options = numberFormat.resolvedOptions(); + assert.sameValue(options.locale, defaultLocale, "Locale " + options.locale + " is affected by key " + key + "; value " + value + "."); + assert.sameValue(JSON.stringify(options), defaultOptionsJSON, "Resolved options " + JSON.stringify(options) + " are affected by key " + key + "; value " + value + "."); + assert.sameValue(numberFormat.format(input), defaultFormatted, "Formatted value " + numberFormat.format(input) + " is affected by key " + key + "; value " + value + "."); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/instance-proto-and-extensible.js b/js/src/tests/test262/intl402/NumberFormat/instance-proto-and-extensible.js new file mode 100644 index 0000000000..0a2b3e8999 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/instance-proto-and-extensible.js @@ -0,0 +1,19 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.3 +description: > + Tests that objects constructed by Intl.NumberFormat have the + specified internal properties. +author: Norbert Lindenberg +---*/ + +var obj = new Intl.NumberFormat(); + +var actualPrototype = Object.getPrototypeOf(obj); +assert.sameValue(actualPrototype, Intl.NumberFormat.prototype, "Prototype of object constructed by Intl.NumberFormat isn't Intl.NumberFormat.prototype."); + +assert(Object.isExtensible(obj), "Object constructed by Intl.NumberFormat must be extensible."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol-on-unwrap.js b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol-on-unwrap.js new file mode 100644 index 0000000000..aac9c4fc1e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol-on-unwrap.js @@ -0,0 +1,34 @@ +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-unwrapnumberformat +description: > + Tests that [[FallbackSymbol]]'s [[Description]] is "IntlLegacyConstructedSymbol" if normative optional is implemented. +author: Yusuke Suzuki +features: [intl-normative-optional] +---*/ + +let object = new Intl.NumberFormat(); +let newObject = Intl.NumberFormat.call(object); +let symbol = null; +let error = null; +try { + let proxy = new Proxy(newObject, { + get(target, property) { + symbol = property; + return target[property]; + } + }); + Intl.NumberFormat.prototype.resolvedOptions.call(proxy); +} catch (e) { + // If normative optional is not implemented, an error will be thrown. + error = e; + assert(error instanceof TypeError); +} +if (error === null) { + assert.sameValue(typeof symbol, "symbol"); + assert.sameValue(symbol.description, "IntlLegacyConstructedSymbol"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol.js b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol.js new file mode 100644 index 0000000000..bf038e96ad --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/intl-legacy-constructed-symbol.js @@ -0,0 +1,20 @@ +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat +description: > + Tests that [[FallbackSymbol]]'s [[Description]] is "IntlLegacyConstructedSymbol" if normative optional is implemented. +author: Yusuke Suzuki +features: [intl-normative-optional] +---*/ + +let object = new Intl.NumberFormat(); +let newObject = Intl.NumberFormat.call(object); +let symbols = Object.getOwnPropertySymbols(newObject); +if (symbols.length !== 0) { + assert.sameValue(symbols.length, 1); + assert.sameValue(symbols[0].description, "IntlLegacyConstructedSymbol"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/legacy-regexp-statics-not-modified.js b/js/src/tests/test262/intl402/NumberFormat/legacy-regexp-statics-not-modified.js new file mode 100644 index 0000000000..ba010300c2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/legacy-regexp-statics-not-modified.js @@ -0,0 +1,21 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_a +description: > + Tests that constructing a NumberFormat doesn't create or modify + unwanted properties on the RegExp constructor. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testForUnwantedRegExpChanges(function () { + new Intl.NumberFormat("de-DE-u-nu-latn"); +}); + +testForUnwantedRegExpChanges(function () { + new Intl.NumberFormat("de-DE-u-nu-latn", {style: "currency", currency: "EUR"}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/length.js b/js/src/tests/test262/intl402/NumberFormat/length.js new file mode 100644 index 0000000000..027ddb1783 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/length.js @@ -0,0 +1,36 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat +description: > + Intl.NumberFormat.length is 0. +info: | + Intl.NumberFormat ( [ locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.NumberFormat.length, 0); + +verifyProperty(Intl.NumberFormat, 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/name.js b/js/src/tests/test262/intl402/NumberFormat/name.js new file mode 100644 index 0000000000..aa918694fc --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/name.js @@ -0,0 +1,29 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat +description: > + Intl.NumberFormat.name is "NumberFormat". +info: | + 11.2.1 Intl.NumberFormat ([ locales [ , options ]]) + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.NumberFormat, 'name', { + value: 'NumberFormat', + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/numbering-system-options.js b/js/src/tests/test262/intl402/NumberFormat/numbering-system-options.js new file mode 100644 index 0000000000..6c199f9543 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/numbering-system-options.js @@ -0,0 +1,64 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializenumberformat +description: > + Tests that the options numberingSystem and calendar can be set through + either the locale or the options. +author: Norbert Lindenberg, Daniel Ehrenberg +---*/ + +let defaultLocale = new Intl.NumberFormat().resolvedOptions().locale; + +let supportedNumberingSystems = ["latn", "arab"].filter(nu => + new Intl.NumberFormat(defaultLocale + "-u-nu-" + nu) + .resolvedOptions().numberingSystem === nu +); + +let options = [ + {key: "nu", property: "numberingSystem", type: "string", values: supportedNumberingSystems}, +]; + +options.forEach(function (option) { + let numberFormat, opt, result; + + // find out which values are supported for a property in the default locale + let supportedValues = []; + option.values.forEach(function (value) { + opt = {}; + opt[option.property] = value; + numberFormat = new Intl.NumberFormat([defaultLocale], opt); + result = numberFormat.resolvedOptions()[option.property]; + if (result !== undefined && supportedValues.indexOf(result) === -1) { + supportedValues.push(result); + } + }); + + // verify that the supported values can also be set through the locale + supportedValues.forEach(function (value) { + numberFormat = new Intl.NumberFormat([defaultLocale + "-u-" + option.key + "-" + value]); + result = numberFormat.resolvedOptions()[option.property]; + assert.sameValue(result, value, "Property " + option.property + " couldn't be set through locale extension key " + option.key + "."); + }); + + // verify that the options setting overrides the locale setting + supportedValues.forEach(function (value) { + let otherValue; + option.values.forEach(function (possibleValue) { + if (possibleValue !== value) { + otherValue = possibleValue; + } + }); + if (otherValue !== undefined) { + opt = {}; + opt[option.property] = value; + numberFormat = new Intl.NumberFormat([defaultLocale + "-u-" + option.key + "-" + otherValue], opt); + result = numberFormat.resolvedOptions()[option.property]; + assert.sameValue(result, value, "Options value for property " + option.property + " doesn't override locale extension key " + option.key + "."); + } + }); +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prop-desc.js new file mode 100644 index 0000000000..589dbe8e32 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prop-desc.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat-intro +description: > + "NumberFormat" property of Intl. +info: | + Intl.NumberFormat (...) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl, 'NumberFormat', { + writable: true, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/NumberFormat/proto-from-ctor-realm.js new file mode 100644 index 0000000000..a8e2be5373 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/proto-from-ctor-realm.js @@ -0,0 +1,60 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.NumberFormat ( [ locales [ , options ] ] ) + + 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget. + 2. Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget, "%NumberFormatPrototype%", « ... »). + ... + 6. Return numberFormat. + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var nf; + +newTarget.prototype = undefined; +nf = Reflect.construct(Intl.NumberFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +nf = Reflect.construct(Intl.NumberFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = true; +nf = Reflect.construct(Intl.NumberFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = 'str'; +nf = Reflect.construct(Intl.NumberFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +nf = Reflect.construct(Intl.NumberFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = 0; +nf = Reflect.construct(Intl.NumberFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(nf), other.Intl.NumberFormat.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/builtin.js new file mode 100644 index 0000000000..95eef9d6b3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/builtin.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.3_L15 +description: > + Tests that Intl.NumberFormat.prototype meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +---*/ + +assert(Object.isExtensible(Intl.NumberFormat.prototype), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat.prototype), Object.prototype, + "Built-in prototype objects must have Object.prototype as their prototype."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..9e3cbd437e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.constructor +description: > + "constructor" property of Intl.NumberFormat.prototype. +info: | + Intl.NumberFormat.prototype.constructor + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.NumberFormat.prototype, "constructor"); +verifyWritable(Intl.NumberFormat.prototype, "constructor"); +verifyConfigurable(Intl.NumberFormat.prototype, "constructor"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/value.js b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/value.js new file mode 100644 index 0000000000..28cb427436 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/constructor/value.js @@ -0,0 +1,14 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.1 +description: > + Tests that Intl.NumberFormat.prototype.constructor is the + Intl.NumberFormat. +author: Roozbeh Pournader +---*/ + +assert.sameValue(Intl.NumberFormat.prototype.constructor, Intl.NumberFormat, "Intl.NumberFormat.prototype.constructor is not the same as Intl.NumberFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js new file mode 100644 index 0000000000..f1817ba06f --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/bound-to-numberformat-instance.js @@ -0,0 +1,37 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_1_c +description: Tests that format function is bound to its Intl.NumberFormat. +author: Norbert Lindenberg +---*/ + +var numbers = [0, -0, 1, -1, 5.5, 123, -123, -123.45, 123.44501, 0.001234, + -0.00000000123, 0.00000000000000000000000000000123, 1.2, 0.0000000012344501, + 123445.01, 12344501000000000000000000000000000, -12344501000000000000000000000000000, + Infinity, -Infinity, NaN]; +var locales = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]]; +var options = [ + undefined, + {style: "percent"}, + {style: "currency", currency: "EUR", currencyDisplay: "symbol"}, + {style: "currency", currency: "IQD", currencyDisplay: "symbol"}, + {style: "currency", currency: "KMF", currencyDisplay: "symbol"}, + {style: "currency", currency: "CLF", currencyDisplay: "symbol"}, + {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3} +]; + +locales.forEach(function (locales) { + options.forEach(function (options) { + var formatObj = new Intl.NumberFormat(locales, options); + var formatFunc = formatObj.format; + numbers.forEach(function (number) { + var referenceFormatted = formatObj.format(number); + var formatted = formatFunc(number); + assert.sameValue(referenceFormatted, formatted, "format function produces different result than format method for locales " + locales + "; options: " + (options ? JSON.stringify(options) : options) + "."); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/builtin.js new file mode 100644 index 0000000000..6e264f8d26 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/builtin.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.3.2_L15 +description: > + Tests that the getter for Intl.NumberFormat.prototype.format + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language + Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +var formatFn = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get; + +assert.sameValue(Object.prototype.toString.call(formatFn), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatFn), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatFn), Function.prototype); + +assert.sameValue(formatFn.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatFn), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/default-value.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/default-value.js new file mode 100644 index 0000000000..b4ee1e8fde --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/default-value.js @@ -0,0 +1,25 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-number-format-functions +description: > + Tests that the default value for the argument of + Intl.NumberFormat.prototype.format (value) is undefined. +info: | + 11.1.4 Number Format Functions + + 3. If value is not provided, let value be undefined. + 4. Let x be ? ToNumber(value). +---*/ + +const nf = new Intl.NumberFormat(); + +// In most locales this is string "NaN", but there are exceptions, cf. "ليس رقم" +// in Arabic, "epäluku" in Finnish, "не число" in Russian, "son emas" in Uzbek etc. +const resultNaN = nf.format(NaN); + +assert.sameValue(nf.format(), resultNaN); +assert.sameValue(nf.format(undefined), resultNaN); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-de-DE.js new file mode 100644 index 0000000000..8c70c5e94a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-de-DE.js @@ -0,0 +1,78 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the engineering and scientific notations. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + 0.000345, + "345E-6", + "3,45E-4", + ], + [ + 0.345, + "345E-3", + "3,45E-1", + ], + [ + 3.45, + "3,45E0", + "3,45E0", + ], + [ + 34.5, + "34,5E0", + "3,45E1", + ], + [ + 543, + "543E0", + "5,43E2", + ], + [ + 5430, + "5,43E3", + "5,43E3", + ], + [ + 543000, + "543E3", + "5,43E5", + ], + [ + 543211.1, + "543,211E3", + "5,432E5", + ], + [ + -Infinity, + "-∞", + "-∞", + ], + [ + Infinity, + "∞", + "∞", + ], + [ + NaN, + "NaN", + "NaN", + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("de-DE", { notation: "engineering" })); + assert.sameValue(nfEngineering.format(number), engineering); + const nfScientific = (new Intl.NumberFormat("de-DE", { notation: "scientific" })); + assert.sameValue(nfScientific.format(number), scientific); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-en-US.js new file mode 100644 index 0000000000..5d8c94ce9a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-en-US.js @@ -0,0 +1,78 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the engineering and scientific notations. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + 0.000345, + "345E-6", + "3.45E-4", + ], + [ + 0.345, + "345E-3", + "3.45E-1", + ], + [ + 3.45, + "3.45E0", + "3.45E0", + ], + [ + 34.5, + "34.5E0", + "3.45E1", + ], + [ + 543, + "543E0", + "5.43E2", + ], + [ + 5430, + "5.43E3", + "5.43E3", + ], + [ + 543000, + "543E3", + "5.43E5", + ], + [ + 543211.1, + "543.211E3", + "5.432E5", + ], + [ + -Infinity, + "-∞", + "-∞", + ], + [ + Infinity, + "∞", + "∞", + ], + [ + NaN, + "NaN", + "NaN", + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("en-US", { notation: "engineering" })); + assert.sameValue(nfEngineering.format(number), engineering); + const nfScientific = (new Intl.NumberFormat("en-US", { notation: "scientific" })); + assert.sameValue(nfScientific.format(number), scientific); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ja-JP.js new file mode 100644 index 0000000000..85dd68d736 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ja-JP.js @@ -0,0 +1,78 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the engineering and scientific notations. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + 0.000345, + "345E-6", + "3.45E-4", + ], + [ + 0.345, + "345E-3", + "3.45E-1", + ], + [ + 3.45, + "3.45E0", + "3.45E0", + ], + [ + 34.5, + "34.5E0", + "3.45E1", + ], + [ + 543, + "543E0", + "5.43E2", + ], + [ + 5430, + "5.43E3", + "5.43E3", + ], + [ + 543000, + "543E3", + "5.43E5", + ], + [ + 543211.1, + "543.211E3", + "5.432E5", + ], + [ + -Infinity, + "-∞", + "-∞", + ], + [ + Infinity, + "∞", + "∞", + ], + [ + NaN, + "NaN", + "NaN", + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("ja-JP", { notation: "engineering" })); + assert.sameValue(nfEngineering.format(number), engineering); + const nfScientific = (new Intl.NumberFormat("ja-JP", { notation: "scientific" })); + assert.sameValue(nfScientific.format(number), scientific); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ko-KR.js new file mode 100644 index 0000000000..23b5632f0b --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-ko-KR.js @@ -0,0 +1,78 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the engineering and scientific notations. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + 0.000345, + "345E-6", + "3.45E-4", + ], + [ + 0.345, + "345E-3", + "3.45E-1", + ], + [ + 3.45, + "3.45E0", + "3.45E0", + ], + [ + 34.5, + "34.5E0", + "3.45E1", + ], + [ + 543, + "543E0", + "5.43E2", + ], + [ + 5430, + "5.43E3", + "5.43E3", + ], + [ + 543000, + "543E3", + "5.43E5", + ], + [ + 543211.1, + "543.211E3", + "5.432E5", + ], + [ + -Infinity, + "-∞", + "-∞", + ], + [ + Infinity, + "∞", + "∞", + ], + [ + NaN, + "NaN", + "NaN", + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("ko-KR", { notation: "engineering" })); + assert.sameValue(nfEngineering.format(number), engineering); + const nfScientific = (new Intl.NumberFormat("ko-KR", { notation: "scientific" })); + assert.sameValue(nfScientific.format(number), scientific); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-zh-TW.js new file mode 100644 index 0000000000..5f4cacbb0b --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/engineering-scientific-zh-TW.js @@ -0,0 +1,78 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the engineering and scientific notations. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + 0.000345, + "345E-6", + "3.45E-4", + ], + [ + 0.345, + "345E-3", + "3.45E-1", + ], + [ + 3.45, + "3.45E0", + "3.45E0", + ], + [ + 34.5, + "34.5E0", + "3.45E1", + ], + [ + 543, + "543E0", + "5.43E2", + ], + [ + 5430, + "5.43E3", + "5.43E3", + ], + [ + 543000, + "543E3", + "5.43E5", + ], + [ + 543211.1, + "543.211E3", + "5.432E5", + ], + [ + -Infinity, + "-∞", + "-∞", + ], + [ + Infinity, + "∞", + "∞", + ], + [ + NaN, + "非數值", + "非數值", + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("zh-TW", { notation: "engineering" })); + assert.sameValue(nfEngineering.format(number), engineering); + const nfScientific = (new Intl.NumberFormat("zh-TW", { notation: "scientific" })); + assert.sameValue(nfScientific.format(number), scientific); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js new file mode 100644 index 0000000000..8b7870f019 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits-precision.js @@ -0,0 +1,34 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_TRF +description: > + Tests that the digits are determined correctly when specifying + pre/post decimal digits. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, + "ar", "de", "th", "ja" +]; +var numberingSystems = [ + "arab", + "latn", + "thai", + "hanidec" +]; +var testData = { + // Ref tc39/ecma402#128 + "12344501000000000000000000000000000": "12344501000000000000000000000000000.0", + "-12344501000000000000000000000000000": "-12344501000000000000000000000000000.0" +}; + +testNumberFormat(locales, numberingSystems, + {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3}, + testData); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js new file mode 100644 index 0000000000..cb9c20ad6e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-fraction-digits.js @@ -0,0 +1,57 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_TRF +description: > + Tests that the digits are determined correctly when specifying + pre/post decimal digits. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, + "ar", "de", "th", "ja" +]; +var numberingSystems = [ + "arab", + "latn", + "thai", + "hanidec" +]; +var testData = { + "0": "000.0", + "-0": "-000.0", + "123": "123.0", + "-123": "-123.0", + "12345": "12345.0", + "-12345": "-12345.0", + "123.45": "123.45", + "-123.45": "-123.45", + "123.444499": "123.444", + "-123.444499": "-123.444", + "123.444500": "123.445", + "-123.444500": "-123.445", + "123.44501": "123.445", + "-123.44501": "-123.445", + "0.001234": "000.001", + "-0.001234": "-000.001", + "0.00000000123": "000.0", + "-0.00000000123": "-000.0", + "0.00000000000000000000000000000123": "000.0", + "-0.00000000000000000000000000000123": "-000.0", + "1.2": "001.2", + "-1.2": "-001.2", + "0.0000000012344501": "000.0", + "-0.0000000012344501": "-000.0", + "123445.01": "123445.01", + "-123445.01": "-123445.01", +}; + +testNumberFormat(locales, numberingSystems, + {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3}, + testData); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-builtin.js new file mode 100644 index 0000000000..55f0ce7dd5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-builtin.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.3.2_1_a_L15 +description: > + Tests that the function returned by + Intl.NumberFormat.prototype.format meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +var formatFn = new Intl.NumberFormat().format; + +assert.sameValue(Object.prototype.toString.call(formatFn), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(formatFn), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(formatFn), Function.prototype); + +assert.sameValue(formatFn.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(formatFn), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-length.js new file mode 100644 index 0000000000..b50c428c8b --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + The length of the bound Number Format function is 1. +info: | + get Intl.NumberFormat.prototype.format + + ... + 4. If nf.[[BoundFormat]] is undefined, then + a. Let F be a new built-in function object as defined in Number Format Functions (11.1.4). + b. Let bf be BoundFunctionCreate(F, nf, « »). + c. Perform ! DefinePropertyOrThrow(bf, "length", PropertyDescriptor {[[Value]]: 1, + [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}). + ... + +includes: [propertyHelper.js] +---*/ + +var formatFn = new Intl.NumberFormat().format; + +assert.sameValue(formatFn.length, 1); + +verifyNotEnumerable(formatFn, "length"); +verifyNotWritable(formatFn, "length"); +verifyConfigurable(formatFn, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-name.js new file mode 100644 index 0000000000..4e4805928e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-function-name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.format +description: > + The bound NumberFormat format function is an anonymous function. +info: | + 11.4.3 get Intl.NumberFormat.prototype.compare + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +---*/ + +var formatFn = new Intl.NumberFormat().format; + +verifyProperty(formatFn, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-negative-numbers.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-negative-numbers.js new file mode 100644 index 0000000000..f572d31997 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-negative-numbers.js @@ -0,0 +1,23 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_FN_1 +description: > + Tests that Intl.NumberFormat.prototype.format doesn't treat all + numbers as negative. +info: | + PartitionNumberPattern ( numberFormat, x ) + 1. If x is not NaN and x < 0 or _x_ is -0, then + a. Let _x_ be -_x_. + b. Let _pattern_ be _numberFormat_.[[NegativePattern]]. +author: Roozbeh Pournader +---*/ + +var formatter = new Intl.NumberFormat(); + +assert.notSameValue(formatter.format(1), formatter.format(-1), 'Intl.NumberFormat is formatting 1 and -1 the same way.'); + +assert.notSameValue(formatter.format(0), formatter.format(-0), 'Intl.NumberFormat is formatting 0 and -0 the same way.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js new file mode 100644 index 0000000000..d6dcae7b65 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js @@ -0,0 +1,45 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_FN_2 +description: > + Tests that Intl.NumberFormat.prototype.format handles NaN, + Infinity, and -Infinity properly. +author: Roozbeh Pournader +---*/ + +// FIXME: We are only listing Numeric_Type=Decimal. May need to add more +// when the spec clarifies. Current as of Unicode 6.1. +var hasUnicodeDigits = new RegExp('.*([' + + '0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F' + + '\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF' + + '\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9' + + '\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819' + + '\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59' + + '\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9' + + '\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19' + + ']|' + + '\uD801[\uDCA0-\uDCA9]|' + + '\uD804[\uDC66-\uDC6F\uDCF0-\uDCF9\uDD36-\uDD3F\uDDD0-\uDDD9]|' + + '\uD805[\uDEC0-\uDEC9]|' + + '\uD835[\uDFCE-\uDFFF])'); + +var formatter = new Intl.NumberFormat(); +var formattedNaN = formatter.format(NaN); +var formattedInfinity = formatter.format(Infinity); +var formattedNegativeInfinity = formatter.format(-Infinity); + +assert.notSameValue(formattedNaN, formattedInfinity, 'Intl.NumberFormat formats NaN and Infinity the same way.'); + +assert.notSameValue(formattedNaN, formattedNegativeInfinity, 'Intl.NumberFormat formats NaN and negative Infinity the same way.'); + +assert.notSameValue(formattedInfinity, formattedNegativeInfinity, 'Intl.NumberFormat formats Infinity and negative Infinity the same way.'); + +assert.sameValue(hasUnicodeDigits.test(formattedNaN), false, 'Intl.NumberFormat formats NaN using a digit.'); + +assert.sameValue(hasUnicodeDigits.test(formattedInfinity), false, 'Intl.NumberFormat formats Infinity using a digit.'); + +assert.sameValue(hasUnicodeDigits.test(formattedNegativeInfinity), false, 'Intl.NumberFormat formats negative Infinity using a digit.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js new file mode 100644 index 0000000000..dfb0aa7f59 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits-precision.js @@ -0,0 +1,34 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_TRP +description: > + Tests that the digits are determined correctly when specifying + significant digits. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, + "ar", "de", "th", "ja" +]; +var numberingSystems = [ + "arab", + "latn", + "thai", + "hanidec" +]; +var testData = { + // Ref tc39/ecma402#128 + "123.44500": "123.45", + "-123.44500": "-123.45", +}; + +testNumberFormat(locales, numberingSystems, + {useGrouping: false, minimumSignificantDigits: 3, maximumSignificantDigits: 5}, + testData); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits.js new file mode 100644 index 0000000000..d9cc063af5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/format-significant-digits.js @@ -0,0 +1,57 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_TRP +description: > + Tests that the digits are determined correctly when specifying + significant digits. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var locales = [ + new Intl.NumberFormat().resolvedOptions().locale, + "ar", "de", "th", "ja" +]; +var numberingSystems = [ + "arab", + "latn", + "thai", + "hanidec" +]; +var testData = { + "0": "0.00", + "-0": "-0.00", + "123": "123", + "-123": "-123", + "12345": "12345", + "-12345": "-12345", + "123.45": "123.45", + "-123.45": "-123.45", + "123.44499": "123.44", + "-123.44499": "-123.44", + "123.44501": "123.45", + "-123.44501": "-123.45", + "0.001234": "0.001234", + "-0.001234": "-0.001234", + "0.00000000123": "0.00000000123", + "-0.00000000123": "-0.00000000123", + "0.00000000000000000000000000000123": "0.00000000000000000000000000000123", + "-0.00000000000000000000000000000123": "-0.00000000000000000000000000000123", + "1.2": "1.20", + "-1.2": "-1.20", + "0.0000000012344501": "0.0000000012345", + "-0.0000000012344501": "-0.0000000012345", + "123445.01": "123450", + "-123445.01": "-123450", + "12344501000000000000000000000000000": "12345000000000000000000000000000000", + "-12344501000000000000000000000000000": "-12345000000000000000000000000000000" +}; + +testNumberFormat(locales, numberingSystems, + {useGrouping: false, minimumSignificantDigits: 3, maximumSignificantDigits: 5}, + testData); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/length.js new file mode 100644 index 0000000000..01f08f8709 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/length.js @@ -0,0 +1,35 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + get Intl.NumberFormat.prototype.format.length is 0. +info: | + get Intl.NumberFormat.prototype.format + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format"); + +assert.sameValue(desc.get.length, 0); + +verifyNotEnumerable(desc.get, "length"); +verifyNotWritable(desc.get, "length"); +verifyConfigurable(desc.get, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/name.js new file mode 100644 index 0000000000..c223ee0ba3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/name.js @@ -0,0 +1,30 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.format +description: > + get Intl.NumberFormat.prototype.format.name is "get format". +info: | + 11.4.3 get Intl.NumberFormat.prototype.format + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format"); + +assert.sameValue(desc.get.name, "get format"); + +verifyNotEnumerable(desc.get, "name"); +verifyNotWritable(desc.get, "name"); +verifyConfigurable(desc.get, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-de-DE.js new file mode 100644 index 0000000000..bd33e60f6a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-de-DE.js @@ -0,0 +1,47 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + +const nfShort = new Intl.NumberFormat("de-DE", { + notation: "compact", + compactDisplay: "short", +}); +assert.sameValue(nfShort.format(987654321), "988\u00a0Mio."); +assert.sameValue(nfShort.format(98765432), "99\u00a0Mio."); +assert.sameValue(nfShort.format(98765), "98.765"); +assert.sameValue(nfShort.format(9876), "9876"); +assert.sameValue(nfShort.format(159), "159"); +assert.sameValue(nfShort.format(15.9), "16"); +assert.sameValue(nfShort.format(1.59), "1,6"); +assert.sameValue(nfShort.format(0.159), "0,16"); +assert.sameValue(nfShort.format(0.0159), "0,016"); +assert.sameValue(nfShort.format(0.00159), "0,0016"); +assert.sameValue(nfShort.format(-Infinity), "-∞"); +assert.sameValue(nfShort.format(Infinity), "∞"); +assert.sameValue(nfShort.format(NaN), "NaN"); + +const nfLong = new Intl.NumberFormat("de-DE", { + notation: "compact", + compactDisplay: "long", +}); +assert.sameValue(nfLong.format(987654321), "988 Millionen"); +assert.sameValue(nfLong.format(98765432), "99 Millionen"); +assert.sameValue(nfLong.format(98765), "99 Tausend"); +assert.sameValue(nfLong.format(9876), "9,9 Tausend"); +assert.sameValue(nfLong.format(159), "159"); +assert.sameValue(nfLong.format(15.9), "16"); +assert.sameValue(nfLong.format(1.59), "1,6"); +assert.sameValue(nfLong.format(0.159), "0,16"); +assert.sameValue(nfLong.format(0.0159), "0,016"); +assert.sameValue(nfLong.format(0.00159), "0,0016"); +assert.sameValue(nfLong.format(-Infinity), "-∞"); +assert.sameValue(nfLong.format(Infinity), "∞"); +assert.sameValue(nfLong.format(NaN), "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-en-US.js new file mode 100644 index 0000000000..09856d66c3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-en-US.js @@ -0,0 +1,47 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + +const nfShort = new Intl.NumberFormat("en-US", { + notation: "compact", + compactDisplay: "short", +}); +assert.sameValue(nfShort.format(987654321), "988M"); +assert.sameValue(nfShort.format(98765432), "99M"); +assert.sameValue(nfShort.format(98765), "99K"); +assert.sameValue(nfShort.format(9876), "9.9K"); +assert.sameValue(nfShort.format(159), "159"); +assert.sameValue(nfShort.format(15.9), "16"); +assert.sameValue(nfShort.format(1.59), "1.6"); +assert.sameValue(nfShort.format(0.159), "0.16"); +assert.sameValue(nfShort.format(0.0159), "0.016"); +assert.sameValue(nfShort.format(0.00159), "0.0016"); +assert.sameValue(nfShort.format(-Infinity), "-∞"); +assert.sameValue(nfShort.format(Infinity), "∞"); +assert.sameValue(nfShort.format(NaN), "NaN"); + +const nfLong = new Intl.NumberFormat("en-US", { + notation: "compact", + compactDisplay: "long", +}); +assert.sameValue(nfLong.format(987654321), "988 million"); +assert.sameValue(nfLong.format(98765432), "99 million"); +assert.sameValue(nfLong.format(98765), "99 thousand"); +assert.sameValue(nfLong.format(9876), "9.9 thousand"); +assert.sameValue(nfLong.format(159), "159"); +assert.sameValue(nfLong.format(15.9), "16"); +assert.sameValue(nfLong.format(1.59), "1.6"); +assert.sameValue(nfLong.format(0.159), "0.16"); +assert.sameValue(nfLong.format(0.0159), "0.016"); +assert.sameValue(nfLong.format(0.00159), "0.0016"); +assert.sameValue(nfLong.format(-Infinity), "-∞"); +assert.sameValue(nfLong.format(Infinity), "∞"); +assert.sameValue(nfLong.format(NaN), "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ja-JP.js new file mode 100644 index 0000000000..24e6dbfd4f --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ja-JP.js @@ -0,0 +1,47 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + +const nfShort = new Intl.NumberFormat("ja-JP", { + notation: "compact", + compactDisplay: "short", +}); +assert.sameValue(nfShort.format(987654321), "9.9億"); +assert.sameValue(nfShort.format(98765432), "9877万"); +assert.sameValue(nfShort.format(98765), "9.9万"); +assert.sameValue(nfShort.format(9876), "9876"); +assert.sameValue(nfShort.format(159), "159"); +assert.sameValue(nfShort.format(15.9), "16"); +assert.sameValue(nfShort.format(1.59), "1.6"); +assert.sameValue(nfShort.format(0.159), "0.16"); +assert.sameValue(nfShort.format(0.0159), "0.016"); +assert.sameValue(nfShort.format(0.00159), "0.0016"); +assert.sameValue(nfShort.format(-Infinity), "-∞"); +assert.sameValue(nfShort.format(Infinity), "∞"); +assert.sameValue(nfShort.format(NaN), "NaN"); + +const nfLong = new Intl.NumberFormat("ja-JP", { + notation: "compact", + compactDisplay: "long", +}); +assert.sameValue(nfLong.format(987654321), "9.9億"); +assert.sameValue(nfLong.format(98765432), "9877万"); +assert.sameValue(nfLong.format(98765), "9.9万"); +assert.sameValue(nfLong.format(9876), "9876"); +assert.sameValue(nfLong.format(159), "159"); +assert.sameValue(nfLong.format(15.9), "16"); +assert.sameValue(nfLong.format(1.59), "1.6"); +assert.sameValue(nfLong.format(0.159), "0.16"); +assert.sameValue(nfLong.format(0.0159), "0.016"); +assert.sameValue(nfLong.format(0.00159), "0.0016"); +assert.sameValue(nfLong.format(-Infinity), "-∞"); +assert.sameValue(nfLong.format(Infinity), "∞"); +assert.sameValue(nfLong.format(NaN), "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ko-KR.js new file mode 100644 index 0000000000..d24f3a6e20 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-ko-KR.js @@ -0,0 +1,47 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + +const nfShort = new Intl.NumberFormat("ko-KR", { + notation: "compact", + compactDisplay: "short", +}); +assert.sameValue(nfShort.format(987654321), "9.9억"); +assert.sameValue(nfShort.format(98765432), "9877만"); +assert.sameValue(nfShort.format(98765), "9.9만"); +assert.sameValue(nfShort.format(9876), "9.9천"); +assert.sameValue(nfShort.format(159), "159"); +assert.sameValue(nfShort.format(15.9), "16"); +assert.sameValue(nfShort.format(1.59), "1.6"); +assert.sameValue(nfShort.format(0.159), "0.16"); +assert.sameValue(nfShort.format(0.0159), "0.016"); +assert.sameValue(nfShort.format(0.00159), "0.0016"); +assert.sameValue(nfShort.format(-Infinity), "-∞"); +assert.sameValue(nfShort.format(Infinity), "∞"); +assert.sameValue(nfShort.format(NaN), "NaN"); + +const nfLong = new Intl.NumberFormat("ko-KR", { + notation: "compact", + compactDisplay: "long", +}); +assert.sameValue(nfLong.format(987654321), "9.9억"); +assert.sameValue(nfLong.format(98765432), "9877만"); +assert.sameValue(nfLong.format(98765), "9.9만"); +assert.sameValue(nfLong.format(9876), "9.9천"); +assert.sameValue(nfLong.format(159), "159"); +assert.sameValue(nfLong.format(15.9), "16"); +assert.sameValue(nfLong.format(1.59), "1.6"); +assert.sameValue(nfLong.format(0.159), "0.16"); +assert.sameValue(nfLong.format(0.0159), "0.016"); +assert.sameValue(nfLong.format(0.00159), "0.0016"); +assert.sameValue(nfLong.format(-Infinity), "-∞"); +assert.sameValue(nfLong.format(Infinity), "∞"); +assert.sameValue(nfLong.format(NaN), "NaN"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-zh-TW.js new file mode 100644 index 0000000000..92e33a7922 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/notation-compact-zh-TW.js @@ -0,0 +1,47 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + +const nfShort = new Intl.NumberFormat("zh-TW", { + notation: "compact", + compactDisplay: "short", +}); +assert.sameValue(nfShort.format(987654321), "9.9億"); +assert.sameValue(nfShort.format(98765432), "9877萬"); +assert.sameValue(nfShort.format(98765), "9.9萬"); +assert.sameValue(nfShort.format(9876), "9876"); +assert.sameValue(nfShort.format(159), "159"); +assert.sameValue(nfShort.format(15.9), "16"); +assert.sameValue(nfShort.format(1.59), "1.6"); +assert.sameValue(nfShort.format(0.159), "0.16"); +assert.sameValue(nfShort.format(0.0159), "0.016"); +assert.sameValue(nfShort.format(0.00159), "0.0016"); +assert.sameValue(nfShort.format(-Infinity), "-∞"); +assert.sameValue(nfShort.format(Infinity), "∞"); +assert.sameValue(nfShort.format(NaN), "非數值"); + +const nfLong = new Intl.NumberFormat("zh-TW", { + notation: "compact", + compactDisplay: "long", +}); +assert.sameValue(nfLong.format(987654321), "9.9億"); +assert.sameValue(nfLong.format(98765432), "9877萬"); +assert.sameValue(nfLong.format(98765), "9.9萬"); +assert.sameValue(nfLong.format(9876), "9876"); +assert.sameValue(nfLong.format(159), "159"); +assert.sameValue(nfLong.format(15.9), "16"); +assert.sameValue(nfLong.format(1.59), "1.6"); +assert.sameValue(nfLong.format(0.159), "0.16"); +assert.sameValue(nfLong.format(0.0159), "0.016"); +assert.sameValue(nfLong.format(0.00159), "0.0016"); +assert.sameValue(nfLong.format(-Infinity), "-∞"); +assert.sameValue(nfLong.format(Infinity), "∞"); +assert.sameValue(nfLong.format(NaN), "非數值"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js new file mode 100644 index 0000000000..84699dfa0e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/numbering-systems.js @@ -0,0 +1,101 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: table-numbering-system-digits +description: > + Tests that Intl.NumberFormat.prototype.format supports all + numbering systems with simple digit mappings. +author: Roozbeh Pournader +---*/ + +const numberingSystems = { + adlm: 0x1E950, + ahom: 0x11730, + arab: 0x0660, + arabext: 0x06F0, + bali: 0x1B50, + beng: 0x09E6, + bhks: 0x11C50, + brah: 0x11066, + cakm: 0x11136, + cham: 0xAA50, + deva: 0x0966, + diak: 0x11950, + fullwide: 0xFF10, + gong: 0x11DA0, + gonm: 0x11D50, + gujr: 0x0AE6, + guru: 0x0A66, + hanidec: [0x3007, 0x4E00, 0x4E8C, 0x4E09, 0x56DB, + 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D], + hmng: 0x16B50, + hmnp: 0x1E140, + java: 0xA9D0, + kali: 0xA900, + khmr: 0x17E0, + knda: 0x0CE6, + lana: 0x1A80, + lanatham: 0x1A90, + laoo: 0x0ED0, + latn: 0x0030, + lepc: 0x1C40, + limb: 0x1946, + mathbold: 0x1D7CE, + mathdbl: 0x1D7D8, + mathmono: 0x1D7F6, + mathsanb: 0x1D7EC, + mathsans: 0x1D7E2, + mlym: 0x0D66, + modi: 0x11650, + mong: 0x1810, + mroo: 0x16A60, + mtei: 0xABF0, + mymr: 0x1040, + mymrshan: 0x1090, + mymrtlng: 0xA9F0, + newa: 0x11450, + nkoo: 0x07C0, + olck: 0x1C50, + orya: 0x0B66, + osma: 0x104A0, + rohg: 0x10D30, + saur: 0xA8D0, + segment: 0x1FBF0, + shrd: 0x111D0, + sind: 0x112F0, + sinh: 0x0DE6, + sora: 0x110F0, + sund: 0x1BB0, + takr: 0x116C0, + talu: 0x19D0, + tamldec: 0x0BE6, + telu: 0x0C66, + thai: 0x0E50, + tibt: 0x0F20, + tirh: 0x114D0, + vaii: 0xA620, + wara: 0x118E0, + wcho: 0x1E2F0, +}; + +for (let [numberingSystem, digitList] of Object.entries(numberingSystems)) { + if (typeof digitList === 'number') { + let zeroCode = digitList; + digitList = []; + for (let i = 0; i <= 9; ++i) { + digitList[i] = zeroCode + i; + } + } + + assert.sameValue(digitList.length, 10); + + let nf = new Intl.NumberFormat(undefined, {numberingSystem}); + + for (let i = 0; i <= 9; ++i) { + assert.sameValue(nf.format(i), String.fromCodePoint(digitList[i]), + `numberingSystem: ${numberingSystem}, digit: ${i}`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/percent-formatter.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/percent-formatter.js new file mode 100644 index 0000000000..5dc7f70e9e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/percent-formatter.js @@ -0,0 +1,25 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_FN_3_b +description: > + Tests that Intl.NumberFormat.prototype.format formats percent + values properly. +author: Roozbeh Pournader +---*/ + +var numberFormatter = new Intl.NumberFormat(); +var percentFormatter = new Intl.NumberFormat(undefined, {style: 'percent'}); + +var formattedTwenty = numberFormatter.format(20); +var formattedTwentyPercent = percentFormatter.format(0.20); + +// FIXME: May not work for some theoretical locales where percents and +// normal numbers are formatted using different numbering systems. +assert.notSameValue(formattedTwentyPercent.indexOf(formattedTwenty), -1, "Intl.NumberFormat's formatting of 20% does not include a formatting of 20 as a substring."); + +// FIXME: Move this to somewhere appropriate +assert.notSameValue(percentFormatter.format(0.011), percentFormatter.format(0.02), 'Intl.NumberFormat is formatting 1.1% and 2% the same way.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/prop-desc.js new file mode 100644 index 0000000000..19b7a02fdd --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/prop-desc.js @@ -0,0 +1,37 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + "format" property of Intl.NumberFormat.prototype. +info: | + get Intl.NumberFormat.prototype.format + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + Every accessor property described in clauses 18 through 26 and in Annex B.2 has the + attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. + If only a get accessor function is described, the set accessor function is the default + value, undefined. If only a set accessor is described the get accessor is the default + value, undefined. + +includes: [propertyHelper.js] +---*/ + +var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format"); + +assert.sameValue(desc.set, undefined); +assert.sameValue(typeof desc.get, "function"); + +verifyNotEnumerable(Intl.NumberFormat.prototype, "format"); +verifyConfigurable(Intl.NumberFormat.prototype, "format"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js new file mode 100644 index 0000000000..d51d9bc7d3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-de-DE.js @@ -0,0 +1,62 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "-987,00 $", + "-0,00 $", + "-0,00 $", + "0,00 $", + "0,00 $", + "987,00 $", + ], + [ + "always", + "-987,00 $", + "-0,00 $", + "-0,00 $", + "+0,00 $", + "+0,00 $", + "+987,00 $", + ], + [ + "never", + "987,00 $", + "0,00 $", + "0,00 $", + "0,00 $", + "0,00 $", + "987,00 $", + ], + [ + "exceptZero", + "-987,00 $", + "0,00 $", + "0,00 $", + "0,00 $", + "0,00 $", + "+987,00 $", + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + assert.sameValue(nf.format(-987), negative); + assert.sameValue(nf.format(-0.0001), negativeNearZero); + assert.sameValue(nf.format(-0), negativeZero); + assert.sameValue(nf.format(0), zero); + assert.sameValue(nf.format(0.0001), positiveNearZero); + assert.sameValue(nf.format(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js new file mode 100644 index 0000000000..2508a1c960 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-en-US.js @@ -0,0 +1,62 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "($987.00)", + "($0.00)", + "($0.00)", + "$0.00", + "$0.00", + "$987.00", + ], + [ + "always", + "($987.00)", + "($0.00)", + "($0.00)", + "+$0.00", + "+$0.00", + "+$987.00", + ], + [ + "never", + "$987.00", + "$0.00", + "$0.00", + "$0.00", + "$0.00", + "$987.00", + ], + [ + "exceptZero", + "($987.00)", + "$0.00", + "$0.00", + "$0.00", + "$0.00", + "+$987.00", + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + assert.sameValue(nf.format(-987), negative); + assert.sameValue(nf.format(-0.0001), negativeNearZero); + assert.sameValue(nf.format(-0), negativeZero); + assert.sameValue(nf.format(0), zero); + assert.sameValue(nf.format(0.0001), positiveNearZero); + assert.sameValue(nf.format(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js new file mode 100644 index 0000000000..768ebbf61f --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ja-JP.js @@ -0,0 +1,62 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "($987.00)", + "($0.00)", + "($0.00)", + "$0.00", + "$0.00", + "$987.00", + ], + [ + "always", + "($987.00)", + "($0.00)", + "($0.00)", + "+$0.00", + "+$0.00", + "+$987.00", + ], + [ + "never", + "$987.00", + "$0.00", + "$0.00", + "$0.00", + "$0.00", + "$987.00", + ], + [ + "exceptZero", + "($987.00)", + "$0.00", + "$0.00", + "$0.00", + "$0.00", + "+$987.00", + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + assert.sameValue(nf.format(-987), negative); + assert.sameValue(nf.format(-0.0001), negativeNearZero); + assert.sameValue(nf.format(-0), negativeZero); + assert.sameValue(nf.format(0), zero); + assert.sameValue(nf.format(0.0001), positiveNearZero); + assert.sameValue(nf.format(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js new file mode 100644 index 0000000000..fdf626fd91 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-ko-KR.js @@ -0,0 +1,62 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "(US$987.00)", + "(US$0.00)", + "(US$0.00)", + "US$0.00", + "US$0.00", + "US$987.00", + ], + [ + "always", + "(US$987.00)", + "(US$0.00)", + "(US$0.00)", + "+US$0.00", + "+US$0.00", + "+US$987.00", + ], + [ + "never", + "US$987.00", + "US$0.00", + "US$0.00", + "US$0.00", + "US$0.00", + "US$987.00", + ], + [ + "exceptZero", + "(US$987.00)", + "US$0.00", + "US$0.00", + "US$0.00", + "US$0.00", + "+US$987.00", + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + assert.sameValue(nf.format(-987), negative); + assert.sameValue(nf.format(-0.0001), negativeNearZero); + assert.sameValue(nf.format(-0), negativeZero); + assert.sameValue(nf.format(0), zero); + assert.sameValue(nf.format(0.0001), positiveNearZero); + assert.sameValue(nf.format(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js new file mode 100644 index 0000000000..92c5c22f5e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-currency-zh-TW.js @@ -0,0 +1,62 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "(US$987.00)", + "(US$0.00)", + "(US$0.00)", + "US$0.00", + "US$0.00", + "US$987.00", + ], + [ + "always", + "(US$987.00)", + "(US$0.00)", + "(US$0.00)", + "+US$0.00", + "+US$0.00", + "+US$987.00", + ], + [ + "never", + "US$987.00", + "US$0.00", + "US$0.00", + "US$0.00", + "US$0.00", + "US$987.00", + ], + [ + "exceptZero", + "(US$987.00)", + "US$0.00", + "US$0.00", + "US$0.00", + "US$0.00", + "+US$987.00", + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + assert.sameValue(nf.format(-987), negative); + assert.sameValue(nf.format(-0.0001), negativeNearZero); + assert.sameValue(nf.format(-0), negativeZero); + assert.sameValue(nf.format(0), zero); + assert.sameValue(nf.format(0.0001), positiveNearZero); + assert.sameValue(nf.format(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js new file mode 100644 index 0000000000..8d7a04d7cd --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-de-DE.js @@ -0,0 +1,77 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "-∞", + "-987", + "-0", + "-0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "always", + "-∞", + "-987", + "-0", + "-0", + "+0", + "+0", + "+987", + "+∞", + "+NaN", + ], + [ + "never", + "∞", + "987", + "0", + "0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "exceptZero", + "-∞", + "-987", + "0", + "0", + "0", + "0", + "+987", + "+∞", + "NaN", + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("de-DE", {signDisplay}); + assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`); + assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`); + assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`); + assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`); + assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`); + assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`); + assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`); + assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-en-US.js new file mode 100644 index 0000000000..7b756562e6 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-en-US.js @@ -0,0 +1,77 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "-∞", + "-987", + "-0", + "-0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "always", + "-∞", + "-987", + "-0", + "-0", + "+0", + "+0", + "+987", + "+∞", + "+NaN", + ], + [ + "never", + "∞", + "987", + "0", + "0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "exceptZero", + "-∞", + "-987", + "0", + "0", + "0", + "0", + "+987", + "+∞", + "NaN", + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("en-US", {signDisplay}); + assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`); + assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`); + assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`); + assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`); + assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`); + assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`); + assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`); + assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ja-JP.js new file mode 100644 index 0000000000..8074c621bb --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ja-JP.js @@ -0,0 +1,77 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "-∞", + "-987", + "-0", + "-0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "always", + "-∞", + "-987", + "-0", + "-0", + "+0", + "+0", + "+987", + "+∞", + "+NaN", + ], + [ + "never", + "∞", + "987", + "0", + "0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "exceptZero", + "-∞", + "-987", + "0", + "0", + "0", + "0", + "+987", + "+∞", + "NaN", + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("ja-JP", {signDisplay}); + assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`); + assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`); + assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`); + assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`); + assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`); + assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`); + assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`); + assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js new file mode 100644 index 0000000000..45029e8f89 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-ko-KR.js @@ -0,0 +1,77 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "-∞", + "-987", + "-0", + "-0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "always", + "-∞", + "-987", + "-0", + "-0", + "+0", + "+0", + "+987", + "+∞", + "+NaN", + ], + [ + "never", + "∞", + "987", + "0", + "0", + "0", + "0", + "987", + "∞", + "NaN", + ], + [ + "exceptZero", + "-∞", + "-987", + "0", + "0", + "0", + "0", + "+987", + "+∞", + "NaN", + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("ko-KR", {signDisplay}); + assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`); + assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`); + assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`); + assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`); + assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`); + assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`); + assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`); + assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js new file mode 100644 index 0000000000..726231f81d --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-rounding.js @@ -0,0 +1,20 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + + +const fmt = new Intl.NumberFormat("en-US", { + maximumFractionDigits: 1, + signDisplay: "exceptZero" +}); + +assert.sameValue(fmt.format(0.01), "0"); +assert.sameValue(fmt.format(-0.01), "0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-zh-TW.js new file mode 100644 index 0000000000..c16fa79c86 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/signDisplay-zh-TW.js @@ -0,0 +1,77 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + "auto", + "-∞", + "-987", + "-0", + "-0", + "0", + "0", + "987", + "∞", + "非數值", + ], + [ + "always", + "-∞", + "-987", + "-0", + "-0", + "+0", + "+0", + "+987", + "+∞", + "+非數值", + ], + [ + "never", + "∞", + "987", + "0", + "0", + "0", + "0", + "987", + "∞", + "非數值", + ], + [ + "exceptZero", + "-∞", + "-987", + "0", + "0", + "0", + "0", + "+987", + "+∞", + "非數值", + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("zh-TW", {signDisplay}); + assert.sameValue(nf.format(-Infinity), expected[0], `-Infinity (${signDisplay})`); + assert.sameValue(nf.format(-987), expected[1], `-987 (${signDisplay})`); + assert.sameValue(nf.format(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + assert.sameValue(nf.format(-0), expected[3], `-0 (${signDisplay})`); + assert.sameValue(nf.format(0), expected[4], `0 (${signDisplay})`); + assert.sameValue(nf.format(0.0001), expected[5], `0.0001 (${signDisplay})`); + assert.sameValue(nf.format(987), expected[6], `987 (${signDisplay})`); + assert.sameValue(nf.format(Infinity), expected[7], `Infinity (${signDisplay})`); + assert.sameValue(nf.format(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/this-value-not-numberformat.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/this-value-not-numberformat.js new file mode 100644 index 0000000000..bb20845bc9 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/this-value-not-numberformat.js @@ -0,0 +1,23 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: > + Tests that Intl.NumberFormat.prototype.format throws a TypeError + if called on a non-object value or an object that hasn't been + initialized as a NumberFormat. +---*/ + +const invalidTargets = [undefined, null, true, 0, 'NumberFormat', [], {}, Symbol()]; +const fn = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, 'format').get; + +invalidTargets.forEach(target => { + assert.throws( + TypeError, + () => fn.call(target), + `Calling format getter on ${String(target)} should throw a TypeError.` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-de-DE.js new file mode 100644 index 0000000000..622496c60c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-de-DE.js @@ -0,0 +1,71 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the unit style. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + -987, + { + "short": "-987 km/h", + "narrow": "-987 km/h", + "long": "-987 Kilometer pro Stunde", + } + ], + [ + -0.001, + { + "short": "-0,001 km/h", + "narrow": "-0,001 km/h", + "long": "-0,001 Kilometer pro Stunde", + } + ], + [ + -0, + { + "short": "-0 km/h", + "narrow": "-0 km/h", + "long": "-0 Kilometer pro Stunde", + } + ], + [ + 0, + { + "short": "0 km/h", + "narrow": "0 km/h", + "long": "0 Kilometer pro Stunde", + } + ], + [ + 0.001, + { + "short": "0,001 km/h", + "narrow": "0,001 km/h", + "long": "0,001 Kilometer pro Stunde", + } + ], + [ + 987, + { + "short": "987 km/h", + "narrow": "987 km/h", + "long": "987 Kilometer pro Stunde", + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("de-DE", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + assert.sameValue(nf.format(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-en-US.js new file mode 100644 index 0000000000..a0d053da30 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-en-US.js @@ -0,0 +1,71 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the unit style. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + -987, + { + "short": "-987 km/h", + "narrow": "-987km/h", + "long": "-987 kilometers per hour", + } + ], + [ + -0.001, + { + "short": "-0.001 km/h", + "narrow": "-0.001km/h", + "long": "-0.001 kilometers per hour", + } + ], + [ + -0, + { + "short": "-0 km/h", + "narrow": "-0km/h", + "long": "-0 kilometers per hour", + } + ], + [ + 0, + { + "short": "0 km/h", + "narrow": "0km/h", + "long": "0 kilometers per hour", + } + ], + [ + 0.001, + { + "short": "0.001 km/h", + "narrow": "0.001km/h", + "long": "0.001 kilometers per hour", + } + ], + [ + 987, + { + "short": "987 km/h", + "narrow": "987km/h", + "long": "987 kilometers per hour", + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("en-US", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + assert.sameValue(nf.format(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ja-JP.js new file mode 100644 index 0000000000..2fc6c38a37 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ja-JP.js @@ -0,0 +1,71 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the unit style. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + -987, + { + "short": "-987 km/h", + "narrow": "-987km/h", + "long": "時速 -987 キロメートル", + } + ], + [ + -0.001, + { + "short": "-0.001 km/h", + "narrow": "-0.001km/h", + "long": "時速 -0.001 キロメートル", + } + ], + [ + -0, + { + "short": "-0 km/h", + "narrow": "-0km/h", + "long": "時速 -0 キロメートル", + } + ], + [ + 0, + { + "short": "0 km/h", + "narrow": "0km/h", + "long": "時速 0 キロメートル", + } + ], + [ + 0.001, + { + "short": "0.001 km/h", + "narrow": "0.001km/h", + "long": "時速 0.001 キロメートル", + } + ], + [ + 987, + { + "short": "987 km/h", + "narrow": "987km/h", + "long": "時速 987 キロメートル", + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("ja-JP", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + assert.sameValue(nf.format(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ko-KR.js new file mode 100644 index 0000000000..a7f8e7a908 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-ko-KR.js @@ -0,0 +1,71 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the unit style. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + -987, + { + "short": "-987km/h", + "narrow": "-987km/h", + "long": "시속 -987킬로미터", + } + ], + [ + -0.001, + { + "short": "-0.001km/h", + "narrow": "-0.001km/h", + "long": "시속 -0.001킬로미터", + } + ], + [ + -0, + { + "short": "-0km/h", + "narrow": "-0km/h", + "long": "시속 -0킬로미터", + } + ], + [ + 0, + { + "short": "0km/h", + "narrow": "0km/h", + "long": "시속 0킬로미터", + } + ], + [ + 0.001, + { + "short": "0.001km/h", + "narrow": "0.001km/h", + "long": "시속 0.001킬로미터", + } + ], + [ + 987, + { + "short": "987km/h", + "narrow": "987km/h", + "long": "시속 987킬로미터", + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("ko-KR", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + assert.sameValue(nf.format(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-zh-TW.js new file mode 100644 index 0000000000..e3c715a30e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/unit-zh-TW.js @@ -0,0 +1,71 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of the unit style. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + + +const tests = [ + [ + -987, + { + "short": "-987 公里/小時", + "narrow": "-987公里/小時", + "long": "每小時 -987 公里", + } + ], + [ + -0.001, + { + "short": "-0.001 公里/小時", + "narrow": "-0.001公里/小時", + "long": "每小時 -0.001 公里", + } + ], + [ + -0, + { + "short": "-0 公里/小時", + "narrow": "-0公里/小時", + "long": "每小時 -0 公里", + } + ], + [ + 0, + { + "short": "0 公里/小時", + "narrow": "0公里/小時", + "long": "每小時 0 公里", + } + ], + [ + 0.001, + { + "short": "0.001 公里/小時", + "narrow": "0.001公里/小時", + "long": "每小時 0.001 公里", + } + ], + [ + 987, + { + "short": "987 公里/小時", + "narrow": "987公里/小時", + "long": "每小時 987 公里", + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("zh-TW", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + assert.sameValue(nf.format(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/units-invalid.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units-invalid.js new file mode 100644 index 0000000000..024be58f94 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units-invalid.js @@ -0,0 +1,112 @@ +// Copyright 2019 Igalia, S.L., Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of units. +features: [Intl.NumberFormat-unified] +---*/ + +const units = [ + "acre-foot", + "ampere", + "arc-minute", + "arc-second", + "astronomical-unit", + "atmosphere", + "bushel", + "calorie", + "carat", + "centiliter", + "century", + "cubic-centimeter", + "cubic-foot", + "cubic-inch", + "cubic-kilometer", + "cubic-meter", + "cubic-mile", + "cubic-yard", + "cup-metric", + "cup", + "day-person", + "deciliter", + "decimeter", + "fathom", + "foodcalorie", + "furlong", + "g-force", + "gallon-imperial", + "generic", + "gigahertz", + "gigawatt", + "hectoliter", + "hectopascal", + "hertz", + "horsepower", + "inch-hg", + "joule", + "karat", + "kelvin", + "kilocalorie", + "kilohertz", + "kilojoule", + "kilowatt-hour", + "kilowatt", + "knot", + "light-year", + "lux", + "megahertz", + "megaliter", + "megawatt", + "metric-ton", + "microgram", + "micrometer", + "microsecond", + "milliampere", + "millibar", + "milligram", + "millimeter-of-mercury", + "milliwatt", + "month-person", + "nanometer", + "nanosecond", + "nautical-mile", + "ohm", + "ounce-troy", + "parsec", + "permille", + "picometer", + "pint-metric", + "pint", + "point", + "quart", + "radian", + "revolution", + "square-centimeter", + "square-foot", + "square-inch", + "square-kilometer", + "square-meter", + "square-mile", + "square-yard", + "tablespoon", + "teaspoon", + "ton", + "volt", + "watt", + "week-person", + "year-person", + "liter-per-100kilometers", + "meter-per-second-squared", + "mile-per-gallon-imperial", + "milligram-per-deciliter", + "millimole-per-liter", + "part-per-million", + "pound-per-square-inch", +]; + +for (const unit of units) { + assert.throws(RangeError, () => new Intl.NumberFormat(undefined, { style: "unit", unit }), `Throw for ${unit}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js new file mode 100644 index 0000000000..f939789ddd --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/units.js @@ -0,0 +1,70 @@ +// Copyright 2019 Igalia, S.L., Google, Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Checks handling of units. +features: [Intl.NumberFormat-unified] +---*/ + +function check(unit) { + const s1 = (123).toLocaleString(undefined, { style: "unit", unit: unit }); + const s2 = (123).toLocaleString(); + assert.notSameValue(s1, s2); +} + +const units = [ + "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", + "mile", + "mile-scandinavian", + "millimeter", + "milliliter", + "millisecond", + "minute", + "month", + "ounce", + "percent", + "petabyte", + "pound", + "second", + "stone", + "terabit", + "terabyte", + "week", + "yard", + "year", +]; + +for (const simpleUnit of units) { + check(simpleUnit); + for (const simpleUnit2 of units) { + check(simpleUnit + "-per-" + simpleUnit2); + check(simpleUnit2 + "-per-" + simpleUnit); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-arg-coerced-to-number.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-arg-coerced-to-number.js new file mode 100644 index 0000000000..da25c9c5f0 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-arg-coerced-to-number.js @@ -0,0 +1,26 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.3.2_1_a_ii +description: > + Tests that Intl.NumberFormat.prototype.format converts other + types to numbers. +author: Roozbeh Pournader +---*/ + +var formatter = new Intl.NumberFormat(); +var testData = [undefined, null, true, '0.6666666', {valueOf: function () { return '0.1234567';}}]; +var number; +var i, input, correctResult, result; + +for (i in testData) { + input = testData[i]; + number = +input; + correctResult = formatter.format(number); + + result = formatter.format(input); + assert.sameValue(result, correctResult, 'Intl.NumberFormat does not convert other types to numbers. Input: "' + input + '".'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js new file mode 100644 index 0000000000..8d05270da3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/format/value-tonumber.js @@ -0,0 +1,44 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-number-format-functions +description: > + Tests that Intl.NumberFormat.prototype.format converts its argument + (called value) to a number using ToNumber (7.1.3). +info: | + 11.1.4Number Format Functions + + 4. Let x be ? ToNumber(value). +features: [Symbol] +---*/ + +const toNumberResults = [ + [undefined, NaN], + [null, +0], + [true, 1], + [false, 0], + ['42', 42], + ['foo', NaN] +]; + +const nf = new Intl.NumberFormat(); + +toNumberResults.forEach(pair => { + const [value, result] = pair; + assert.sameValue(nf.format(value), nf.format(result)); +}); + +let count = 0; +const dummy = {}; +dummy[Symbol.toPrimitive] = hint => (hint === 'number' ? ++count : NaN); +assert.sameValue(nf.format(dummy), nf.format(count)); +assert.sameValue(count, 1); + +assert.throws( + TypeError, + () => nf.format(Symbol()), + "ToNumber(arg) throws a TypeError when arg is of type 'Symbol'" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/default-parameter.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/default-parameter.js new file mode 100644 index 0000000000..c2ec726586 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/default-parameter.js @@ -0,0 +1,44 @@ +// Copyright (C) 2017 Josh Wolfe. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Intl.NumberFormat.prototype.formatToParts called with no parameters +info: | + Intl.NumberFormat.prototype.formatToParts ([ value ]) + + 3. If value is not provided, let value be undefined. +---*/ + +var nf = new Intl.NumberFormat(); + +const implicit = nf.formatToParts(); +const explicit = nf.formatToParts(undefined); + +// In most locales this is string "NaN", but there are exceptions, cf. "ليس رقم" +// in Arabic, "epäluku" in Finnish, "не число" in Russian, "son emas" in Uzbek etc. +const resultNaN = nf.format(NaN); +const result = [{ type: 'nan', value: resultNaN }]; + +assert( + partsEquals(implicit, explicit), + 'formatToParts() should be equivalent to formatToParts(undefined)' +); + +assert( + partsEquals(implicit, result), + 'Both implicit and explicit calls should have the correct result' +); + +function partsEquals(parts1, parts2) { + if (parts1.length !== parts2.length) return false; + for (var i = 0; i < parts1.length; i++) { + var part1 = parts1[i]; + var part2 = parts2[i]; + if (part1.type !== part2.type) return false; + if (part1.value !== part2.value) return false; + } + return true; +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-de-DE.js new file mode 100644 index 0000000000..b325432203 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-de-DE.js @@ -0,0 +1,88 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the engineering and scientific notations. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + 0.000345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}], + ], + [ + 0.345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}], + ], + [ + 3.45, + [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + ], + [ + 34.5, + [{"type":"integer","value":"34"},{"type":"decimal","value":","},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":","},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}], + ], + [ + 543, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}], + ], + [ + 5430, + [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + ], + [ + 543000, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + 543211.1, + [{"type":"integer","value":"543"},{"type":"decimal","value":","},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":","},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("de-DE", { notation: "engineering" })); + verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`); + const nfScientific = (new Intl.NumberFormat("de-DE", { notation: "scientific" })); + verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-en-US.js new file mode 100644 index 0000000000..c05ad26852 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-en-US.js @@ -0,0 +1,88 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the engineering and scientific notations. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + 0.000345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}], + ], + [ + 0.345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}], + ], + [ + 3.45, + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + ], + [ + 34.5, + [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}], + ], + [ + 543, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}], + ], + [ + 5430, + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + ], + [ + 543000, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + 543211.1, + [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("en-US", { notation: "engineering" })); + verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`); + const nfScientific = (new Intl.NumberFormat("en-US", { notation: "scientific" })); + verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ja-JP.js new file mode 100644 index 0000000000..4bf8ecaea7 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ja-JP.js @@ -0,0 +1,88 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the engineering and scientific notations. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + 0.000345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}], + ], + [ + 0.345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}], + ], + [ + 3.45, + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + ], + [ + 34.5, + [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}], + ], + [ + 543, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}], + ], + [ + 5430, + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + ], + [ + 543000, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + 543211.1, + [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("ja-JP", { notation: "engineering" })); + verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`); + const nfScientific = (new Intl.NumberFormat("ja-JP", { notation: "scientific" })); + verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ko-KR.js new file mode 100644 index 0000000000..fa6cc8b5c9 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-ko-KR.js @@ -0,0 +1,88 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the engineering and scientific notations. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + 0.000345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}], + ], + [ + 0.345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}], + ], + [ + 3.45, + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + ], + [ + 34.5, + [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}], + ], + [ + 543, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}], + ], + [ + 5430, + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + ], + [ + 543000, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + 543211.1, + [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("ko-KR", { notation: "engineering" })); + verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`); + const nfScientific = (new Intl.NumberFormat("ko-KR", { notation: "scientific" })); + verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-zh-TW.js new file mode 100644 index 0000000000..86b59171cc --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/engineering-scientific-zh-TW.js @@ -0,0 +1,88 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the engineering and scientific notations. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + 0.000345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"6"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"4"}], + ], + [ + 0.345, + [{"type":"integer","value":"345"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentMinusSign","value":"-"},{"type":"exponentInteger","value":"1"}], + ], + [ + 3.45, + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + ], + [ + 34.5, + [{"type":"integer","value":"34"},{"type":"decimal","value":"."},{"type":"fraction","value":"5"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"3"},{"type":"decimal","value":"."},{"type":"fraction","value":"45"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"1"}], + ], + [ + 543, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"0"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"2"}], + ], + [ + 5430, + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + ], + [ + 543000, + [{"type":"integer","value":"543"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"43"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + 543211.1, + [{"type":"integer","value":"543"},{"type":"decimal","value":"."},{"type":"fraction","value":"211"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"3"}], + [{"type":"integer","value":"5"},{"type":"decimal","value":"."},{"type":"fraction","value":"432"},{"type":"exponentSeparator","value":"E"},{"type":"exponentInteger","value":"5"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"非數值"}], + [{"type":"nan","value":"非數值"}], + ], +]; + +for (const [number, engineering, scientific] of tests) { + const nfEngineering = (new Intl.NumberFormat("zh-TW", { notation: "engineering" })); + verifyFormatParts(nfEngineering.formatToParts(number), engineering, `${number} - engineering`); + const nfScientific = (new Intl.NumberFormat("zh-TW", { notation: "scientific" })); + verifyFormatParts(nfScientific.formatToParts(number), scientific, `${number} - scientific`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/length.js new file mode 100644 index 0000000000..d6dfcab716 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/length.js @@ -0,0 +1,15 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Intl.NumberFormat.prototype.formatToParts.length. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.NumberFormat.prototype.formatToParts.length, 1); + +verifyNotEnumerable(Intl.NumberFormat.prototype.formatToParts, "length"); +verifyNotWritable(Intl.NumberFormat.prototype.formatToParts, "length"); +verifyConfigurable(Intl.NumberFormat.prototype.formatToParts, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/main.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/main.js new file mode 100644 index 0000000000..d6ce6de200 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/main.js @@ -0,0 +1,67 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Tests for existance and behavior of Intl.NumberFormat.prototype.formatToParts +---*/ + +function reduce(parts) { + return parts.map(part => part.value).join(''); +} + +function compareFTPtoFormat(locales, options, value) { + const nf = new Intl.NumberFormat(locales, options); + assert.sameValue( + nf.format(value), + reduce(nf.formatToParts(value)), + `Expected the same value for value ${value}, + locales: ${locales} and options: ${options}` + ); +} + +const num1 = 123456.789; +const num2 = 0.123; + +compareFTPtoFormat(); +compareFTPtoFormat('pl'); +compareFTPtoFormat(['pl']); +compareFTPtoFormat([]); +compareFTPtoFormat(['de'], undefined, 0); +compareFTPtoFormat(['de'], undefined, -10); +compareFTPtoFormat(['de'], undefined, 25324234235); +compareFTPtoFormat(['de'], undefined, num1); +compareFTPtoFormat(['de'], { + style: 'percent' +}, num2); +compareFTPtoFormat(['de'], { + style: 'currency', + currency: 'EUR' +}, num1); +compareFTPtoFormat(['de'], { + style: 'currency', + currency: 'EUR', + currencyDisplay: 'code' +}, num1); +compareFTPtoFormat(['de'], { + useGrouping: true +}, num1); +compareFTPtoFormat(['de'], { + useGrouping: false +}, num1); +compareFTPtoFormat(['de'], { + minimumIntegerDigits: 2 +}, num2); +compareFTPtoFormat(['de'], { + minimumFractionDigits: 6 +}, num2); +compareFTPtoFormat(['de'], { + maximumFractionDigits: 1 +}, num2); +compareFTPtoFormat(['de'], { + maximumSignificantDigits: 3 +}, num1); +compareFTPtoFormat(['de'], { + maximumSignificantDigits: 5 +}, num1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/name.js new file mode 100644 index 0000000000..32f12380de --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/name.js @@ -0,0 +1,17 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +description: Intl.NumberFormat.prototype.formatToParts.name value and descriptor. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.NumberFormat.prototype.formatToParts.name, 'formatToParts', + 'The value of `Intl.NumberFormat.prototype.formatToParts.name` is `"formatToParts"`' +); + +verifyNotEnumerable(Intl.NumberFormat.prototype.formatToParts, 'name'); +verifyNotWritable(Intl.NumberFormat.prototype.formatToParts, 'name'); +verifyConfigurable(Intl.NumberFormat.prototype.formatToParts, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-de-DE.js new file mode 100644 index 0000000000..a5de211642 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-de-DE.js @@ -0,0 +1,94 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} +const tests = [ + [ + 987654321, + [{"type":"integer","value":"988"},{"type":"literal","value":"\u00a0"},{"type":"compact","value":"Mio."}], + [{"type":"integer","value":"988"},{"type":"literal","value":" "},{"type":"compact","value":"Millionen"}], + ], + [ + 98765432, + [{"type":"integer","value":"99"},{"type":"literal","value":"\u00a0"},{"type":"compact","value":"Mio."}], + [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"Millionen"}], + ], + [ + 98765, + [{"type":"integer","value":"98"},{"type":"group","value":"."},{"type":"integer","value":"765"}], + [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"Tausend"}], + ], + [ + 9876, + [{"type":"integer","value":"9876"}], + [{"type":"integer","value":"9"},{"type":"decimal","value":","},{"type":"fraction","value":"9"},{"type":"literal","value":" "},{"type":"compact","value":"Tausend"}], + ], + [ + 159, + [{"type":"integer","value":"159"}], + ], + [ + 15.9, + [{"type":"integer","value":"16"}], + ], + [ + 1.59, + [{"type":"integer","value":"1"},{"type":"decimal","value":","},{"type":"fraction","value":"6"}], + ], + [ + 0.159, + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"16"}], + ], + [ + 0.0159, + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"016"}], + ], + [ + 0.00159, + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"0016"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, short, long = short] of tests) { + const nfShort = new Intl.NumberFormat("de-DE", { + notation: "compact", + compactDisplay: "short", + }); + verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`); + + const nfLong = new Intl.NumberFormat("de-DE", { + notation: "compact", + compactDisplay: "long", + }); + verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-en-US.js new file mode 100644 index 0000000000..84ea596f29 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-en-US.js @@ -0,0 +1,94 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} +const tests = [ + [ + 987654321, + [{"type":"integer","value":"988"},{"type":"compact","value":"M"}], + [{"type":"integer","value":"988"},{"type":"literal","value":" "},{"type":"compact","value":"million"}], + ], + [ + 98765432, + [{"type":"integer","value":"99"},{"type":"compact","value":"M"}], + [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"million"}], + ], + [ + 98765, + [{"type":"integer","value":"99"},{"type":"compact","value":"K"}], + [{"type":"integer","value":"99"},{"type":"literal","value":" "},{"type":"compact","value":"thousand"}], + ], + [ + 9876, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"K"}], + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"literal","value":" "},{"type":"compact","value":"thousand"}], + ], + [ + 159, + [{"type":"integer","value":"159"}], + ], + [ + 15.9, + [{"type":"integer","value":"16"}], + ], + [ + 1.59, + [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}], + ], + [ + 0.159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}], + ], + [ + 0.0159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}], + ], + [ + 0.00159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, short, long = short] of tests) { + const nfShort = new Intl.NumberFormat("en-US", { + notation: "compact", + compactDisplay: "short", + }); + verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`); + + const nfLong = new Intl.NumberFormat("en-US", { + notation: "compact", + compactDisplay: "long", + }); + verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ja-JP.js new file mode 100644 index 0000000000..9299f9f7bc --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ja-JP.js @@ -0,0 +1,90 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} +const tests = [ + [ + 987654321, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"億"}], + ], + [ + 98765432, + [{"type":"integer","value":"9877"},{"type":"compact","value":"万"}], + ], + [ + 98765, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"万"}], + ], + [ + 9876, + [{"type":"integer","value":"9876"}], + ], + [ + 159, + [{"type":"integer","value":"159"}], + ], + [ + 15.9, + [{"type":"integer","value":"16"}], + ], + [ + 1.59, + [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}], + ], + [ + 0.159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}], + ], + [ + 0.0159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}], + ], + [ + 0.00159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, short, long = short] of tests) { + const nfShort = new Intl.NumberFormat("ja-JP", { + notation: "compact", + compactDisplay: "short", + }); + verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`); + + const nfLong = new Intl.NumberFormat("ja-JP", { + notation: "compact", + compactDisplay: "long", + }); + verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ko-KR.js new file mode 100644 index 0000000000..067c9a3b32 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-ko-KR.js @@ -0,0 +1,90 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} +const tests = [ + [ + 987654321, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"억"}], + ], + [ + 98765432, + [{"type":"integer","value":"9877"},{"type":"compact","value":"만"}], + ], + [ + 98765, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"만"}], + ], + [ + 9876, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"천"}], + ], + [ + 159, + [{"type":"integer","value":"159"}], + ], + [ + 15.9, + [{"type":"integer","value":"16"}], + ], + [ + 1.59, + [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}], + ], + [ + 0.159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}], + ], + [ + 0.0159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}], + ], + [ + 0.00159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [number, short, long = short] of tests) { + const nfShort = new Intl.NumberFormat("ko-KR", { + notation: "compact", + compactDisplay: "short", + }); + verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`); + + const nfLong = new Intl.NumberFormat("ko-KR", { + notation: "compact", + compactDisplay: "long", + }); + verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-zh-TW.js new file mode 100644 index 0000000000..0b0ab99b1a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/notation-compact-zh-TW.js @@ -0,0 +1,90 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} +const tests = [ + [ + 987654321, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"億"}], + ], + [ + 98765432, + [{"type":"integer","value":"9877"},{"type":"compact","value":"萬"}], + ], + [ + 98765, + [{"type":"integer","value":"9"},{"type":"decimal","value":"."},{"type":"fraction","value":"9"},{"type":"compact","value":"萬"}], + ], + [ + 9876, + [{"type":"integer","value":"9876"}], + ], + [ + 159, + [{"type":"integer","value":"159"}], + ], + [ + 15.9, + [{"type":"integer","value":"16"}], + ], + [ + 1.59, + [{"type":"integer","value":"1"},{"type":"decimal","value":"."},{"type":"fraction","value":"6"}], + ], + [ + 0.159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"16"}], + ], + [ + 0.0159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"016"}], + ], + [ + 0.00159, + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"0016"}], + ], + [ + -Infinity, + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + ], + [ + Infinity, + [{"type":"infinity","value":"∞"}], + ], + [ + NaN, + [{"type":"nan","value":"非數值"}], + ], +]; + +for (const [number, short, long = short] of tests) { + const nfShort = new Intl.NumberFormat("zh-TW", { + notation: "compact", + compactDisplay: "short", + }); + verifyFormatParts(nfShort.formatToParts(number), short, `Compact short: ${number}`); + + const nfLong = new Intl.NumberFormat("zh-TW", { + notation: "compact", + compactDisplay: "long", + }); + verifyFormatParts(nfLong.formatToParts(number), long, `Compact long: ${number}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js new file mode 100644 index 0000000000..02b1cb5c42 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js @@ -0,0 +1,38 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the percent style and unit. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const nfStyle = new Intl.NumberFormat("en-US", { style: "percent" }); +verifyFormatParts(nfStyle.formatToParts(-123), [ + {"type":"minusSign","value":"-"}, + {"type":"integer","value":"12"}, + {"type":"group","value":","}, + {"type":"integer","value":"300"}, + {"type":"percentSign","value":"%"}, +], "style"); + +const nfUnit = new Intl.NumberFormat("en-US", { style: "unit", unit: "percent" }); +verifyFormatParts(nfUnit.formatToParts(-123), [ + {"type":"minusSign","value":"-"}, + {"type":"integer","value":"123"}, + {"type":"unit","value":"%"}, +], "unit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/prop-desc.js new file mode 100644 index 0000000000..97503e3f9b --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/prop-desc.js @@ -0,0 +1,39 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: > + "formatToParts" property of Intl.NumberFormat.prototype. +info: | + 11.4.4 Intl.NumberFormat.prototype.formatToParts + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + Every accessor property described in clauses 18 through 26 and in Annex B.2 has the + attributes { [[Enumerable]]: false, [[Configurable]]: true } unless otherwise specified. + If only a get accessor function is described, the set accessor function is the default + value, undefined. If only a set accessor is described the get accessor is the default + value, undefined. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue( + typeof Intl.NumberFormat.prototype.formatToParts, + 'function', + '`typeof Intl.NumberFormat.prototype.formatToParts` is `function`' +); + +verifyNotEnumerable(Intl.NumberFormat.prototype, 'formatToParts'); +verifyWritable(Intl.NumberFormat.prototype, 'formatToParts'); +verifyConfigurable(Intl.NumberFormat.prototype, 'formatToParts'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/shell.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js new file mode 100644 index 0000000000..fc03d0b585 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-de-DE.js @@ -0,0 +1,72 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + ], + [ + "always", + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + ], + [ + "never", + [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + ], + [ + "exceptZero", + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"},{"type":"decimal","value":","},{"type":"fraction","value":"00"},{"type":"literal","value":" "},{"type":"currency","value":"$"}], + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("de-DE", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + verifyFormatParts(nf.formatToParts(-987), negative); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); + verifyFormatParts(nf.formatToParts(-0), negativeZero); + verifyFormatParts(nf.formatToParts(0), zero); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); + verifyFormatParts(nf.formatToParts(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js new file mode 100644 index 0000000000..a55af1a2d5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-en-US.js @@ -0,0 +1,72 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "always", + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "never", + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "exceptZero", + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + verifyFormatParts(nf.formatToParts(-987), negative); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); + verifyFormatParts(nf.formatToParts(-0), negativeZero); + verifyFormatParts(nf.formatToParts(0), zero); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); + verifyFormatParts(nf.formatToParts(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js new file mode 100644 index 0000000000..c7feda2b40 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ja-JP.js @@ -0,0 +1,72 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "always", + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "never", + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "exceptZero", + [{"type":"literal","value":"("},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + verifyFormatParts(nf.formatToParts(-987), negative); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); + verifyFormatParts(nf.formatToParts(-0), negativeZero); + verifyFormatParts(nf.formatToParts(0), zero); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); + verifyFormatParts(nf.formatToParts(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js new file mode 100644 index 0000000000..2188d98020 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-ko-KR.js @@ -0,0 +1,72 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "always", + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "never", + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "exceptZero", + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("ko-KR", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + verifyFormatParts(nf.formatToParts(-987), negative); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); + verifyFormatParts(nf.formatToParts(-0), negativeZero); + verifyFormatParts(nf.formatToParts(0), zero); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); + verifyFormatParts(nf.formatToParts(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js new file mode 100644 index 0000000000..89629468a2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-currency-zh-TW.js @@ -0,0 +1,72 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the compactDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "always", + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "never", + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], + [ + "exceptZero", + [{"type":"literal","value":"("},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"},{"type":"literal","value":")"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"currency","value":"US$"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + [{"type":"plusSign","value":"+"},{"type":"currency","value":"US$"},{"type":"integer","value":"987"},{"type":"decimal","value":"."},{"type":"fraction","value":"00"}], + ], +]; + +for (const [signDisplay, negative, negativeNearZero, negativeZero, zero, positiveNearZero, positive] of tests) { + const nf = new Intl.NumberFormat("zh-TW", { style: "currency", currency: "USD", currencySign: "accounting", signDisplay }); + verifyFormatParts(nf.formatToParts(-987), negative); + verifyFormatParts(nf.formatToParts(-0.0001), negativeNearZero); + verifyFormatParts(nf.formatToParts(-0), negativeZero); + verifyFormatParts(nf.formatToParts(0), zero); + verifyFormatParts(nf.formatToParts(0.0001), positiveNearZero); + verifyFormatParts(nf.formatToParts(987), positive); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-de-DE.js new file mode 100644 index 0000000000..f0e57379f6 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-de-DE.js @@ -0,0 +1,87 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "always", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}], + ], + [ + "never", + [{"type":"infinity","value":"∞"}], + [{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "exceptZero", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("de-DE", {signDisplay}); + verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-en-US.js new file mode 100644 index 0000000000..6fdf3bb5a1 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-en-US.js @@ -0,0 +1,87 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "always", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}], + ], + [ + "never", + [{"type":"infinity","value":"∞"}], + [{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "exceptZero", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("en-US", {signDisplay}); + verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ja-JP.js new file mode 100644 index 0000000000..41748c1dab --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ja-JP.js @@ -0,0 +1,87 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "always", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}], + ], + [ + "never", + [{"type":"infinity","value":"∞"}], + [{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "exceptZero", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("ja-JP", {signDisplay}); + verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR.js new file mode 100644 index 0000000000..6a751269f3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-ko-KR.js @@ -0,0 +1,87 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "always", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"plusSign","value":"+"},{"type":"nan","value":"NaN"}], + ], + [ + "never", + [{"type":"infinity","value":"∞"}], + [{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], + [ + "exceptZero", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"NaN"}], + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("ko-KR", {signDisplay}); + verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW.js new file mode 100644 index 0000000000..e3d2d30fa1 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/signDisplay-zh-TW.js @@ -0,0 +1,87 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the signDisplay option to the NumberFormat constructor. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + "auto", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"非數值"}], + ], + [ + "always", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"plusSign","value":"+"},{"type":"nan","value":"非數值"}], + ], + [ + "never", + [{"type":"infinity","value":"∞"}], + [{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"987"}], + [{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"非數值"}], + ], + [ + "exceptZero", + [{"type":"minusSign","value":"-"},{"type":"infinity","value":"∞"}], + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"integer","value":"0"}], + [{"type":"plusSign","value":"+"},{"type":"integer","value":"987"}], + [{"type":"plusSign","value":"+"},{"type":"infinity","value":"∞"}], + [{"type":"nan","value":"非數值"}], + ], +]; + +for (const [signDisplay, ...expected] of tests) { + const nf = new Intl.NumberFormat("zh-TW", {signDisplay}); + verifyFormatParts(nf.formatToParts(-Infinity), expected[0], `-Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-987), expected[1], `-987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0.0001), expected[2], `-0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(-0), expected[3], `-0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0), expected[4], `0 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(0.0001), expected[5], `0.0001 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(987), expected[6], `987 (${signDisplay})`); + verifyFormatParts(nf.formatToParts(Infinity), expected[7], `Infinity (${signDisplay})`); + verifyFormatParts(nf.formatToParts(NaN), expected[8], `NaN (${signDisplay})`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/this-value-not-numberformat.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/this-value-not-numberformat.js new file mode 100644 index 0000000000..e5beb30623 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/this-value-not-numberformat.js @@ -0,0 +1,23 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.formatToParts +description: > + Tests that Intl.NumberFormat.prototype.formatToParts throws a + TypeError if called on a non-object value or an object that hasn't + been initialized as a NumberFormat. +---*/ + +const invalidTargets = [undefined, null, true, 0, 'NumberFormat', [], {}, Symbol()]; +const fn = Intl.NumberFormat.prototype.formatToParts; + +invalidTargets.forEach(target => { + assert.throws( + TypeError, + () => fn.call(target), + `Calling formatToParts on ${String(target)} should throw a TypeError.` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-de-DE.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-de-DE.js new file mode 100644 index 0000000000..ce186e9ecf --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-de-DE.js @@ -0,0 +1,99 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the unit style. +locale: [de-DE] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + -987, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "long": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}], + } + ], + [ + -0.001, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "long": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}], + } + ], + [ + -0, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "long": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}], + } + ], + [ + 0, + { + "short": + [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "long": + [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}], + } + ], + [ + 0.001, + { + "short": + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "long": + [{"type":"integer","value":"0"},{"type":"decimal","value":","},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}], + } + ], + [ + 987, + { + "short": + [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "long": + [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"Kilometer pro Stunde"}], + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("de-DE", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + verifyFormatParts(nf.formatToParts(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-en-US.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-en-US.js new file mode 100644 index 0000000000..db2220de22 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-en-US.js @@ -0,0 +1,99 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the unit style. +locale: [en-US] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + -987, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}], + } + ], + [ + -0.001, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}], + } + ], + [ + -0, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}], + } + ], + [ + 0, + { + "short": + [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}], + } + ], + [ + 0.001, + { + "short": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}], + } + ], + [ + 987, + { + "short": + [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"kilometers per hour"}], + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("en-US", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + verifyFormatParts(nf.formatToParts(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ja-JP.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ja-JP.js new file mode 100644 index 0000000000..2296f529a8 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ja-JP.js @@ -0,0 +1,99 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the unit style. +locale: [ja-JP] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + -987, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}], + } + ], + [ + -0.001, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}], + } + ], + [ + -0, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}], + } + ], + [ + 0, + { + "short": + [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}], + } + ], + [ + 0.001, + { + "short": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}], + } + ], + [ + 987, + { + "short": + [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"時速"},{"type":"literal","value":" "},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"キロメートル"}], + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("ja-JP", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + verifyFormatParts(nf.formatToParts(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ko-KR.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ko-KR.js new file mode 100644 index 0000000000..74d938b513 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-ko-KR.js @@ -0,0 +1,99 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the unit style. +locale: [ko-KR] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + -987, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"킬로미터"}], + } + ], + [ + -0.001, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"킬로미터"}], + } + ], + [ + -0, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"킬로미터"}], + } + ], + [ + 0, + { + "short": + [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"unit","value":"킬로미터"}], + } + ], + [ + 0.001, + { + "short": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"킬로미터"}], + } + ], + [ + 987, + { + "short": + [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "narrow": + [{"type":"integer","value":"987"},{"type":"unit","value":"km/h"}], + "long": + [{"type":"unit","value":"시속"},{"type":"literal","value":" "},{"type":"integer","value":"987"},{"type":"unit","value":"킬로미터"}], + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("ko-KR", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + verifyFormatParts(nf.formatToParts(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-zh-TW.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-zh-TW.js new file mode 100644 index 0000000000..6399ff7023 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit-zh-TW.js @@ -0,0 +1,99 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the unit style. +locale: [zh-TW] +features: [Intl.NumberFormat-unified] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(Array.isArray(expected), true, `${message}: expected is Array`); + assert.sameValue(Array.isArray(actual), true, `${message}: actual is Array`); + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + } +} + +const tests = [ + [ + -987, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"unit","value":"公里/小時"}], + "long": + [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}], + } + ], + [ + -0.001, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"公里/小時"}], + "long": + [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}], + } + ], + [ + -0, + { + "short": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}], + "narrow": + [{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"unit","value":"公里/小時"}], + "long": + [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"minusSign","value":"-"},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}], + } + ], + [ + 0, + { + "short": + [{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"unit","value":"公里/小時"}], + "long": + [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}], + } + ], + [ + 0.001, + { + "short": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}], + "narrow": + [{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"unit","value":"公里/小時"}], + "long": + [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"integer","value":"0"},{"type":"decimal","value":"."},{"type":"fraction","value":"001"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}], + } + ], + [ + 987, + { + "short": + [{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里/小時"}], + "narrow": + [{"type":"integer","value":"987"},{"type":"unit","value":"公里/小時"}], + "long": + [{"type":"unit","value":"每小時"},{"type":"literal","value":" "},{"type":"integer","value":"987"},{"type":"literal","value":" "},{"type":"unit","value":"公里"}], + } + ], +]; + +for (const [number, expectedData] of tests) { + for (const [unitDisplay, expected] of Object.entries(expectedData)) { + const nf = new Intl.NumberFormat("zh-TW", { style: "unit", unit: "kilometer-per-hour", unitDisplay }); + verifyFormatParts(nf.formatToParts(number), expected); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit.js new file mode 100644 index 0000000000..54b165ed89 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/unit.js @@ -0,0 +1,27 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: Checks handling of the unit style. +features: [Intl.NumberFormat-unified] +---*/ + +const numbers = [-987, -0.001, -0, 0, 0.001, 987]; +const displays = [ + "short", + "narrow", + "long", +]; + +for (const unitDisplay of displays) { + const nf = new Intl.NumberFormat("en-US", { style: "unit", unit: "meter", unitDisplay }); + for (const number of numbers) { + const result = nf.formatToParts(number); + assert.sameValue(result.map(({ value }) => value).join(""), nf.format(number)); + assert.sameValue(result.some(({ type }) => type === "unit"), true); + } +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/value-tonumber.js b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/value-tonumber.js new file mode 100644 index 0000000000..c2601b026f --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/formatToParts/value-tonumber.js @@ -0,0 +1,52 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.formattoparts +description: > + Tests that Intl.NumberFormat.prototype.formatToParts converts + its argument (called value) to a number using ToNumber (7.1.3). +info: | + 11.1.4 Number Format Functions + + 4. Let x be ? ToNumber(value). +features: [Symbol] +---*/ + +const toNumberResults = [ + [undefined, NaN], + [null, +0], + [true, 1], + [false, +0], + ['42', 42], + ['foo', NaN] +]; + +const nf = new Intl.NumberFormat(); + +function assertSameParts(actual, expected) { + assert.sameValue(actual.length, expected.length); + for (let i = 0; i < expected.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type); + assert.sameValue(actual[i].value, expected[i].value); + } +} + +toNumberResults.forEach(pair => { + const [value, result] = pair; + assertSameParts(nf.formatToParts(value), nf.formatToParts(result)); +}); + +let count = 0; +const dummy = {}; +dummy[Symbol.toPrimitive] = hint => (hint === 'number' ? ++count : NaN); +assertSameParts(nf.formatToParts(dummy), nf.formatToParts(count)); +assert.sameValue(count, 1); + +assert.throws( + TypeError, + () => nf.formatToParts(Symbol()), + "ToNumber(arg) throws a TypeError when arg is of type 'Symbol'" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/prop-desc.js new file mode 100644 index 0000000000..24b65adc9a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/prop-desc.js @@ -0,0 +1,17 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.2.1 +description: Tests that Intl.NumberFormat.prototype has the required attributes. +author: Norbert Lindenberg +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.NumberFormat, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js new file mode 100644 index 0000000000..0fb1fb510d --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/basic.js @@ -0,0 +1,43 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.3.3 +description: > + Tests that the object returned by + Intl.NumberFormat.prototype.resolvedOptions has the right + properties. +author: Norbert Lindenberg +includes: [testIntl.js, propertyHelper.js] +---*/ + +var actual = new Intl.NumberFormat().resolvedOptions(); + +var actual2 = new Intl.NumberFormat().resolvedOptions(); +assert.notSameValue(actual2, actual, "resolvedOptions returned the same object twice."); + +// this assumes the default values where the specification provides them +assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale), + "Invalid locale: " + actual.locale); +assert(isValidNumberingSystem(actual.numberingSystem), + "Invalid numbering system: " + actual.numberingSystem); +assert.sameValue(actual.style, "decimal"); +assert.sameValue(actual.minimumIntegerDigits, 1); +assert.sameValue(actual.minimumFractionDigits, 0); +assert.sameValue(actual.maximumFractionDigits, 3); +assert.sameValue(actual.useGrouping, true); + +var dataPropertyDesc = { writable: true, enumerable: true, configurable: true }; +verifyProperty(actual, "locale", dataPropertyDesc); +verifyProperty(actual, "numberingSystem", dataPropertyDesc); +verifyProperty(actual, "style", dataPropertyDesc); +verifyProperty(actual, "currency", undefined); +verifyProperty(actual, "currencyDisplay", undefined); +verifyProperty(actual, "minimumIntegerDigits", dataPropertyDesc); +verifyProperty(actual, "minimumFractionDigits", dataPropertyDesc); +verifyProperty(actual, "maximumFractionDigits", dataPropertyDesc); +verifyProperty(actual, "minimumSignificantDigits", undefined); +verifyProperty(actual, "maximumSignificantDigits", undefined); +verifyProperty(actual, "useGrouping", dataPropertyDesc); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/builtin.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/builtin.js new file mode 100644 index 0000000000..c513cc7fa5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.3.3_L15 +description: > + Tests that Intl.NumberFormat.prototype.resolvedOptions meets the + requirements for built-in objects defined by the introduction of + chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.NumberFormat.prototype.resolvedOptions), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.NumberFormat.prototype.resolvedOptions), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat.prototype.resolvedOptions), Function.prototype); + +assert.sameValue(Intl.NumberFormat.prototype.resolvedOptions.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.NumberFormat.prototype.resolvedOptions), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/compactDisplay.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/compactDisplay.js new file mode 100644 index 0000000000..9d42cee786 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/compactDisplay.js @@ -0,0 +1,26 @@ +// Copyright 2019 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.resolvedoptions +description: Verifies the existence of the compactDisplay property for the object returned by resolvedOptions(). +features: [Intl.NumberFormat-unified] +---*/ + +for (const notation of [undefined, "standard", "scientific", "engineering"]) { + const options = new Intl.NumberFormat([], { + notation, + compactDisplay: "long", + }).resolvedOptions(); + assert.sameValue("compactDisplay" in options, false, `There should be no compactDisplay property with notation=${notation}`); + assert.sameValue(options.compactDisplay, undefined, `The compactDisplay property should be undefined with notation=${notation}`); +} + +const options = new Intl.NumberFormat([], { + notation: "compact", + compactDisplay: "long", +}).resolvedOptions(); +assert.sameValue("compactDisplay" in options, true, "There should be a compactDisplay property with notation=compact"); +assert.sameValue(options.compactDisplay, "long", "The compactDisplay property should be defined with notation=compact"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..34d1db76e2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.resolvedoptions +description: > + Intl.NumberFormat.prototype.resolvedOptions.length is 0. +info: | + Intl.NumberFormat.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.NumberFormat.prototype.resolvedOptions.length, 0); + +verifyNotEnumerable(Intl.NumberFormat.prototype.resolvedOptions, "length"); +verifyNotWritable(Intl.NumberFormat.prototype.resolvedOptions, "length"); +verifyConfigurable(Intl.NumberFormat.prototype.resolvedOptions, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..64e0dc22f3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.resolvedOptions +description: > + Intl.NumberFormat.prototype.resolvedOptions.name is "resolvedOptions". +info: | + 11.4.4 Intl.NumberFormat.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.NumberFormat.prototype.resolvedOptions.name, "resolvedOptions"); + +verifyNotEnumerable(Intl.NumberFormat.prototype.resolvedOptions, "name"); +verifyNotWritable(Intl.NumberFormat.prototype.resolvedOptions, "name"); +verifyConfigurable(Intl.NumberFormat.prototype.resolvedOptions, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js new file mode 100644 index 0000000000..81385e67c6 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/order.js @@ -0,0 +1,36 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [compareArray.js] +features: [Intl.NumberFormat-unified] +---*/ + +const options = new Intl.NumberFormat([], { + "style": "currency", + "currency": "EUR", + "currencyDisplay": "symbol", + "minimumSignificantDigits": 1, + "maximumSignificantDigits": 2, +}).resolvedOptions(); + +const expected = [ + "locale", + "numberingSystem", + "style", + "currency", + "currencyDisplay", + "currencySign", + "minimumIntegerDigits", + "minimumSignificantDigits", + "maximumSignificantDigits", + "useGrouping", + "notation", + "signDisplay", +]; + +assert.compareArray(Object.getOwnPropertyNames(options), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..93239d52c6 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.resolvedoptions +description: > + "resolvedOptions" property of Intl.NumberFormat.prototype. +info: | + Intl.NumberFormat.prototype.resolvedOptions () + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.NumberFormat.prototype, "resolvedOptions"); +verifyWritable(Intl.NumberFormat.prototype, "resolvedOptions"); +verifyConfigurable(Intl.NumberFormat.prototype, "resolvedOptions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/this-value-not-numberformat.js b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/this-value-not-numberformat.js new file mode 100644 index 0000000000..d9773f00a3 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/resolvedOptions/this-value-not-numberformat.js @@ -0,0 +1,23 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.prototype.resolvedOptions +description: > + Tests that Intl.NumberFormat.prototype.resolvedOptions throws a + TypeError if called on a non-object value or an object that hasn't + been initialized as a NumberFormat. +---*/ + +const invalidTargets = [undefined, null, true, 0, 'NumberFormat', [], {}, Symbol()]; +const fn = Intl.NumberFormat.prototype.resolvedOptions; + +invalidTargets.forEach(target => { + assert.throws( + TypeError, + () => fn.call(target), + `Calling resolvedOptions on ${String(target)} should throw a TypeError.` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/shell.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/this-value-numberformat-prototype.js b/js/src/tests/test262/intl402/NumberFormat/prototype/this-value-numberformat-prototype.js new file mode 100644 index 0000000000..8fed1e229a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/this-value-numberformat-prototype.js @@ -0,0 +1,17 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-properties-of-intl-numberformat-prototype-object +description: > + Tests that Intl.NumberFormat.prototype is not an object that has been + initialized as an Intl.NumberFormat. +author: Roozbeh Pournader +---*/ + +// test by calling a function that should fail as "this" is not an object +// initialized as an Intl.NumberFormat +assert.throws(TypeError, () => Intl.NumberFormat.prototype.format(0), + "Intl.NumberFormat's prototype is not an object that has been initialized as an Intl.NumberFormat"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/configurable.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/configurable.js new file mode 100644 index 0000000000..a6aa44d04a --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/configurable.js @@ -0,0 +1,35 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype-@@tostringtag +description: > + Check that the initial value of the property is "Intl.NumberFormat" and that any changes + made by reconfiguring are reflected. +---*/ + +assert.sameValue(Intl.NumberFormat.prototype[Symbol.toStringTag], 'Intl.NumberFormat'); +assert.sameValue( + Object.prototype.toString.call(new Intl.NumberFormat()), + '[object Intl.NumberFormat]' +); + +Object.defineProperty(Intl.NumberFormat.prototype, Symbol.toStringTag, { + value: 'Alpha' +}); + +assert.sameValue(Intl.NumberFormat.prototype[Symbol.toStringTag], 'Alpha'); +assert.sameValue( + Object.prototype.toString.call(new Intl.NumberFormat()), + '[object Alpha]' +); + +delete Intl.NumberFormat.prototype[Symbol.toStringTag]; + +assert.sameValue(Intl.NumberFormat.prototype[Symbol.toStringTag], undefined); +assert.sameValue( + Object.prototype.toString.call(new Intl.NumberFormat()), + '[object Object]' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/prop-desc.js new file mode 100644 index 0000000000..e5116e6dec --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/prop-desc.js @@ -0,0 +1,18 @@ +// Copyright (C) 2018 Ujjwal Sharma. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype-@@tostringtag +description: > + Tests that Intl.NumberFormat.prototype[@@toStringTag] has the required attributes. +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.NumberFormat.prototype, Symbol.toStringTag, { + value: 'Intl.NumberFormat', + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/NumberFormat/shell.js b/js/src/tests/test262/intl402/NumberFormat/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/shell.js diff --git a/js/src/tests/test262/intl402/NumberFormat/significant-digits-options-get-sequence.js b/js/src/tests/test262/intl402/NumberFormat/significant-digits-options-get-sequence.js new file mode 100644 index 0000000000..0602e55b9c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/significant-digits-options-get-sequence.js @@ -0,0 +1,42 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_32 +description: > + Tests that the options minimumSignificantDigits and + maximumSignificantDigits are read in the right sequence. +author: Norbert Lindenberg +---*/ + +var minimumSignificantDigitsRead = false; +var maximumSignificantDigitsRead = false; + +function readMinimumSignificantDigits() { + assert.sameValue(minimumSignificantDigitsRead, false, + "minimumSignificantDigits getter already called"); + assert.sameValue(maximumSignificantDigitsRead, false, + "maximumSignificantDigits getter called before minimumSignificantDigits"); + minimumSignificantDigitsRead = true; + return 1; +} + +function readMaximumSignificantDigits() { + assert.sameValue(maximumSignificantDigitsRead, false, + "maximumSignificantDigits getter already called"); + maximumSignificantDigitsRead = true; + return 1; +} + +var options = {}; +Object.defineProperty(options, "minimumSignificantDigits", + { get: readMinimumSignificantDigits }); +Object.defineProperty(options, "maximumSignificantDigits", + { get: readMaximumSignificantDigits }); + +new Intl.NumberFormat("de", options); + +assert(minimumSignificantDigitsRead, "minimumSignificantDigits getter was called once"); +assert(maximumSignificantDigitsRead, "maximumSignificantDigits getter was called once"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/style-unit.js b/js/src/tests/test262/intl402/NumberFormat/style-unit.js new file mode 100644 index 0000000000..f41406dcfe --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/style-unit.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-setnumberformatunitoptions +description: Checks handling of valid values for the numeric option to the RelativeTimeFormat constructor. +info: | + SetNumberFormatUnitOptions ( intlObj, options ) + + 3. Let style be ? GetOption(options, "style", "string", « "decimal", "percent", "currency", "unit" », "decimal"). + 4. Set intlObj.[[Style]] to style. + +features: [Intl.NumberFormat-unified] +---*/ + +const validOptions = [ + [undefined, "decimal"], + ["unit", "unit"], + [{ toString() { return "unit"; } }, "unit"], +]; + +for (const [validOption, expected] of validOptions) { + const nf = new Intl.NumberFormat([], {"style": validOption, "unit": "gigabit"}); + const resolvedOptions = nf.resolvedOptions(); + assert.sameValue(resolvedOptions.style, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/subclassing.js b/js/src/tests/test262/intl402/NumberFormat/subclassing.js new file mode 100644 index 0000000000..e143233d50 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/subclassing.js @@ -0,0 +1,30 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.2 +description: Tests that Intl.NumberFormat can be subclassed. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +// get a number format and have it format an array of numbers for comparison with the subclass +var locales = ["tlh", "id", "en"]; +var a = [0, 1, -1, -123456.789, -Infinity, NaN]; +var referenceNumberFormat = new Intl.NumberFormat(locales); +var referenceFormatted = a.map(referenceNumberFormat.format); + +class MyNumberFormat extends Intl.NumberFormat { + constructor(locales, options) { + super(locales, options); + // could initialize MyNumberFormat properties + } + // could add methods to MyNumberFormat.prototype +} + +var format = new MyNumberFormat(locales); +var actual = a.map(format.format); +assert.compareArray(actual, referenceFormatted); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/basic.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/basic.js new file mode 100644 index 0000000000..fbf53ad990 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/basic.js @@ -0,0 +1,25 @@ +// Copyright 2012 Google Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.2.2_a +description: > + Tests that Intl.NumberFormat has a supportedLocalesOf property, + and it works as planned. +author: Roozbeh Pournader +---*/ + +var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale; +var notSupported = 'zxx'; // "no linguistic content" +var requestedLocales = [defaultLocale, notSupported]; + +var supportedLocales; + +assert(Intl.NumberFormat.hasOwnProperty('supportedLocalesOf'), "Intl.NumberFormat doesn't have a supportedLocalesOf property."); + +supportedLocales = Intl.NumberFormat.supportedLocalesOf(requestedLocales); +assert.sameValue(supportedLocales.length, 1, 'The length of supported locales list is not 1.'); + +assert.sameValue(supportedLocales[0], defaultLocale, 'The default locale is not returned in the supported list.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/browser.js diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/builtin.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/builtin.js new file mode 100644 index 0000000000..0c5efac8c5 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.2.2_L15 +description: > + Tests that Intl.NumberFormat.supportedLocalesOf meets the + requirements for built-in objects defined by the introduction of + chapter 17 of the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.NumberFormat.supportedLocalesOf), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.NumberFormat.supportedLocalesOf), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.NumberFormat.supportedLocalesOf), Function.prototype); + +assert.sameValue(Intl.NumberFormat.supportedLocalesOf.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.NumberFormat.supportedLocalesOf), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/length.js new file mode 100644 index 0000000000..1e6e3ea9ad --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.supportedlocalesof +description: > + Intl.NumberFormat.supportedLocalesOf.length is 1. +info: | + Intl.NumberFormat.supportedLocalesOf ( locales [ , options ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.NumberFormat.supportedLocalesOf.length, 1); + +verifyNotEnumerable(Intl.NumberFormat.supportedLocalesOf, "length"); +verifyNotWritable(Intl.NumberFormat.supportedLocalesOf, "length"); +verifyConfigurable(Intl.NumberFormat.supportedLocalesOf, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/name.js new file mode 100644 index 0000000000..c84103775e --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.NumberFormat.supportedLocalesOf +description: > + Intl.NumberFormat.supportedLocalesOf.name is "supportedLocalesOf". +info: | + 11.3.2 Intl.NumberFormat.supportedLocalesOf (locales [ , options ]) + + 17 ECMAScript Standard Built-in Objects: + 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, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.NumberFormat.supportedLocalesOf.name, "supportedLocalesOf"); + +verifyNotEnumerable(Intl.NumberFormat.supportedLocalesOf, "name"); +verifyNotWritable(Intl.NumberFormat.supportedLocalesOf, "name"); +verifyConfigurable(Intl.NumberFormat.supportedLocalesOf, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/prop-desc.js new file mode 100644 index 0000000000..e54c14fc12 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.supportedlocalesof +description: > + "supportedLocalesOf" property of Intl.NumberFormat. +info: | + Intl.NumberFormat.supportedLocalesOf ( locales [ , options ] ) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.NumberFormat, "supportedLocalesOf"); +verifyWritable(Intl.NumberFormat, "supportedLocalesOf"); +verifyConfigurable(Intl.NumberFormat, "supportedLocalesOf"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/taint-Object-prototype.js b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/taint-Object-prototype.js new file mode 100644 index 0000000000..d8644585e4 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/supportedLocalesOf/taint-Object-prototype.js @@ -0,0 +1,16 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 11.2.2_b +description: > + Tests that Intl.NumberFormat.supportedLocalesOf doesn't access + arguments that it's not given. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintDataProperty(Object.prototype, "1"); +new Intl.NumberFormat("und"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/taint-Object-prototype.js b/js/src/tests/test262/intl402/NumberFormat/taint-Object-prototype.js new file mode 100644 index 0000000000..19a41731d8 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/taint-Object-prototype.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_6 +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintProperties(["localeMatcher"]); + +var locale = new Intl.NumberFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; +assert(isCanonicalizedStructurallyValidLanguageTag(locale), "NumberFormat returns invalid locale " + locale + "."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-currency.js b/js/src/tests/test262/intl402/NumberFormat/test-option-currency.js new file mode 100644 index 0000000000..d1d786fab1 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-currency.js @@ -0,0 +1,57 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_17 +description: Tests that the option currency is processed correctly. +author: Norbert Lindenberg +---*/ + +var validValues = ["CNY", "USD", "EUR", "IDR", "jpy", {toString: function () {return "INR";}}]; +var invalidValues = ["$", "SFr.", "US$", "ßP", {toString: function () {return;}}]; + +var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale; + +validValues.forEach(function (value) { + var format, actual, expected; + + // with currency style, we should get the upper case form back + format = new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value}); + actual = format.resolvedOptions().currency; + expected = value.toString().toUpperCase(); + assert.sameValue(actual, expected, "Incorrect resolved currency with currency style."); + + // without currency style, we shouldn't get any currency back + format = new Intl.NumberFormat([defaultLocale], {currency: value}); + actual = format.resolvedOptions().currency; + expected = undefined; + assert.sameValue(actual, expected, "Incorrect resolved currency with non-currency style."); + + // currencies specified through the locale must be ignored + format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value}); + actual = format.resolvedOptions().currency; + expected = value.toString().toUpperCase(); + assert.sameValue(actual, expected, "Incorrect resolved currency with -u-cu- and currency style."); + + format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value}); + actual = format.resolvedOptions().currency; + expected = undefined; + assert.sameValue(actual, expected, "Incorrect resolved currency with -u-cu- and non-currency style."); +}); + +invalidValues.forEach(function (value) { + assert.throws(RangeError, function () { + return new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value}); + }, "Invalid currency value " + value + " was not rejected."); + assert.throws(RangeError, function () { + return new Intl.NumberFormat([defaultLocale], {currency: value}); + }, "Invalid currency value " + value + " was not rejected."); + assert.throws(RangeError, function () { + return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value}); + }, "Invalid currency value " + value + " was not rejected."); + assert.throws(RangeError, function () { + return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value}); + }, "Invalid currency value " + value + " was not rejected."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-currencyDisplay.js b/js/src/tests/test262/intl402/NumberFormat/test-option-currencyDisplay.js new file mode 100644 index 0000000000..afc92c1151 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-currencyDisplay.js @@ -0,0 +1,16 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_21 +description: Tests that the option currencyDisplay is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"], + "symbol", {extra: {any: {style: "currency", currency: "XDR"}}}); +testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"], + undefined, {noReturn: true}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-localeMatcher.js b/js/src/tests/test262/intl402/NumberFormat/test-option-localeMatcher.js new file mode 100644 index 0000000000..b2525bc392 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-localeMatcher.js @@ -0,0 +1,13 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_7 +description: Tests that the option localeMatcher is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.NumberFormat, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-style.js b/js/src/tests/test262/intl402/NumberFormat/test-option-style.js new file mode 100644 index 0000000000..fd9063b490 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-style.js @@ -0,0 +1,14 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_15 +description: Tests that the option style is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.NumberFormat, "style", "string", ["decimal", "percent", "currency"], "decimal", + {extra: {"currency": {currency: "CNY"}}}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js new file mode 100644 index 0000000000..4e9317af31 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/test-option-useGrouping.js @@ -0,0 +1,13 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_34 +description: Tests that the option useGrouping is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testOption(Intl.NumberFormat, "useGrouping", "boolean", undefined, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/this-value-ignored.js b/js/src/tests/test262/intl402/NumberFormat/this-value-ignored.js new file mode 100644 index 0000000000..ac07b22269 --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/this-value-ignored.js @@ -0,0 +1,37 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl-numberformat-constructor +description: > + Tests that the this-value is ignored in NumberFormat, if the this-value + isn't a NumberFormat instance. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + if (Constructor === Intl.NumberFormat) + return; + + var obj, newObj; + + // variant 1: use constructor in a "new" expression + obj = new Constructor(); + newObj = Intl.NumberFormat.call(obj); + assert.notSameValue(obj, newObj, "NumberFormat object created with \"new\" was not ignored as this-value."); + + // variant 2: use constructor as a function + if (Constructor !== Intl.Collator && + Constructor !== Intl.NumberFormat && + Constructor !== Intl.DateTimeFormat) + { + // Newer Intl constructors are not callable as a function. + return; + } + obj = Constructor(); + newObj = Intl.NumberFormat.call(obj); + assert.notSameValue(obj, newObj, "NumberFormat object created with constructor as function was not ignored as this-value."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/NumberFormat/throws-for-currency-style-without-currency-option.js b/js/src/tests/test262/intl402/NumberFormat/throws-for-currency-style-without-currency-option.js new file mode 100644 index 0000000000..74d7d2934c --- /dev/null +++ b/js/src/tests/test262/intl402/NumberFormat/throws-for-currency-style-without-currency-option.js @@ -0,0 +1,22 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 11.1.1_19 +description: > + Tests that the currency style can not be used without a specified + currency. +author: Norbert Lindenberg +---*/ + +var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale; + +assert.throws(TypeError, function () { + return new Intl.NumberFormat([defaultLocale], {style: "currency"}); +}, "Throws TypeError when currency code is not specified."); + +assert.throws(TypeError, function () { + return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency"}); +}, "Throws TypeError when currency code is not specified; Currenty code from Unicode locale extension sequence is ignored."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/browser.js b/js/src/tests/test262/intl402/PluralRules/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/browser.js diff --git a/js/src/tests/test262/intl402/PluralRules/builtin.js b/js/src/tests/test262/intl402/PluralRules/builtin.js new file mode 100644 index 0000000000..7979c93243 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/builtin.js @@ -0,0 +1,21 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules +description: > + Tests that Intl.PluralRules meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Zibi Braniecki +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.PluralRules), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.PluralRules), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.PluralRules), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/can-be-subclassed.js b/js/src/tests/test262/intl402/PluralRules/can-be-subclassed.js new file mode 100644 index 0000000000..e09c8b5f51 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/can-be-subclassed.js @@ -0,0 +1,30 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl-pluralrules-constructor +description: Tests that Intl.PluralRules can be subclassed. +author: Zibi Braniecki +includes: [compareArray.js] +---*/ + +// get a plural-rules and have it format an array of dates for comparison with the subclass +var locales = ["tlh", "id", "en"]; +var a = [1, 5, 12]; + +var referencePluralRules = new Intl.PluralRules(locales); +var referenceSelected = a.map(referencePluralRules.select.bind(referencePluralRules)); + +class MyPluralRules extends Intl.PluralRules { + constructor(locales, options) { + super(locales, options); + // could initialize MyPluralRules properties + } + // could add methods to MyPluralRules.prototype +} + +var pr = new MyPluralRules(locales); +var actual = a.map(pr.select.bind(pr)); +assert.compareArray(actual, referenceSelected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/constructor-options-throwing-getters.js b/js/src/tests/test262/intl402/PluralRules/constructor-options-throwing-getters.js new file mode 100644 index 0000000000..3099b1d1a2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/constructor-options-throwing-getters.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializepluralrules +description: Checks the propagation of exceptions from the options for the NumberFormat constructor. +---*/ + +function CustomError() {} + +const options = [ + "localeMatcher", + "type", + "minimumIntegerDigits", + "minimumFractionDigits", + "maximumFractionDigits", + "minimumSignificantDigits", + "maximumSignificantDigits", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.PluralRules("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/default-options-object-prototype.js b/js/src/tests/test262/intl402/PluralRules/default-options-object-prototype.js new file mode 100644 index 0000000000..fc837a2e2c --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/default-options-object-prototype.js @@ -0,0 +1,20 @@ +// Copyright (C) 2017 Igalia, S. L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializepluralrules +description: > + Monkey-patching Object.prototype does not change the default + options for PluralRules as a null prototype is used. +info: | + InitializePluralRules ( collator, locales, options ) + + 1. If _options_ is *undefined*, then + 1. Let _options_ be ObjectCreate(*null*). +---*/ + +Object.prototype.type = "ordinal"; +let pluralRules = new Intl.PluralRules("en"); +assert.sameValue(pluralRules.resolvedOptions().type, "cardinal"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/internals.js b/js/src/tests/test262/intl402/PluralRules/internals.js new file mode 100644 index 0000000000..db0b3a19b9 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/internals.js @@ -0,0 +1,19 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl-pluralrules-constructor +description: > + Tests that objects constructed by Intl.PluralRules have the specified + internal properties. +author: Zibi Braniecki +---*/ + +var obj = new Intl.PluralRules(); + +var actualPrototype = Object.getPrototypeOf(obj); +assert.sameValue(actualPrototype, Intl.PluralRules.prototype, "Prototype of object constructed by Intl.PluralRules isn't Intl.PluralRules.prototype; got " + actualPrototype); + +assert(Object.isExtensible(obj), "Object constructed by Intl.PluralRules must be extensible."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/length.js b/js/src/tests/test262/intl402/PluralRules/length.js new file mode 100644 index 0000000000..cc2ea11067 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/length.js @@ -0,0 +1,18 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules +description: Intl.PluralRules.length. +author: Zibi Braniecki +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.PluralRules, 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/name.js b/js/src/tests/test262/intl402/PluralRules/name.js new file mode 100644 index 0000000000..fdcfd0ae70 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/name.js @@ -0,0 +1,18 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules +description: Intl.PluralRules.name is "PluralRules" +author: Zibi Braniecki +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.PluralRules, 'name', { + value: 'PluralRules', + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prop-desc.js b/js/src/tests/test262/intl402/PluralRules/prop-desc.js new file mode 100644 index 0000000000..d21a3fec88 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prop-desc.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules +description: > + "PluralRules" property of Intl. +info: | + Intl.PluralRules (...) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl, 'PluralRules', { + writable: true, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/PluralRules/proto-from-ctor-realm.js new file mode 100644 index 0000000000..c5834ea464 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/proto-from-ctor-realm.js @@ -0,0 +1,59 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.PluralRules ( [ locales [ , options ] ] ) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let pluralRules be ? OrdinaryCreateFromConstructor(newTarget, "%PluralRulesPrototype%", « ... »). + 3. Return ? InitializePluralRules(pluralRules, locales, options). + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var pr; + +newTarget.prototype = undefined; +pr = Reflect.construct(Intl.PluralRules, [], newTarget); +assert.sameValue(Object.getPrototypeOf(pr), other.Intl.PluralRules.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +pr = Reflect.construct(Intl.PluralRules, [], newTarget); +assert.sameValue(Object.getPrototypeOf(pr), other.Intl.PluralRules.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = false; +pr = Reflect.construct(Intl.PluralRules, [], newTarget); +assert.sameValue(Object.getPrototypeOf(pr), other.Intl.PluralRules.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = ''; +pr = Reflect.construct(Intl.PluralRules, [], newTarget); +assert.sameValue(Object.getPrototypeOf(pr), other.Intl.PluralRules.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +pr = Reflect.construct(Intl.PluralRules, [], newTarget); +assert.sameValue(Object.getPrototypeOf(pr), other.Intl.PluralRules.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = 0; +pr = Reflect.construct(Intl.PluralRules, [], newTarget); +assert.sameValue(Object.getPrototypeOf(pr), other.Intl.PluralRules.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/bind.js b/js/src/tests/test262/intl402/PluralRules/prototype/bind.js new file mode 100644 index 0000000000..9b5142866c --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/bind.js @@ -0,0 +1,28 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-properties-of-intl-pluralrules-prototype-object +description: > + Tests that Intl.PluralRules.prototype functions throw a TypeError if + called on a non-object value or an object that hasn't been + initialized as a PluralRules. +author: Zibi Braniecki +---*/ + +var functions = { + select: Intl.PluralRules.prototype.select, + resolvedOptions: Intl.PluralRules.prototype.resolvedOptions +}; +var invalidTargets = [undefined, null, true, 0, "PluralRules", [], {}]; + +Object.getOwnPropertyNames(functions).forEach(function (functionName) { + var f = functions[functionName]; + invalidTargets.forEach(function (target) { + assert.throws(TypeError, function () { + f.call(target); + }, "Calling " + functionName + " on " + target + " was not rejected."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/browser.js b/js/src/tests/test262/intl402/PluralRules/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/browser.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/builtins.js b/js/src/tests/test262/intl402/PluralRules/prototype/builtins.js new file mode 100644 index 0000000000..22bc883a14 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/builtins.js @@ -0,0 +1,18 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-properties-of-intl-pluralrules-prototype-object +description: > + Tests that Intl.PluralRules.prototype meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Zibi Braniecki +---*/ + +assert(Object.isExtensible(Intl.PluralRules.prototype), "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.PluralRules.prototype), Object.prototype, + "Built-in prototype objects must have Object.prototype as their prototype."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/constructor/browser.js b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/constructor/main.js b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/main.js new file mode 100644 index 0000000000..8a3bb64e8c --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/main.js @@ -0,0 +1,14 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.constructor +description: > + Tests that Intl.PluralRules.prototype is an object that has been + initialized as an Intl.PluralRules. +author: Zibi Braniecki +---*/ + +assert.sameValue(Intl.PluralRules.prototype.constructor, Intl.PluralRules, "Intl.PluralRules.prototype.constructor is not the same as Intl.PluralRules"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..4e9757a6c2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype.constructor +description: > + "constructor" property of Intl.PluralRules.prototype. +info: | + Intl.PluralRules.prototype.constructor + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.PluralRules.prototype, "constructor"); +verifyWritable(Intl.PluralRules.prototype, "constructor"); +verifyConfigurable(Intl.PluralRules.prototype, "constructor"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/constructor/shell.js b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/properties.js b/js/src/tests/test262/intl402/PluralRules/prototype/properties.js new file mode 100644 index 0000000000..d30b187e6c --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/properties.js @@ -0,0 +1,17 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-properties-of-intl-pluralrules-prototype-object +description: Tests that Intl.PluralRules.prototype has the required attributes. +author: Zibi Braniecki +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.PluralRules, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/prototype.js b/js/src/tests/test262/intl402/PluralRules/prototype/prototype.js new file mode 100644 index 0000000000..6329c09f5f --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/prototype.js @@ -0,0 +1,18 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-properties-of-intl-pluralrules-prototype-object +description: > + Tests that Intl.PluralRules.prototype is not an object that has been + initialized as an Intl.PluralRules. +author: Zibi Braniecki +---*/ + +// test by calling a function that fails if "this" is not an object +// initialized as an Intl.PluralRules +assert.throws(TypeError, function() { + Intl.PluralRules.prototype.select(0); +}, "Intl.PluralRules.prototype is not an object that has been initialized as an Intl.PluralRules"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/builtins.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/builtins.js new file mode 100644 index 0000000000..72e8ef9d1f --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/builtins.js @@ -0,0 +1,30 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.resolvedOptions +description: > + Tests that Intl.PluralRules.prototype.resolvedOptions meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Zibi Braniecki +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.PluralRules.prototype.resolvedOptions), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.PluralRules.prototype.resolvedOptions), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.PluralRules.prototype.resolvedOptions), Function.prototype); + +assert.sameValue(Intl.PluralRules.prototype.resolvedOptions.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.PluralRules.prototype.resolvedOptions), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..6c40703981 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype.resolvedoptions +description: > + Intl.PluralRules.prototype.resolvedOptions.length is 0. +info: | + Intl.PluralRules.prototype.resolvedOptions () + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.PluralRules.prototype.resolvedOptions.length, 0); + +verifyNotEnumerable(Intl.PluralRules.prototype.resolvedOptions, "length"); +verifyNotWritable(Intl.PluralRules.prototype.resolvedOptions, "length"); +verifyConfigurable(Intl.PluralRules.prototype.resolvedOptions, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..92adab33f1 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/name.js @@ -0,0 +1,17 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.resolvedOptions.name +description: Intl.PluralRules.resolvedOptions.name is "resolvedOptions" +author: Zibi Braniecki +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.PluralRules.prototype.resolvedOptions.name, "resolvedOptions"); + +verifyNotEnumerable(Intl.PluralRules.prototype.resolvedOptions, "name"); +verifyNotWritable(Intl.PluralRules.prototype.resolvedOptions, "name"); +verifyConfigurable(Intl.PluralRules.prototype.resolvedOptions, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/order.js new file mode 100644 index 0000000000..b4a87c0259 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/order.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [compareArray.js] +features: [Intl.NumberFormat-unified] +---*/ + +const options = new Intl.PluralRules([], { + "minimumSignificantDigits": 1, + "maximumSignificantDigits": 2, +}).resolvedOptions(); + +const expected = [ + "locale", + "type", + "minimumIntegerDigits", + "minimumSignificantDigits", + "maximumSignificantDigits", + "pluralCategories", +]; + +assert.compareArray(Object.getOwnPropertyNames(options), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/pluralCategories.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/pluralCategories.js new file mode 100644 index 0000000000..fe4d6b5c1d --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/pluralCategories.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia S.L. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.resolvedOptions +description: > + Tests that Intl.PluralRules.prototype.resolvedOptions creates a new array + for the pluralCategories property on every call. +includes: [propertyHelper.js, compareArray.js] +---*/ + +const allowedValues = ["zero", "one", "two", "few", "many", "other"]; + +const pluralrules = new Intl.PluralRules(); +const options1 = pluralrules.resolvedOptions(); +const options2 = pluralrules.resolvedOptions(); + +assert.notSameValue(options1.pluralCategories, options2.pluralCategories, "Should have different arrays"); +assert.compareArray(options1.pluralCategories, options2.pluralCategories, "Arrays should have same values"); + +for (const category of options1.pluralCategories) { + assert(allowedValues.includes(category), `Found ${category}, expected one of ${allowedValues}`); +} + +verifyProperty(options1, "pluralCategories", { + writable: true, + enumerable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..c35d943143 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype.resolvedoptions +description: > + "resolvedOptions" property of Intl.PluralRules.prototype. +info: | + Intl.PluralRules.prototype.resolvedOptions () + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.PluralRules.prototype, "resolvedOptions"); +verifyWritable(Intl.PluralRules.prototype, "resolvedOptions"); +verifyConfigurable(Intl.PluralRules.prototype, "resolvedOptions"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/properties.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/properties.js new file mode 100644 index 0000000000..1db3cb1927 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/properties.js @@ -0,0 +1,38 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.resolvedOptions +description: > + Tests that the object returned by + Intl.PluralRules.prototype.resolvedOptions has the right + properties. +author: Zibi Braniecki +includes: [testIntl.js, propertyHelper.js] +---*/ + +var actual = new Intl.PluralRules().resolvedOptions(); + +var actual2 = new Intl.PluralRules().resolvedOptions(); +assert.notSameValue(actual2, actual, "resolvedOptions returned the same object twice."); + +// this assumes the default values where the specification provides them +assert(isCanonicalizedStructurallyValidLanguageTag(actual.locale), + "Invalid locale: " + actual.locale); +assert.sameValue(actual.type, "cardinal"); +assert.sameValue(actual.minimumIntegerDigits, 1); +assert.sameValue(actual.minimumFractionDigits, 0); +assert.sameValue(actual.maximumFractionDigits, 3); + +var dataPropertyDesc = { writable: true, enumerable: true, configurable: true }; +verifyProperty(actual, "locale", dataPropertyDesc); +verifyProperty(actual, "type", dataPropertyDesc); +verifyProperty(actual, "currency", undefined); +verifyProperty(actual, "currencyDisplay", undefined); +verifyProperty(actual, "minimumIntegerDigits", dataPropertyDesc); +verifyProperty(actual, "minimumFractionDigits", dataPropertyDesc); +verifyProperty(actual, "maximumFractionDigits", dataPropertyDesc); +verifyProperty(actual, "minimumSignificantDigits", undefined); +verifyProperty(actual, "maximumSignificantDigits", undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/resolvedOptions/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/select/browser.js b/js/src/tests/test262/intl402/PluralRules/prototype/select/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/select/browser.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/select/length.js b/js/src/tests/test262/intl402/PluralRules/prototype/select/length.js new file mode 100644 index 0000000000..baedab2dca --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/select/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype.select +description: > + Intl.PluralRules.prototype.select is 1. +info: | + Intl.PluralRules.prototype.select( value ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.PluralRules.prototype.select.length, 1); + +verifyNotEnumerable(Intl.PluralRules.prototype.select, "length"); +verifyNotWritable(Intl.PluralRules.prototype.select, "length"); +verifyConfigurable(Intl.PluralRules.prototype.select, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/select/name.js b/js/src/tests/test262/intl402/PluralRules/prototype/select/name.js new file mode 100644 index 0000000000..5c2b10ab5e --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/select/name.js @@ -0,0 +1,19 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.select +description: Intl.PluralRules.prototype.select.name is "select" +author: Zibi Braniecki +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.PluralRules.prototype.select.name, 'select', + 'The value of `Intl.PluralRules.prototype.select.name` is `"select"`' +); + +verifyNotEnumerable(Intl.PluralRules.prototype.select, 'name'); +verifyNotWritable(Intl.PluralRules.prototype.select, 'name'); +verifyConfigurable(Intl.PluralRules.prototype.select, 'name'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/select/non-finite.js b/js/src/tests/test262/intl402/PluralRules/prototype/select/non-finite.js new file mode 100644 index 0000000000..14166d66ec --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/select/non-finite.js @@ -0,0 +1,24 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.prototype.select +description: Tests that select function returns "other" for non finite values. +info: | + 1.1.4. ResolvePlural (pluralRules, n) + (...) + 1.1.4_3. If isFinite(n) is false, then + 1.1.4_3.a. Return "other". +author: Zibi Braniecki + +---*/ + +var invalidValues = [NaN, Infinity, -Infinity]; + +var pr = new Intl.PluralRules(); + +invalidValues.forEach(function (value) { + assert.sameValue(pr.select(value), "other"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/select/prop-desc.js b/js/src/tests/test262/intl402/PluralRules/prototype/select/prop-desc.js new file mode 100644 index 0000000000..13839624f1 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/select/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype.select +description: > + "select" property of Intl.PluralRules.prototype. +info: | + Intl.PluralRules.prototype.select( value ) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.PluralRules.prototype, "select"); +verifyWritable(Intl.PluralRules.prototype, "select"); +verifyConfigurable(Intl.PluralRules.prototype, "select"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/select/shell.js b/js/src/tests/test262/intl402/PluralRules/prototype/select/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/select/shell.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/select/tainting.js b/js/src/tests/test262/intl402/PluralRules/prototype/select/tainting.js new file mode 100644 index 0000000000..19dc9eddc5 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/select/tainting.js @@ -0,0 +1,22 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-intl-pluralrules-abstracts +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +info: | + 1.1.1. InitializePluralRules (pluralRules, locales, options) + (...) + 1.1.1_6. Let t be ? GetOption(options, "type", "string", « "cardinal", "ordinal" », "cardinal"). +author: Zibi Braniecki +includes: [testIntl.js] +---*/ + +taintProperties(["type"]); + +var pr = new Intl.PluralRules(); +var time = pr.select(9); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/shell.js b/js/src/tests/test262/intl402/PluralRules/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/shell.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString-changed-tag.js b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString-changed-tag.js new file mode 100644 index 0000000000..20b48fcc35 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString-changed-tag.js @@ -0,0 +1,30 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype-tostringtag +description: > + Object.prototype.toString utilizes Intl.PluralRules.prototype[@@toStringTag]. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". + + Intl.PluralRules.prototype [ @@toStringTag ] + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.toStringTag] +---*/ + +Object.defineProperty(Intl.PluralRules.prototype, Symbol.toStringTag, { + value: "test262", +}); + +assert.sameValue(Object.prototype.toString.call(Intl.PluralRules.prototype), "[object test262]"); +assert.sameValue(Object.prototype.toString.call(new Intl.PluralRules()), "[object test262]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString-removed-tag.js b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString-removed-tag.js new file mode 100644 index 0000000000..02f835ff2f --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString-removed-tag.js @@ -0,0 +1,24 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype-tostringtag +description: > + Object.prototype.toString doesn't special-case neither Intl.PluralRules instances nor its prototype. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". +features: [Symbol.toStringTag] +---*/ + +delete Intl.PluralRules.prototype[Symbol.toStringTag]; + +assert.sameValue(Object.prototype.toString.call(Intl.PluralRules.prototype), "[object Object]"); +assert.sameValue(Object.prototype.toString.call(new Intl.PluralRules()), "[object Object]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString.js new file mode 100644 index 0000000000..e5a30f15e4 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toString.js @@ -0,0 +1,26 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype-tostringtag +description: > + Object.prototype.toString utilizes Intl.PluralRules.prototype[@@toStringTag]. +info: | + Object.prototype.toString ( ) + + [...] + 14. Else, let builtinTag be "Object". + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". + + Intl.PluralRules.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl.PluralRules". +features: [Symbol.toStringTag] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.PluralRules.prototype), "[object Intl.PluralRules]"); +assert.sameValue(Object.prototype.toString.call(new Intl.PluralRules()), "[object Intl.PluralRules]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toStringTag.js new file mode 100644 index 0000000000..cdac2facc9 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/prototype/toStringTag/toStringTag.js @@ -0,0 +1,25 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.prototype-tostringtag +description: > + Property descriptor of Intl.PluralRules.prototype[@@toStringTag]. +info: | + Intl.PluralRules.prototype [ @@toStringTag ] + + The initial value of the @@toStringTag property is the String value "Intl.PluralRules". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.toStringTag] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Intl.PluralRules.prototype, Symbol.toStringTag, { + value: "Intl.PluralRules", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/shell.js b/js/src/tests/test262/intl402/PluralRules/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/shell.js diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/arguments.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/arguments.js new file mode 100644 index 0000000000..bf6e487d6e --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/arguments.js @@ -0,0 +1,16 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.supportedLocalesOf +description: > + Tests that Intl.PluralRules.supportedLocalesOf doesn't access + arguments that it's not given. +author: Zibi Braniecki +includes: [testIntl.js] +---*/ + +taintDataProperty(Object.prototype, "1"); +new Intl.PluralRules("und"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/browser.js diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/length.js new file mode 100644 index 0000000000..6192952f33 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.supportedlocalesof +description: > + Intl.PluralRules.supportedLocalesOf.length is 1. +info: | + Intl.PluralRules.supportedLocalesOf ( locales [ , options ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(Intl.PluralRules.supportedLocalesOf.length, 1); + +verifyNotEnumerable(Intl.PluralRules.supportedLocalesOf, "length"); +verifyNotWritable(Intl.PluralRules.supportedLocalesOf, "length"); +verifyConfigurable(Intl.PluralRules.supportedLocalesOf, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/main.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/main.js new file mode 100644 index 0000000000..23afcb1099 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/main.js @@ -0,0 +1,25 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.supportedLocalesOf +description: > + Tests that Intl.PluralRules has a supportedLocalesOf property, and + it works as planned. +author: Zibi Braniecki +---*/ + +var defaultLocale = new Intl.PluralRules().resolvedOptions().locale; +var notSupported = 'zxx'; // "no linguistic content" +var requestedLocales = [defaultLocale, notSupported]; + +var supportedLocales; + +assert(Intl.PluralRules.hasOwnProperty('supportedLocalesOf'), "Intl.PluralRules doesn't have a supportedLocalesOf property."); + +supportedLocales = Intl.PluralRules.supportedLocalesOf(requestedLocales); +assert.sameValue(supportedLocales.length, 1, 'The length of supported locales list is not 1.'); + +assert.sameValue(supportedLocales[0], defaultLocale, 'The default locale is not returned in the supported list.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/name.js new file mode 100644 index 0000000000..a79e9180be --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/name.js @@ -0,0 +1,16 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.supportedLocalesOf +description: Tests that Intl.PluralRules.supportedLocalesOf.name is "supportedLocalesOf" +author: Zibi Braniecki +includes: [propertyHelper.js] +---*/ +assert.sameValue(Intl.PluralRules.supportedLocalesOf.name, "supportedLocalesOf"); + +verifyNotEnumerable(Intl.PluralRules.supportedLocalesOf, "name"); +verifyNotWritable(Intl.PluralRules.supportedLocalesOf, "name"); +verifyConfigurable(Intl.PluralRules.supportedLocalesOf, "name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/prop-desc.js new file mode 100644 index 0000000000..ac8a8d5ba3 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.pluralrules.supportedlocalesof +description: > + "supportedLocalesOf" property of Intl.PluralRules. +info: | + Intl.PluralRules.supportedLocalesOf ( locales [ , options ] ) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +---*/ + +verifyNotEnumerable(Intl.PluralRules, "supportedLocalesOf"); +verifyWritable(Intl.PluralRules, "supportedLocalesOf"); +verifyConfigurable(Intl.PluralRules, "supportedLocalesOf"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/supportedLocalesOf.js b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/supportedLocalesOf.js new file mode 100644 index 0000000000..1bff8cdb1c --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/supportedLocalesOf/supportedLocalesOf.js @@ -0,0 +1,30 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules.supportedLocalesOf +description: > + Tests that Intl.PluralRules.supportedLocalesOf meets the requirements for + built-in objects defined by the introduction of chapter 17 of the + ECMAScript Language Specification. +author: Zibi Braniecki +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.PluralRules.supportedLocalesOf), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(Intl.PluralRules.supportedLocalesOf), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(Intl.PluralRules.supportedLocalesOf), Function.prototype); + +assert.sameValue(Intl.PluralRules.supportedLocalesOf.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(Intl.PluralRules.supportedLocalesOf), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/PluralRules/undefined-newtarget-throws.js b/js/src/tests/test262/intl402/PluralRules/undefined-newtarget-throws.js new file mode 100644 index 0000000000..77c82be1de --- /dev/null +++ b/js/src/tests/test262/intl402/PluralRules/undefined-newtarget-throws.js @@ -0,0 +1,27 @@ +// Copyright 2016 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-Intl.PluralRules +description: Tests that PluralRules throws when called as a function +author: Zibi Braniecki +includes: [testIntl.js] +---*/ + +assert.throws(TypeError, function() { + Intl.PluralRules(); +}, "Intl.PluralRules throws when called as a function"); + +assert.throws(TypeError, function() { + Intl.PluralRules.call(undefined); +}, "Intl.PluralRules throws when called as a function with |undefined| as this-value"); + +testWithIntlConstructors(function (Constructor) { + var obj = new Constructor(); + + assert.throws(TypeError, function() { + Intl.PluralRules.call(obj) + }, "Intl.PluralRules throws when called as a function with an Intl-object as this-value"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/locales-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/locales-invalid.js new file mode 100644 index 0000000000..dc5ea2b632 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/locales-invalid.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: sec-Intl.RelativeTimeFormat +description: Checks error cases for the locales argument to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 3. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). +includes: [testIntl.js] +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat, "function"); + +for (const [locales, expectedError] of getInvalidLocaleArguments()) { + assert.throws(expectedError, function() { new Intl.RelativeTimeFormat(locales) }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/locales-valid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/locales-valid.js new file mode 100644 index 0000000000..91a1721531 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/locales-valid.js @@ -0,0 +1,45 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks various cases for the locales argument to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 3. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). +features: [Intl.RelativeTimeFormat] +---*/ + +const defaultLocale = new Intl.RelativeTimeFormat().resolvedOptions().locale; + +const tests = [ + [undefined, defaultLocale, "undefined"], + ["EN", "en", "Single value"], + [[], defaultLocale, "Empty array"], + [["en", "EN"], "en", "Duplicate value (canonical first)"], + [["EN", "en"], "en", "Duplicate value (canonical last)"], + [{ 0: "DE", length: 0 }, defaultLocale, "Object with zero length"], + [{ 0: "DE", length: 1 }, "de", "Object with length"], +]; + +const errorTests = [ + [["en-GB-oed"], "Grandfathered"], + [["x-private"], "Private", ["lookup"]], +]; + +for (const [locales, expected, name, matchers = ["best fit", "lookup"]] of tests) { + for (const matcher of matchers) { + const rtf = new Intl.RelativeTimeFormat(locales, {localeMatcher: matcher}); + assert.sameValue(rtf.resolvedOptions().locale, expected, name); + } +} + +for (const [locales, name, matchers = ["best fit", "lookup"]] of errorTests) { + for (const matcher of matchers) { + assert.throws(RangeError, function() { + new Intl.RelativeTimeFormat(locales, {localeMatcher: matcher}); + }, name); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/newtarget-undefined.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/newtarget-undefined.js new file mode 100644 index 0000000000..34e34faaed --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/newtarget-undefined.js @@ -0,0 +1,29 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.RelativeTimeFormat +description: > + Verifies the NewTarget check for Intl.RelativeTimeFormat. +info: | + Intl.RelativeTimeFormat ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat, "function"); + +assert.throws(TypeError, function() { + Intl.RelativeTimeFormat(); +}); + +assert.throws(TypeError, function() { + Intl.RelativeTimeFormat("en"); +}); + +assert.throws(TypeError, function() { + Intl.RelativeTimeFormat("not-valid-tag"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-invalid.js new file mode 100644 index 0000000000..94db7ed97f --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-invalid.js @@ -0,0 +1,18 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of a null options argument to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 5. Else + a. Let options be ? ToObject(options). +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat, "function"); + +assert.throws(TypeError, function() { new Intl.RelativeTimeFormat([], null) }) + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-localeMatcher-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-localeMatcher-invalid.js new file mode 100644 index 0000000000..f567f29a04 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-localeMatcher-invalid.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of invalid value for the localeMatcher option to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 7. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.RelativeTimeFormat] +---*/ + +const invalidOptions = [ + null, + 1, + "", + "Lookup", + "LOOKUP", + "lookup\0", + "Best fit", + "BEST FIT", + "best\u00a0fit", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.RelativeTimeFormat([], {"localeMatcher": invalidOption}); + }, `${invalidOption} is an invalid localeMatcher option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-invalid.js new file mode 100644 index 0000000000..4451d7be14 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-invalid.js @@ -0,0 +1,46 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: > + Checks error cases for the options argument to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + + ... + 8. If numberingSystem is not undefined, then + a. If numberingSystem does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception. + +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat, "function"); + +/* + alphanum = (ALPHA / DIGIT) ; letters and numbers + numberingSystem = (3*8alphanum) *("-" (3*8alphanum)) +*/ +const invalidNumberingSystemOptions = [ + "", + "a", + "ab", + "abcdefghi", + "abc-abcdefghi", + "!invalid!", + "-latn-", + "latn-", + "latn--", + "latn-ca", + "latn-ca-", + "latn-ca-gregory", + "latné", + "latn编号", +]; +for (const numberingSystem of invalidNumberingSystemOptions) { + assert.throws(RangeError, function() { + new Intl.RelativeTimeFormat('en', {numberingSystem}); + }, `new Intl.RelativeTimeFormat("en", {numberingSystem: "${numberingSystem}"}) throws RangeError`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-valid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-valid.js new file mode 100644 index 0000000000..aa9d5038f1 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numberingSystem-valid.js @@ -0,0 +1,29 @@ +// Copyright 2018 André Bargull; Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks valid cases for the options argument to the RelativeTimeFormat constructor. +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat, "function"); + +const validNumberingSystemOptions = [ + "abc", + "abcd", + "abcde", + "abcdef", + "abcdefg", + "abcdefgh", + "12345678", + "1234abcd", + "1234abcd-abc123", +]; + +for (const numberingSystem of validNumberingSystemOptions) { + const rtf = new Intl.RelativeTimeFormat("en", {numberingSystem}); + assert.sameValue(rtf.resolvedOptions().numberingSystem, "latn"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numeric-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numeric-invalid.js new file mode 100644 index 0000000000..3b02910050 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numeric-invalid.js @@ -0,0 +1,33 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of invalid value for the numeric option to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 16. Let numeric be ? GetOption(options, "numeric", "string", «"always", "auto"», "always"). +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat, "function"); + +const invalidOptions = [ + null, + 1, + "", + "Always", + "ALWAYS", + "always\0", + "Auto", + "AUTO", + "auto\0", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.RelativeTimeFormat([], {"numeric": invalidOption}); + }, `${invalidOption} is an invalid numeric option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numeric-valid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numeric-valid.js new file mode 100644 index 0000000000..d831b94128 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-numeric-valid.js @@ -0,0 +1,27 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of valid values for the numeric option to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 16. Let numeric be ? GetOption(options, "numeric", "string", «"always", "auto"», "always"). + 17. Set relativeTimeFormat.[[Numeric]] to numeric. +features: [Intl.RelativeTimeFormat] +---*/ + +const validOptions = [ + [undefined, "always"], + ["always", "always"], + ["auto", "auto"], + [{ toString() { return "auto"; } }, "auto"], +]; + +for (const [validOption, expected] of validOptions) { + const tf = new Intl.RelativeTimeFormat([], {"numeric": validOption}); + const resolvedOptions = tf.resolvedOptions(); + assert.sameValue(resolvedOptions.numeric, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-order.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-order.js new file mode 100644 index 0000000000..e8684f2121 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-order.js @@ -0,0 +1,68 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks the order of operations on the options argument to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 7. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). + 14. Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long"). + 16. Let numeric be ? GetOption(options, "numeric", "string", «"always", "auto"», "always"). +includes: [compareArray.js] +features: [Intl.RelativeTimeFormat] +---*/ + +const callOrder = []; + +new Intl.RelativeTimeFormat([], { + get localeMatcher() { + callOrder.push("localeMatcher"); + return { + toString() { + callOrder.push("localeMatcher toString"); + return "best fit"; + } + }; + }, + get style() { + callOrder.push("style"); + return { + toString() { + callOrder.push("style toString"); + return "long"; + } + }; + }, + get numberingSystem() { + callOrder.push("numberingSystem"); + return { + toString() { + callOrder.push("numberingSystem toString"); + return "abc"; + } + }; + }, + get numeric() { + callOrder.push("numeric"); + return { + toString() { + callOrder.push("numeric toString"); + return "always"; + } + }; + }, +}); + +assert.compareArray(callOrder, [ + "localeMatcher", + "localeMatcher toString", + "numberingSystem", + "numberingSystem toString", + "style", + "style toString", + "numeric", + "numeric toString", +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-proto.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-proto.js new file mode 100644 index 0000000000..c47805f02b --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-proto.js @@ -0,0 +1,90 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: | + Checks that the RelativeTimeFormat constructor does not cause the + NumberFormat and PluralRules constructors to get properties off + Object.prototype through the options objects it creates. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 20. Let nfOptions be ObjectCreate(null). + 25. Let prOptions be ObjectCreate(null). +features: [Intl.RelativeTimeFormat] +---*/ + +Object.defineProperties(Object.prototype, { + // NumberFormat & PluralRules + "localeMatcher": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: localeMatcher"); + }, + }, + + "minimumIntegerDigits": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: minimumIntegerDigits"); + }, + }, + + "minimumFractionDigits": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: minimumFractionDigits"); + }, + }, + + "maximumFractionDigits": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: maximumFractionDigits"); + }, + }, + + "minimumSignificantDigits": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: minimumSignificantDigits"); + }, + }, + + "maximumSignificantDigits": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: maximumSignificantDigits"); + }, + }, + + // NumberFormat + "style": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: style"); + }, + }, + + "currency": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: currency"); + }, + }, + + "currencyDisplay": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: currencyDisplay"); + }, + }, + + "useGrouping": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: useGrouping"); + }, + }, + + // PluralRules + "type": { + "get": function() { + throw new Test262Error("Should not call getter on Object.prototype: type"); + }, + }, +}); + +new Intl.RelativeTimeFormat(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-style-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-style-invalid.js new file mode 100644 index 0000000000..7b397bed71 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-style-invalid.js @@ -0,0 +1,34 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of invalid value for the style option to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 14. Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long"). +features: [Intl.RelativeTimeFormat] +---*/ + +const invalidOptions = [ + null, + 1, + "", + "Long", + "LONG", + "long\0", + "Short", + "SHORT", + "short\0", + "Narrow", + "NARROW", + "narrow\0", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.RelativeTimeFormat([], {"style": invalidOption}); + }, `${invalidOption} is an invalid style option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-style-valid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-style-valid.js new file mode 100644 index 0000000000..1e53694ae7 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-style-valid.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of valid values for the style option to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) + 14. Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long"). + 15. Set relativeTimeFormat.[[Style]] to s. +features: [Intl.RelativeTimeFormat] +---*/ + +const validOptions = [ + [undefined, "long"], + ["long", "long"], + ["short", "short"], + ["narrow", "narrow"], + [{ toString() { return "narrow"; } }, "narrow"], +]; + +for (const [validOption, expected] of validOptions) { + const tf = new Intl.RelativeTimeFormat([], {"style": validOption}); + const resolvedOptions = tf.resolvedOptions(); + assert.sameValue(resolvedOptions.style, expected); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-throwing-getters.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-throwing-getters.js new file mode 100644 index 0000000000..f06e962f64 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-throwing-getters.js @@ -0,0 +1,119 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-InitializeRelativeTimeFormat +description: Checks the propagation of exceptions from the options for the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat + + 5. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). + ... + 7. Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined). + ... + 16. Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long"). + ... + 18. Let numeric be ? GetOption(options, "numeric", "string", «"always", "auto"», "always"). + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + 2. If value is not undefined, then + a. Assert: type is "boolean" or "string". + b. If type is "boolean", then + i. Let value be ToBoolean(value). + c. If type is "string", then + i. Let value be ? ToString(value). + d. If values is not undefined, then + i. If values does not contain an element equal to value, throw a RangeError exception. + e. Return value. + 3. Else, return fallback. +features: [Intl.RelativeTimeFormat] +includes: [compareArray.js] +---*/ + +function CustomError() {} + +const o1 = { + get localeMatcher() { + throw new CustomError(); + }, + get numberingSystem() { + throw "should not get the numberingSystem option before localeMatcher"; + }, + get style() { + throw "should not get the style option before localeMatcher"; + }, + get numeric() { + throw "should not get the numeric option before localeMatcher"; + } +}; + +const o2captures = []; +const o2 = { + get localeMatcher() { + o2captures.push('localeMatcher'); + }, + get numberingSystem() { + throw new CustomError(); + }, + get style() { + throw "should not get the style option before numberingSystem"; + }, + get numeric() { + throw "should not get the numeric option before numberingSystem"; + } +}; + +const o3captures = []; +const o3 = { + get localeMatcher() { + o3captures.push('localeMatcher'); + }, + get numberingSystem() { + o3captures.push('numberingSystem'); + }, + get style() { + throw new CustomError(); + }, + get numeric() { + throw "should not get the numeric option before style"; + } +}; + +const o4captures = []; +const o4 = { + get localeMatcher() { + o4captures.push('localeMatcher'); + }, + get numberingSystem() { + o4captures.push('numberingSystem'); + }, + get style() { + o4captures.push('style'); + }, + get numeric() { + throw new CustomError(); + } +}; + +assert.throws(CustomError, () => { + new Intl.RelativeTimeFormat("en", o1); +}, `Exception from localeMatcher getter should be propagated`); + +assert.throws(CustomError, () => { + new Intl.RelativeTimeFormat("en", o2); +}, `Exception from numberingSystem getter should be propagated`); +assert.compareArray(o2captures, ['localeMatcher']); + +assert.throws(CustomError, () => { + new Intl.RelativeTimeFormat("en", o3); +}, `Exception from style getter should be propagated`); +assert.compareArray(o3captures, ['localeMatcher', 'numberingSystem']); + +assert.throws(CustomError, () => { + new Intl.RelativeTimeFormat("en", o4); +}, `Exception from numeric getter should be propagated`); +assert.compareArray(o4captures, ['localeMatcher', 'numberingSystem', 'style']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-toobject-prototype.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-toobject-prototype.js new file mode 100644 index 0000000000..2c352b2dd0 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-toobject-prototype.js @@ -0,0 +1,37 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of non-object option arguments to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) +features: [Intl.RelativeTimeFormat] +---*/ + +Object.defineProperties(Object.prototype, { + "style": { + value: "short", + }, + "numeric": { + value: "auto", + }, +}) + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), +]; + +for (const options of optionsArguments) { + const rtf = new Intl.RelativeTimeFormat([], options); + const resolvedOptions = rtf.resolvedOptions(); + assert.sameValue(resolvedOptions.style, "short", + `options argument ${String(options)} should yield the correct value for "style"`); + assert.sameValue(resolvedOptions.numeric, "auto", + `options argument ${String(options)} should yield the correct value for "numeric"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-toobject.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-toobject.js new file mode 100644 index 0000000000..872308d078 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-toobject.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of non-object option arguments to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) +features: [Intl.RelativeTimeFormat] +---*/ + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), +]; + +for (const options of optionsArguments) { + const rtf = new Intl.RelativeTimeFormat([], options); + const resolvedOptions = rtf.resolvedOptions(); + assert.sameValue(resolvedOptions.style, "long", + `options argument ${String(options)} should yield the correct value for "style"`); + assert.sameValue(resolvedOptions.numeric, "always", + `options argument ${String(options)} should yield the correct value for "numeric"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-undefined.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-undefined.js new file mode 100644 index 0000000000..1953dd1cdc --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/options-undefined.js @@ -0,0 +1,40 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks handling of non-object option arguments to the RelativeTimeFormat constructor. +info: | + InitializeRelativeTimeFormat (relativeTimeFormat, locales, options) +features: [Intl.RelativeTimeFormat] +---*/ + +Object.defineProperties(Object.prototype, { + style: { + get() { + throw new Error("Should not call style getter"); + } + }, + numeric: { + get() { + throw new Error("Should not call numeric getter"); + } + }, +}) + +const optionsArguments = [ + [], + [[]], + [[], undefined], +]; + +for (const args of optionsArguments) { + const rtf = new Intl.RelativeTimeFormat(...args); + const resolvedOptions = rtf.resolvedOptions(); + assert.sameValue(resolvedOptions.style, "long", + `Calling with ${args.length} empty arguments should yield the fallback value for "style"`); + assert.sameValue(resolvedOptions.numeric, "always", + `Calling with ${args.length} empty arguments should yield the fallback value for "numeric"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/proto-from-ctor-realm.js new file mode 100644 index 0000000000..5f71812c17 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/proto-from-ctor-realm.js @@ -0,0 +1,59 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.RelativeTimeFormat ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let relativeTimeFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%RelativeTimeFormatPrototype%", « ... »). + 3. Return ? InitializeRelativeTimeFormat(relativeTimeFormat, locales, options). + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.RelativeTimeFormat, cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var rtf; + +newTarget.prototype = undefined; +rtf = Reflect.construct(Intl.RelativeTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(rtf), other.Intl.RelativeTimeFormat.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +rtf = Reflect.construct(Intl.RelativeTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(rtf), other.Intl.RelativeTimeFormat.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = true; +rtf = Reflect.construct(Intl.RelativeTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(rtf), other.Intl.RelativeTimeFormat.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = ''; +rtf = Reflect.construct(Intl.RelativeTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(rtf), other.Intl.RelativeTimeFormat.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +rtf = Reflect.construct(Intl.RelativeTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(rtf), other.Intl.RelativeTimeFormat.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = -1; +rtf = Reflect.construct(Intl.RelativeTimeFormat, [], newTarget); +assert.sameValue(Object.getPrototypeOf(rtf), other.Intl.RelativeTimeFormat.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/subclassing.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/subclassing.js new file mode 100644 index 0000000000..02b7b9fd2a --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/constructor/subclassing.js @@ -0,0 +1,42 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: Checks that RelativeTimeFormat can be subclassed. +info: | + Intl.RelativeTimeFormat ( [ locales [ , options ] ] ) + + 2. Let relativeTimeFormat be ! OrdinaryCreateFromConstructor(NewTarget, "%RelativeTimeFormatPrototype%", « [[InitializedRelativeTimeFormat]] »). + +features: [Intl.RelativeTimeFormat] +---*/ + +class CustomRelativeTimeFormat extends Intl.RelativeTimeFormat { + constructor(locales, options) { + super(locales, options); + this.isCustom = true; + } +} + +const locale = "de"; +const value = 7; +const unit = "day"; + +const real_rtf = new Intl.RelativeTimeFormat(locale); +assert.sameValue(real_rtf.isCustom, undefined, "Custom property"); + +const custom_rtf = new CustomRelativeTimeFormat(locale); +assert.sameValue(custom_rtf.isCustom, true, "Custom property"); + +assert.sameValue(custom_rtf.format(value, unit), + real_rtf.format(value, unit), + "Direct call"); + +assert.sameValue(Intl.RelativeTimeFormat.prototype.format.call(custom_rtf, value, unit), + Intl.RelativeTimeFormat.prototype.format.call(real_rtf, value, unit), + "Indirect call"); + +assert.sameValue(Object.getPrototypeOf(custom_rtf), CustomRelativeTimeFormat.prototype, "Prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/length.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/length.js new file mode 100644 index 0000000000..752e277bc5 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: > + Checks the "length" property of the RelativeTimeFormat 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 RelativeTimeFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/name.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/name.js new file mode 100644 index 0000000000..4dc57bf36f --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/name.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: sec-Intl.RelativeTimeFormat +description: > + Checks the "name" property of the RelativeTimeFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat, "name", { + value: "RelativeTimeFormat", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/prop-desc.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/prop-desc.js new file mode 100644 index 0000000000..af3bcf0aef --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/prop-desc.js @@ -0,0 +1,37 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat +description: > + "RelativeTimeFormat" property of Intl. +info: | + Intl.RelativeTimeFormat (...) + + 7 Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + 17 ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat, "function"); + +verifyProperty(Intl, "RelativeTimeFormat", { + value: Intl.RelativeTimeFormat, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/prototype.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/prototype.js new file mode 100644 index 0000000000..665269f330 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/prototype.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: sec-Intl.RelativeTimeFormat +description: The prototype of the Intl.RelativeTimeFormat constructor is %FunctionPrototype%. +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. + Unless otherwise specified every built-in function object has the %FunctionPrototype% object as the initial value of its [[Prototype]] internal slot. +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue( + Object.getPrototypeOf(Intl.RelativeTimeFormat), + Function.prototype, + "Object.getPrototypeOf(Intl.RelativeTimeFormat) equals the value of Function.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/basic.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/basic.js new file mode 100644 index 0000000000..7cd949a718 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/basic.js @@ -0,0 +1,23 @@ +// Copyright 2018 Google Inc., Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: > + Tests that Intl.RelativeTimeFormat has a supportedLocalesOf property, + and it works as planned. +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat.supportedLocalesOf, "function", + "supportedLocalesOf should be supported."); + +const defaultLocale = new Intl.RelativeTimeFormat().resolvedOptions().locale; +const notSupported = 'zxx'; // "no linguistic content" +const requestedLocales = [defaultLocale, notSupported]; + +const supportedLocales = Intl.RelativeTimeFormat.supportedLocalesOf(requestedLocales); +assert.sameValue(supportedLocales.length, 1, 'The length of supported locales list is not 1.'); +assert.sameValue(supportedLocales[0], defaultLocale, 'The default locale is not returned in the supported list.'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/branding.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/branding.js new file mode 100644 index 0000000000..fa89f86ba0 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/branding.js @@ -0,0 +1,34 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: > + Verifies there's no branding check for Intl.RelativeTimeFormat.supportedLocalesOf(). +info: | + Intl.RelativeTimeFormat.supportedLocalesOf ( locales [, options ]) +features: [Intl.RelativeTimeFormat] +---*/ + +const supportedLocalesOf = Intl.RelativeTimeFormat.supportedLocalesOf; + +assert.sameValue(typeof supportedLocalesOf, "function"); + +const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.RelativeTimeFormat, + Intl.RelativeTimeFormat.prototype, +]; + +for (const thisValue of thisValues) { + const result = supportedLocalesOf.call(thisValue); + assert.sameValue(Array.isArray(result), true); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/length.js new file mode 100644 index 0000000000..2775259dc6 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/length.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: > + Checks the "length" property of Intl.RelativeTimeFormat.supportedLocalesOf(). +info: | + The value of the length property of the supportedLocalesOf method is 1. + 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, has a length property whose value is an integer. + Unless otherwise specified, the length property of a built-in function object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.supportedLocalesOf, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/locales-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/locales-invalid.js new file mode 100644 index 0000000000..57cfa4a3ee --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/locales-invalid.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: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: Checks error cases for the locales argument to the supportedLocalesOf function. +info: | + Intl.RelativeTimeFormat.supportedLocalesOf ( locales [, options ]) + + 2. Let requestedLocales be CanonicalizeLocaleList(locales). +includes: [testIntl.js] +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat.supportedLocalesOf, "function", + "Should support Intl.RelativeTimeFormat.supportedLocalesOf."); + +for (const [locales, expectedError] of getInvalidLocaleArguments()) { + assert.throws(expectedError, () => Intl.RelativeTimeFormat.supportedLocalesOf(locales)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/name.js new file mode 100644 index 0000000000..34c59814fd --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/name.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: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: > + Checks the "name" property of Intl.RelativeTimeFormat.supportedLocalesOf(). +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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.supportedLocalesOf, "name", { + value: "supportedLocalesOf", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-localeMatcher-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-localeMatcher-invalid.js new file mode 100644 index 0000000000..854f9ca3d7 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-localeMatcher-invalid.js @@ -0,0 +1,36 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: Checks handling of invalid values for the localeMatcher option to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + b. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat.supportedLocalesOf, "function", + "Should support Intl.RelativeTimeFormat.supportedLocalesOf."); + +const invalidOptions = [ + null, + 1, + "", + "Lookup", + "LOOKUP", + "lookup\0", + "Best fit", + "BEST FIT", + "best\u00a0fit", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + Intl.RelativeTimeFormat.supportedLocalesOf([], {"localeMatcher": invalidOption}); + }, `${invalidOption} is an invalid localeMatcher option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-null.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-null.js new file mode 100644 index 0000000000..be15359c46 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-null.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: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: Checks handling of a null options argument to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + a. Let options be ? ToObject(options). +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat.supportedLocalesOf, "function", + "Should support Intl.RelativeTimeFormat.supportedLocalesOf."); + +assert.throws(TypeError, function() { + Intl.RelativeTimeFormat.supportedLocalesOf([], null); +}, "Should throw when passing null as the options argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-toobject.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-toobject.js new file mode 100644 index 0000000000..036883f5ca --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-toobject.js @@ -0,0 +1,43 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: Checks handling of non-object options arguments to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + a. Let options be ? ToObject(options). +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat.supportedLocalesOf, "function", + "Should support Intl.RelativeTimeFormat.supportedLocalesOf."); + +let called; +Object.defineProperties(Object.prototype, { + "localeMatcher": { + get() { + ++called; + return "best fit"; + } + } +}); + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), +]; + +for (const options of optionsArguments) { + called = 0; + const result = Intl.RelativeTimeFormat.supportedLocalesOf([], options); + assert.sameValue(Array.isArray(result), true, `Expected array from ${String(options)}`); + assert.sameValue(called, 1, `Expected one call from ${String(options)}`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-undefined.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-undefined.js new file mode 100644 index 0000000000..9a0832ec14 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/options-undefined.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: Checks handling of an undefined options argument to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + b. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(typeof Intl.RelativeTimeFormat.supportedLocalesOf, "function", + "Should support Intl.RelativeTimeFormat.supportedLocalesOf."); + +Object.defineProperties(Object.prototype, { + "localeMatcher": { + get() { throw new Error("Should not call localeMatcher getter"); } + } +}); + +assert.sameValue(Array.isArray(Intl.RelativeTimeFormat.supportedLocalesOf()), true, "No arguments"); +assert.sameValue(Array.isArray(Intl.RelativeTimeFormat.supportedLocalesOf([])), true, "One argument"); +assert.sameValue(Array.isArray(Intl.RelativeTimeFormat.supportedLocalesOf([], undefined)), true, "Two arguments"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/prop-desc.js new file mode 100644 index 0000000000..ea80acf8a3 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/prop-desc.js @@ -0,0 +1,31 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: > + Checks the "supportedLocalesOf" property of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.supportedLocalesOf ( locales [, options ]) + + 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. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue( + typeof Intl.RelativeTimeFormat.supportedLocalesOf, + "function", + "typeof Intl.RelativeTimeFormat.supportedLocalesOf is function" +); + +verifyProperty(Intl.RelativeTimeFormat, "supportedLocalesOf", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/result-type.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/result-type.js new file mode 100644 index 0000000000..8801c662c2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/result-type.js @@ -0,0 +1,35 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.supportedLocalesOf +description: Verifies the type of the return value of Intl.RelativeTimeFormat.supportedLocalesOf(). +info: | + Intl.RelativeTimeFormat.supportedLocalesOf ( locales [, options ]) +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +const result = Intl.RelativeTimeFormat.supportedLocalesOf("en"); +assert.sameValue(Array.isArray(result), true, + "Array.isArray() should return true"); +assert.sameValue(Object.getPrototypeOf(result), Array.prototype, + "The prototype should be Array.prototype"); +assert.sameValue(Object.isExtensible(result), true, + "Object.isExtensible() should return true"); + +assert.notSameValue(result.length, 0); +for (let i = 0; i < result.length; ++i) { + verifyProperty(result, String(i), { + "writable": true, + "enumerable": true, + "configurable": true, + }); +} + +verifyProperty(result, "length", { + "enumerable": false, + "configurable": false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/constructor/supportedLocalesOf/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/instance/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/instance/extensibility.js b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/extensibility.js new file mode 100644 index 0000000000..67ad4b9b83 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/extensibility.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: sec-Intl.RelativeTimeFormat +description: > + Intl.RelativeTimeFormat instance object extensibility +info: | + 17 ECMAScript Standard Built-in Objects: + + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue( + Object.isExtensible(new Intl.RelativeTimeFormat()), + true, + "Object.isExtensible(new Intl.RelativeTimeFormat()) returns true" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/instance/prototype.js b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/prototype.js new file mode 100644 index 0000000000..f874db89f6 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/prototype.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: sec-Intl.RelativeTimeFormat +description: > + Intl.RelativeTimeFormat instance object is created from %RelativeTimeFormatPrototype%. +info: | + Intl.RelativeTimeFormat ([ locales [ , options ]]) + + 2. Let relativeTimeFormat be ! OrdinaryCreateFromConstructor(NewTarget, "%RelativeTimeFormatPrototype%"). +features: [Intl.RelativeTimeFormat] +---*/ + +const value = new Intl.RelativeTimeFormat(); +assert.sameValue( + Object.getPrototypeOf(value), + Intl.RelativeTimeFormat.prototype, + "Object.getPrototypeOf(value) equals the value of Intl.RelativeTimeFormat.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/instance/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/instance/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..b441c56413 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/prop-desc.js @@ -0,0 +1,26 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.constructor +description: Checks the "constructor" property of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype.constructor + + The initial value of Intl.RelativeTimeFormat.prototype.constructor is %RelativeTimeFormat%. + + 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. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype, "constructor", { + value: Intl.RelativeTimeFormat, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/branding.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/branding.js new file mode 100644 index 0000000000..fa7f890ad7 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/branding.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Verifies the branding check for the "format" function of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype.format( value, unit ) + + 2. If Type(relativeTimeFormat) is not Object or relativeTimeFormat does not have an [[InitializedRelativeTimeFormat]] internal slot whose value is true, throw a TypeError exception. +features: [Intl.RelativeTimeFormat] +---*/ + +const format = Intl.RelativeTimeFormat.prototype.format; + +assert.sameValue(typeof format, "function"); + +assert.throws(TypeError, () => format.call(undefined), "undefined"); +assert.throws(TypeError, () => format.call(null), "null"); +assert.throws(TypeError, () => format.call(true), "true"); +assert.throws(TypeError, () => format.call(""), "empty string"); +assert.throws(TypeError, () => format.call(Symbol()), "symbol"); +assert.throws(TypeError, () => format.call(1), "1"); +assert.throws(TypeError, () => format.call({}), "plain object"); +assert.throws(TypeError, () => format.call(Intl.RelativeTimeFormat), "Intl.RelativeTimeFormat"); +assert.throws(TypeError, () => format.call(Intl.RelativeTimeFormat.prototype), "Intl.RelativeTimeFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-numeric-always.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-numeric-always.js new file mode 100644 index 0000000000..2a567d6d01 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-numeric-always.js @@ -0,0 +1,39 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in English. +features: [Intl.RelativeTimeFormat] +locale: [en-US] +---*/ + +const units = [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year", +]; + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +for (const unit of units) { + assert.sameValue(rtf.format(1000, unit), `in 1,000 ${unit}s`); + assert.sameValue(rtf.format(10, unit), `in 10 ${unit}s`); + assert.sameValue(rtf.format(2, unit), `in 2 ${unit}s`); + assert.sameValue(rtf.format(1, unit), `in 1 ${unit}`); + assert.sameValue(rtf.format(0, unit), `in 0 ${unit}s`); + assert.sameValue(rtf.format(-0, unit), `0 ${unit}s ago`); + assert.sameValue(rtf.format(-1, unit), `1 ${unit} ago`); + assert.sameValue(rtf.format(-2, unit), `2 ${unit}s ago`); + assert.sameValue(rtf.format(-10, unit), `10 ${unit}s ago`); + assert.sameValue(rtf.format(-1000, unit), `1,000 ${unit}s ago`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-numeric-auto.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-numeric-auto.js new file mode 100644 index 0000000000..ef84a32934 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-numeric-auto.js @@ -0,0 +1,87 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in English. +features: [Intl.RelativeTimeFormat] +locale: [en-US] +---*/ + +const units = [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year", +]; + +const rtf = new Intl.RelativeTimeFormat("en-US", { "numeric": "auto" }); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +// https://www.unicode.org/cldr/charts/33/summary/en.html#1530 +const exceptions = { + "year": { + "-1": "last year", + "0": "this year", + "1": "next year", + }, + "quarter": { + "-1": "last quarter", + "0": "this quarter", + "1": "next quarter", + }, + "month": { + "-1": "last month", + "0": "this month", + "1": "next month", + }, + "week": { + "-1": "last week", + "0": "this week", + "1": "next week", + }, + "day": { + "-1": "yesterday", + "0": "today", + "1": "tomorrow", + }, + "hour": { + "-1": "1 hour ago", + '0': 'this hour', + "1": "in 1 hour", + }, + "minute": { + "-1": "1 minute ago", + '0': 'this minute', + "1": "in 1 minute", + }, + "second": { + "-1": "1 second ago", + "0": "now", + "1": "in 1 second", + }, +}; + +for (const unit of units) { + const expected = unit in exceptions + ? [exceptions[unit]["1"], exceptions[unit]["0"], exceptions[unit]["0"], exceptions[unit]["-1"]] + : [`in 1 ${unit}`, `in 0 ${unit}s`, `0 ${unit}s ago`, `1 ${unit} ago`]; + + assert.sameValue(rtf.format(1000, unit), `in 1,000 ${unit}s`); + assert.sameValue(rtf.format(10, unit), `in 10 ${unit}s`); + assert.sameValue(rtf.format(2, unit), `in 2 ${unit}s`); + assert.sameValue(rtf.format(1, unit), expected[0]); + assert.sameValue(rtf.format(0, unit), expected[1]); + assert.sameValue(rtf.format(-0, unit), expected[2]); + assert.sameValue(rtf.format(-1, unit), expected[3]); + assert.sameValue(rtf.format(-2, unit), `2 ${unit}s ago`); + assert.sameValue(rtf.format(-10, unit), `10 ${unit}s ago`); + assert.sameValue(rtf.format(-1000, unit), `1,000 ${unit}s ago`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-style-short.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-style-short.js new file mode 100644 index 0000000000..869ce5036a --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/en-us-style-short.js @@ -0,0 +1,42 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in English. +features: [Intl.RelativeTimeFormat] +locale: [en-US] +---*/ + +const units = { + "second": ["sec."], + "minute": ["min."], + "hour": ["hr."], + "day": ["day", "days"], + "week": ["wk."], + "month": ["mo."], + "quarter": ["qtr.", "qtrs."], + "year": ["yr."], +}; + +const rtf = new Intl.RelativeTimeFormat("en-US", { + "style": "short", +}); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +for (const [unitArgument, unitStrings] of Object.entries(units)) { + const [singular, plural = singular] = unitStrings; + assert.sameValue(rtf.format(1000, unitArgument), `in 1,000 ${plural}`); + assert.sameValue(rtf.format(10, unitArgument), `in 10 ${plural}`); + assert.sameValue(rtf.format(2, unitArgument), `in 2 ${plural}`); + assert.sameValue(rtf.format(1, unitArgument), `in 1 ${singular}`); + assert.sameValue(rtf.format(0, unitArgument), `in 0 ${plural}`); + assert.sameValue(rtf.format(-0, unitArgument), `0 ${plural} ago`); + assert.sameValue(rtf.format(-1, unitArgument), `1 ${singular} ago`); + assert.sameValue(rtf.format(-2, unitArgument), `2 ${plural} ago`); + assert.sameValue(rtf.format(-10, unitArgument), `10 ${plural} ago`); + assert.sameValue(rtf.format(-1000, unitArgument), `1,000 ${plural} ago`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/length.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/length.js new file mode 100644 index 0000000000..e2f791593b --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/length.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: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the "length" property of Intl.RelativeTimeFormat.prototype.format(). +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 RelativeTimeFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype.format, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/name.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/name.js new file mode 100644 index 0000000000..d71d98d964 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/name.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: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the "name" property of Intl.RelativeTimeFormat.prototype.format(). +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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype.format, "name", { + value: "format", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-long.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-long.js new file mode 100644 index 0000000000..596e1b914c --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-long.js @@ -0,0 +1,71 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in Polish. +features: [Intl.RelativeTimeFormat] +locale: [pl-PL] +---*/ + +function regular(s) { + return { + "many": s, + "few": s + "y", + "one": s + "ę", + } +} + +// https://www.unicode.org/cldr/charts/33/summary/pl.html#1419 +const units = { + "second": regular("sekund"), + "minute": regular("minut"), + "hour": regular("godzin"), + "day": { + "many": "dni", + "few": "dni", + "one": "dzień", + }, + "week": { + "many": "tygodni", + "few": "tygodnie", + "one": "tydzień", + }, + "month": { + 1000: "miesięcy", + "many": "miesięcy", + "few": "miesiące", + "one": "miesiąc", + }, + "quarter": { + "many": "kwartałów", + "few": "kwartały", + "one": "kwartał", + }, + "year": { + "many": "lat", + "few": "lata", + "one": "rok", + }, +}; + +const rtf = new Intl.RelativeTimeFormat("pl-PL", { + "style": "long", +}); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +for (const [unitArgument, expected] of Object.entries(units)) { + assert.sameValue(rtf.format(1000, unitArgument), `za 1000 ${expected.many}`); + assert.sameValue(rtf.format(10, unitArgument), `za 10 ${expected.many}`); + assert.sameValue(rtf.format(2, unitArgument), `za 2 ${expected.few}`); + assert.sameValue(rtf.format(1, unitArgument), `za 1 ${expected.one}`); + assert.sameValue(rtf.format(0, unitArgument), `za 0 ${expected.many}`); + assert.sameValue(rtf.format(-0, unitArgument), `0 ${expected.many} temu`); + assert.sameValue(rtf.format(-1, unitArgument), `1 ${expected.one} temu`); + assert.sameValue(rtf.format(-2, unitArgument), `2 ${expected.few} temu`); + assert.sameValue(rtf.format(-10, unitArgument), `10 ${expected.many} temu`); + assert.sameValue(rtf.format(-1000, unitArgument), `1000 ${expected.many} temu`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-narrow.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-narrow.js new file mode 100644 index 0000000000..12d32ce1aa --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-narrow.js @@ -0,0 +1,62 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in Polish. +features: [Intl.RelativeTimeFormat] +locale: [pl-PL] +---*/ + +function always(s) { + return { + "many": s, + "few": s, + "one": s, + } +} + +// https://www.unicode.org/cldr/charts/33/summary/pl.html#1419 +const units = { + "second": always("s"), + "minute": always("min"), + "hour": always("g."), + "day": { + "many": "dni", + "few": "dni", + "one": "dzień", + }, + "week": { + "many": "tyg.", + "few": "tyg.", + "one": "tydz.", + }, + "month": always("mies."), + "quarter": always("kw."), + "year": { + "many": "lat", + "few": "lata", + "one": "rok", + }, +}; + +const rtf = new Intl.RelativeTimeFormat("pl-PL", { + "style": "narrow", +}); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +for (const [unitArgument, expected] of Object.entries(units)) { + assert.sameValue(rtf.format(1000, unitArgument), `za 1000 ${expected.many}`); + assert.sameValue(rtf.format(10, unitArgument), `za 10 ${expected.many}`); + assert.sameValue(rtf.format(2, unitArgument), `za 2 ${expected.few}`); + assert.sameValue(rtf.format(1, unitArgument), `za 1 ${expected.one}`); + assert.sameValue(rtf.format(0, unitArgument), `za 0 ${expected.many}`); + assert.sameValue(rtf.format(-0, unitArgument), `0 ${expected.many} temu`); + assert.sameValue(rtf.format(-1, unitArgument), `1 ${expected.one} temu`); + assert.sameValue(rtf.format(-2, unitArgument), `2 ${expected.few} temu`); + assert.sameValue(rtf.format(-10, unitArgument), `10 ${expected.many} temu`); + assert.sameValue(rtf.format(-1000, unitArgument), `1000 ${expected.many} temu`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-short.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-short.js new file mode 100644 index 0000000000..27a4a972d8 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-short.js @@ -0,0 +1,62 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in Polish. +features: [Intl.RelativeTimeFormat] +locale: [pl-PL] +---*/ + +function always(s) { + return { + "many": s, + "few": s, + "one": s, + } +} + +// https://www.unicode.org/cldr/charts/33/summary/pl.html#1419 +const units = { + "second": always("sek."), + "minute": always("min"), + "hour": always("godz."), + "day": { + "many": "dni", + "few": "dni", + "one": "dzień", + }, + "week": { + "many": "tyg.", + "few": "tyg.", + "one": "tydz.", + }, + "month": always("mies."), + "quarter": always("kw."), + "year": { + "many": "lat", + "few": "lata", + "one": "rok", + }, +}; + +const rtf = new Intl.RelativeTimeFormat("pl-PL", { + "style": "short", +}); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +for (const [unitArgument, expected] of Object.entries(units)) { + assert.sameValue(rtf.format(1000, unitArgument), `za 1000 ${expected.many}`); + assert.sameValue(rtf.format(10, unitArgument), `za 10 ${expected.many}`); + assert.sameValue(rtf.format(2, unitArgument), `za 2 ${expected.few}`); + assert.sameValue(rtf.format(1, unitArgument), `za 1 ${expected.one}`); + assert.sameValue(rtf.format(0, unitArgument), `za 0 ${expected.many}`); + assert.sameValue(rtf.format(-0, unitArgument), `0 ${expected.many} temu`); + assert.sameValue(rtf.format(-1, unitArgument), `1 ${expected.one} temu`); + assert.sameValue(rtf.format(-2, unitArgument), `2 ${expected.few} temu`); + assert.sameValue(rtf.format(-10, unitArgument), `10 ${expected.many} temu`); + assert.sameValue(rtf.format(-1000, unitArgument), `1000 ${expected.many} temu`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/prop-desc.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/prop-desc.js new file mode 100644 index 0000000000..0b4b9f8572 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/prop-desc.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the "format" property of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype.format () + + 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. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue( + typeof Intl.RelativeTimeFormat.prototype.format, + "function", + "typeof Intl.RelativeTimeFormat.prototype.format is function" +); + +verifyProperty(Intl.RelativeTimeFormat.prototype, "format", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/unit-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/unit-invalid.js new file mode 100644 index 0000000000..186ff57ec9 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/unit-invalid.js @@ -0,0 +1,55 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the handling of invalid unit arguments to Intl.RelativeTimeFormat.prototype.format(). +info: | + SingularRelativeTimeUnit ( unit ) + + 10. If unit is not one of "second", "minute", "hour", "day", "week", "month", "quarter", "year", throw a RangeError exception. + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.format, "function"); + +const values = [ + undefined, + null, + true, + 1, + 0.1, + NaN, + {}, + "", + "SECOND", + "MINUTE", + "HOUR", + "DAY", + "WEEK", + "MONTH", + "QUARTER", + "YEAR", + "decade", + "decades", + "century", + "centuries", + "millisecond", + "milliseconds", + "microsecond", + "microseconds", + "nanosecond", + "nanoseconds", +]; + +for (const value of values) { + assert.throws(RangeError, () => rtf.format(0, value), String(value)); +} + +const symbol = Symbol(); +assert.throws(TypeError, () => rtf.format(0, symbol), "symbol"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/unit-plural.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/unit-plural.js new file mode 100644 index 0000000000..faf8e37ecc --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/unit-plural.js @@ -0,0 +1,42 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the handling of plural unit arguments to Intl.RelativeTimeFormat.prototype.format(). +info: | + SingularRelativeTimeUnit ( unit ) + + 2. If unit is "seconds", return "second". + 3. If unit is "minutes", return "minute". + 4. If unit is "hours", return "hour". + 5. If unit is "days", return "day". + 6. If unit is "weeks", return "week". + 7. If unit is "months", return "month". + 8. If unit is "quarters", return "quarter". + 9. If unit is "years", return "year". + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +const units = [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year", +]; + +for (const unit of units) { + assert.sameValue(rtf.format(3, unit + "s"), rtf.format(3, unit), + `Should support unit ${unit}s as a synonym for ${unit}`) +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-non-finite.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-non-finite.js new file mode 100644 index 0000000000..77827e4c68 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-non-finite.js @@ -0,0 +1,38 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the handling of invalid value arguments to Intl.RelativeTimeFormat.prototype.format(). +info: | + Intl.RelativeTimeFormat.prototype.format( value, unit ) + + 3. Let value be ? ToNumber(value). + + PartitionRelativeTimePattern ( relativeTimeFormat, value, unit ) + + 4. If isFinite(value) is false, then throw a RangeError exception. + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +const values = [ + [undefined, "undefined"], + [NaN, "NaN"], + [Infinity, "Infinity"], + [-Infinity, "-Infinity"], + ["string", '"string"'], + [{}, "empty object"], + [{ toString() { return NaN; }, valueOf: undefined }, "object with toString"], + [{ valueOf() { return NaN; }, toString: undefined }, "object with valueOf"], +]; + +for (const [value, name] of values) { + assert.throws(RangeError, () => rtf.format(value, "second"), name); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-symbol.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-symbol.js new file mode 100644 index 0000000000..83b1617f29 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-symbol.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: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the handling of invalid value arguments to Intl.RelativeTimeFormat.prototype.format(). +info: | + Intl.RelativeTimeFormat.prototype.format( value, unit ) + + 3. Let value be ? ToNumber(value). + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +const symbol = Symbol(); +assert.throws(TypeError, () => rtf.format(symbol, "second")); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-tonumber.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-tonumber.js new file mode 100644 index 0000000000..2ca5ae6100 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/format/value-tonumber.js @@ -0,0 +1,40 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the handling of non-number value arguments to Intl.RelativeTimeFormat.prototype.format(). +info: | + Intl.RelativeTimeFormat.prototype.format( value, unit ) + + 3. Let value be ? ToNumber(value). + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +const values = [ + [null, 0], + + [true, 1], + [false, 0], + + ["5", 5], + ["-5", -5], + ["0", 0], + ["-0", -0], + [" 6 ", 6], + + [{ toString() { return 7; } }, 7, "object with toString"], + [{ valueOf() { return 7; } }, 7, "object with valueOf"], +]; + +for (const [input, number, name = String(input)] of values) { + assert.sameValue(rtf.format(input, "second"), rtf.format(number, "second"), + `Should treat ${name} as ${number}`) +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/branding.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/branding.js new file mode 100644 index 0000000000..fa5f00ad62 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/branding.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Verifies the branding check for the "formatToParts" function of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype.formatToParts( value, unit ) + + 2. If Type(relativeTimeFormat) is not Object or relativeTimeFormat does not have an [[InitializedRelativeTimeFormat]] internal slot whose value is true, throw a TypeError exception. +features: [Intl.RelativeTimeFormat] +---*/ + +const formatToParts = Intl.RelativeTimeFormat.prototype.formatToParts; + +assert.sameValue(typeof formatToParts, "function"); + +assert.throws(TypeError, () => formatToParts.call(undefined), "undefined"); +assert.throws(TypeError, () => formatToParts.call(null), "null"); +assert.throws(TypeError, () => formatToParts.call(true), "true"); +assert.throws(TypeError, () => formatToParts.call(""), "empty string"); +assert.throws(TypeError, () => formatToParts.call(Symbol()), "symbol"); +assert.throws(TypeError, () => formatToParts.call(1), "1"); +assert.throws(TypeError, () => formatToParts.call({}), "plain object"); +assert.throws(TypeError, () => formatToParts.call(Intl.RelativeTimeFormat), "Intl.RelativeTimeFormat"); +assert.throws(TypeError, () => formatToParts.call(Intl.RelativeTimeFormat.prototype), "Intl.RelativeTimeFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-always.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-always.js new file mode 100644 index 0000000000..b10ee9a701 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-always.js @@ -0,0 +1,107 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.formatToParts() in English. +features: [Intl.RelativeTimeFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + assert.sameValue(actual[i].unit, expected[i].unit, `${message}: parts[${i}].unit`); + } +} + +const units = [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year", +]; + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +for (const unit of units) { + verifyFormatParts(rtf.formatToParts(1000, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "1", "unit": unit }, + { "type": "group", "value": ",", "unit": unit }, + { "type": "integer", "value": "000", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(1000, ${unit})`); + + verifyFormatParts(rtf.formatToParts(10, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "10", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(10, ${unit})`); + + verifyFormatParts(rtf.formatToParts(2, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "2", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(2, ${unit})`); + + verifyFormatParts(rtf.formatToParts(1, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "1", "unit": unit }, + { "type": "literal", "value": ` ${unit}` }, + ], `formatToParts(1, ${unit})`); + + verifyFormatParts(rtf.formatToParts(0, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "0", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(0, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-0, unit), [ + { "type": "integer", "value": "0", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ], `formatToParts(-0, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-1, unit), [ + { "type": "integer", "value": "1", "unit": unit }, + { "type": "literal", "value": ` ${unit} ago` }, + ], `formatToParts(-1, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-2, unit), [ + { "type": "integer", "value": "2", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ], `formatToParts(-2, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-10, unit), [ + { "type": "integer", "value": "10", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ], `formatToParts(-10, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-1000, unit), [ + { "type": "integer", "value": "1", "unit": unit }, + { "type": "group", "value": ",", "unit": unit }, + { "type": "integer", "value": "000", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ], `formatToParts(-1000, ${unit})`); + + verifyFormatParts(rtf.formatToParts(123456.78, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "123", "unit": unit }, + { "type": "group", "value": ",", "unit": unit }, + { "type": "integer", "value": "456", "unit": unit }, + { "type": "decimal", "value": ".", "unit": unit }, + { "type": "fraction", "value": "78", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(123456.78, ${unit})`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-auto.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-auto.js new file mode 100644 index 0000000000..fdf9ab6487 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-numeric-auto.js @@ -0,0 +1,156 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.formatToParts() in English. +features: [Intl.RelativeTimeFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + assert.sameValue(actual[i].unit, expected[i].unit, `${message}: parts[${i}].unit`); + } +} + +function expected(key, unit, default_) { + // https://www.unicode.org/cldr/charts/33/summary/en.html#1530 + const exceptions = { + "year": { + "-1": "last year", + "0": "this year", + "1": "next year", + }, + "quarter": { + "-1": "last quarter", + "0": "this quarter", + "1": "next quarter", + }, + "month": { + "-1": "last month", + "0": "this month", + "1": "next month", + }, + "week": { + "-1": "last week", + "0": "this week", + "1": "next week", + }, + "day": { + "-1": "yesterday", + "0": "today", + "1": "tomorrow", + }, + "hour": { + "0": "this hour", + }, + "minute": { + "0": "this minute", + }, + "second": { + "0": "now", + }, + }; + + const exception = exceptions[unit] || {}; + if (key in exception) { + return [ + { "type": "literal", "value": exception[key] }, + ] + } + + return default_; +} + +const units = [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year", +]; + +const rtf = new Intl.RelativeTimeFormat("en-US", { "numeric": "auto" }); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +for (const unit of units) { + verifyFormatParts(rtf.formatToParts(1000, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "1", "unit": unit }, + { "type": "group", "value": ",", "unit": unit }, + { "type": "integer", "value": "000", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(1000, ${unit})`); + + verifyFormatParts(rtf.formatToParts(10, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "10", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(10, ${unit})`); + + verifyFormatParts(rtf.formatToParts(2, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "2", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(2, ${unit})`); + + verifyFormatParts(rtf.formatToParts(1, unit), expected("1", unit, [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "1", "unit": unit }, + { "type": "literal", "value": ` ${unit}` }, + ]), `formatToParts(1, ${unit})`); + + verifyFormatParts(rtf.formatToParts(0, unit), expected("0", unit, [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "0", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ]), `formatToParts(0, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-0, unit), expected("0", unit, [ + { "type": "integer", "value": "0", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ]), `formatToParts(-0, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-1, unit), expected("-1", unit, [ + { "type": "integer", "value": "1", "unit": unit }, + { "type": "literal", "value": ` ${unit} ago` }, + ]), `formatToParts(-1, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-2, unit), [ + { "type": "integer", "value": "2", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ], `formatToParts(-2, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-10, unit), [ + { "type": "integer", "value": "10", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ], `formatToParts(-10, ${unit})`); + + verifyFormatParts(rtf.formatToParts(-1000, unit), [ + { "type": "integer", "value": "1", "unit": unit }, + { "type": "group", "value": ",", "unit": unit }, + { "type": "integer", "value": "000", "unit": unit }, + { "type": "literal", "value": ` ${unit}s ago` }, + ], `formatToParts(-1000, ${unit})`); + + verifyFormatParts(rtf.formatToParts(123456.78, unit), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "123", "unit": unit }, + { "type": "group", "value": ",", "unit": unit }, + { "type": "integer", "value": "456", "unit": unit }, + { "type": "decimal", "value": ".", "unit": unit }, + { "type": "fraction", "value": "78", "unit": unit }, + { "type": "literal", "value": ` ${unit}s` }, + ], `formatToParts(123456.78, ${unit})`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-style-short.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-style-short.js new file mode 100644 index 0000000000..812a66d8c2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-style-short.js @@ -0,0 +1,111 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.formatToParts() in English. +features: [Intl.RelativeTimeFormat] +locale: [en-US] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + assert.sameValue(actual[i].unit, expected[i].unit, `${message}: parts[${i}].unit`); + } +} + +const units = { + "second": ["sec."], + "minute": ["min."], + "hour": ["hr."], + "day": ["day", "days"], + "week": ["wk."], + "month": ["mo."], + "quarter": ["qtr.", "qtrs."], + "year": ["yr."], +}; + +const rtf = new Intl.RelativeTimeFormat("en-US", { + "style": "short", +}); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +for (const [unitArgument, unitStrings] of Object.entries(units)) { + const [singular, plural = singular] = unitStrings; + + verifyFormatParts(rtf.formatToParts(1000, unitArgument), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "group", "value": ",", "unit": unitArgument }, + { "type": "integer", "value": "000", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural}` }, + ], `formatToParts(1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(10, unitArgument), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural}` }, + ], `formatToParts(10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(2, unitArgument), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural}` }, + ], `formatToParts(2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(1, unitArgument), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${singular}` }, + ], `formatToParts(1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(0, unitArgument), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural}` }, + ], `formatToParts(0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-0, unitArgument), [ + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural} ago` }, + ], `formatToParts(-0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1, unitArgument), [ + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${singular} ago` }, + ], `formatToParts(-1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-2, unitArgument), [ + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural} ago` }, + ], `formatToParts(-2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-10, unitArgument), [ + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural} ago` }, + ], `formatToParts(-10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1000, unitArgument), [ + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "group", "value": ",", "unit": unitArgument }, + { "type": "integer", "value": "000", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural} ago` }, + ], `formatToParts(-1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(123456.78, unitArgument), [ + { "type": "literal", "value": "in " }, + { "type": "integer", "value": "123", "unit": unitArgument }, + { "type": "group", "value": ",", "unit": unitArgument }, + { "type": "integer", "value": "456", "unit": unitArgument }, + { "type": "decimal", "value": ".", "unit": unitArgument }, + { "type": "fraction", "value": "78", "unit": unitArgument }, + { "type": "literal", "value": ` ${plural}` }, + ], `formatToParts(123456.78, ${unitArgument})`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/length.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/length.js new file mode 100644 index 0000000000..c6badcd71a --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/length.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: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the "length" property of Intl.RelativeTimeFormat.prototype.formatToParts(). +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 RelativeTimeFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype.formatToParts, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/name.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/name.js new file mode 100644 index 0000000000..df10bfe3a7 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/name.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: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the "name" property of Intl.RelativeTimeFormat.prototype.formatToParts(). +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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype.formatToParts, "name", { + value: "formatToParts", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-long.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-long.js new file mode 100644 index 0000000000..0a10fe68e6 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-long.js @@ -0,0 +1,141 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in Polish. +features: [Intl.RelativeTimeFormat] +locale: [pl-PL] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + assert.sameValue(actual[i].unit, expected[i].unit, `${message}: parts[${i}].unit`); + } +} + +function regular(s) { + return { + "many": s, + "few": s + "y", + "one": s + "ę", + "other": s + "y", + } +} + +// https://www.unicode.org/cldr/charts/33/summary/pl.html#1419 +const units = { + "second": regular("sekund"), + "minute": regular("minut"), + "hour": regular("godzin"), + "day": { + "many": "dni", + "few": "dni", + "one": "dzień", + "other": "dnia", + }, + "week": { + "many": "tygodni", + "few": "tygodnie", + "one": "tydzień", + "other": "tygodnia", + }, + "month": { + 1000: "miesięcy", + "many": "miesięcy", + "few": "miesiące", + "one": "miesiąc", + "other": "miesiąca", + }, + "quarter": { + "many": "kwartałów", + "few": "kwartały", + "one": "kwartał", + "other": "kwartału", + }, + "year": { + "many": "lat", + "few": "lata", + "one": "rok", + "other": "roku", + }, +}; + +const rtf = new Intl.RelativeTimeFormat("pl-PL", { + "style": "long", +}); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +for (const [unitArgument, expected] of Object.entries(units)) { + verifyFormatParts(rtf.formatToParts(1000, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "1000", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(10, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(2, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.few}` }, + ], `formatToParts(2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(1, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.one}` }, + ], `formatToParts(1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(0, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-0, unitArgument), [ + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1, unitArgument), [ + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.one} temu` }, + ], `formatToParts(-1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-2, unitArgument), [ + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.few} temu` }, + ], `formatToParts(-2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-10, unitArgument), [ + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1000, unitArgument), [ + { "type": "integer", "value": "1000", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(123456.78, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "123", "unit": unitArgument }, + { "type": "group", "value": "\u00a0", "unit": unitArgument }, + { "type": "integer", "value": "456", "unit": unitArgument }, + { "type": "decimal", "value": ",", "unit": unitArgument }, + { "type": "fraction", "value": "78", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.other}` }, + ], `formatToParts(123456.78, ${unitArgument})`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-narrow.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-narrow.js new file mode 100644 index 0000000000..f8af023ca2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-narrow.js @@ -0,0 +1,130 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in Polish. +features: [Intl.RelativeTimeFormat] +locale: [pl-PL] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + assert.sameValue(actual[i].unit, expected[i].unit, `${message}: parts[${i}].unit`); + } +} + +function always(s) { + return { + "many": s, + "few": s, + "one": s, + "other": s, + } +} + +// https://www.unicode.org/cldr/charts/33/summary/pl.html#1419 +const units = { + "second": always("s"), + "minute": always("min"), + "hour": always("g."), + "day": { + "many": "dni", + "few": "dni", + "one": "dzień", + "other": "dnia", + }, + "week": { + "many": "tyg.", + "few": "tyg.", + "one": "tydz.", + "other": "tyg.", + }, + "month": always("mies."), + "quarter": always("kw."), + "year": { + "many": "lat", + "few": "lata", + "one": "rok", + "other": "roku", + }, +}; + +const rtf = new Intl.RelativeTimeFormat("pl-PL", { + "style": "narrow", +}); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +for (const [unitArgument, expected] of Object.entries(units)) { + verifyFormatParts(rtf.formatToParts(1000, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "1000", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(10, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(2, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.few}` }, + ], `formatToParts(2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(1, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.one}` }, + ], `formatToParts(1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(0, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-0, unitArgument), [ + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1, unitArgument), [ + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.one} temu` }, + ], `formatToParts(-1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-2, unitArgument), [ + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.few} temu` }, + ], `formatToParts(-2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-10, unitArgument), [ + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1000, unitArgument), [ + { "type": "integer", "value": "1000", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(123456.78, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "123", "unit": unitArgument }, + { "type": "group", "value": "\u00a0", "unit": unitArgument }, + { "type": "integer", "value": "456", "unit": unitArgument }, + { "type": "decimal", "value": ",", "unit": unitArgument }, + { "type": "fraction", "value": "78", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.other}` }, + ], `formatToParts(123456.78, ${unitArgument})`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-short.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-short.js new file mode 100644 index 0000000000..97734b1365 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/pl-pl-style-short.js @@ -0,0 +1,130 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the behavior of Intl.RelativeTimeFormat.prototype.format() in Polish. +features: [Intl.RelativeTimeFormat] +locale: [pl-PL] +---*/ + +function verifyFormatParts(actual, expected, message) { + assert.sameValue(actual.length, expected.length, `${message}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, `${message}: parts[${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, `${message}: parts[${i}].value`); + assert.sameValue(actual[i].unit, expected[i].unit, `${message}: parts[${i}].unit`); + } +} + +function always(s) { + return { + "many": s, + "few": s, + "one": s, + "other": s, + } +} + +// https://www.unicode.org/cldr/charts/33/summary/pl.html#1419 +const units = { + "second": always("sek."), + "minute": always("min"), + "hour": always("godz."), + "day": { + "many": "dni", + "few": "dni", + "one": "dzień", + "other": "dnia", + }, + "week": { + "many": "tyg.", + "few": "tyg.", + "one": "tydz.", + "other": "tyg.", + }, + "month": always("mies."), + "quarter": always("kw."), + "year": { + "many": "lat", + "few": "lata", + "one": "rok", + "other": "roku", + }, +}; + +const rtf = new Intl.RelativeTimeFormat("pl-PL", { + "style": "short", +}); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +for (const [unitArgument, expected] of Object.entries(units)) { + verifyFormatParts(rtf.formatToParts(1000, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "1000", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(10, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(2, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.few}` }, + ], `formatToParts(2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(1, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.one}` }, + ], `formatToParts(1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(0, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many}` }, + ], `formatToParts(0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-0, unitArgument), [ + { "type": "integer", "value": "0", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-0, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1, unitArgument), [ + { "type": "integer", "value": "1", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.one} temu` }, + ], `formatToParts(-1, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-2, unitArgument), [ + { "type": "integer", "value": "2", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.few} temu` }, + ], `formatToParts(-2, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-10, unitArgument), [ + { "type": "integer", "value": "10", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-10, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(-1000, unitArgument), [ + { "type": "integer", "value": "1000", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.many} temu` }, + ], `formatToParts(-1000, ${unitArgument})`); + + verifyFormatParts(rtf.formatToParts(123456.78, unitArgument), [ + { "type": "literal", "value": "za " }, + { "type": "integer", "value": "123", "unit": unitArgument }, + { "type": "group", "value": "\u00a0", "unit": unitArgument }, + { "type": "integer", "value": "456", "unit": unitArgument }, + { "type": "decimal", "value": ",", "unit": unitArgument }, + { "type": "fraction", "value": "78", "unit": unitArgument }, + { "type": "literal", "value": ` ${expected.other}` }, + ], `formatToParts(123456.78, ${unitArgument})`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/prop-desc.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/prop-desc.js new file mode 100644 index 0000000000..257c9ea533 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/prop-desc.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the "formatToParts" property of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype.formatToParts () + + 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. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue( + typeof Intl.RelativeTimeFormat.prototype.formatToParts, + "function", + "typeof Intl.RelativeTimeFormat.prototype.formatToParts is function" +); + +verifyProperty(Intl.RelativeTimeFormat.prototype, "formatToParts", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/result-type.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/result-type.js new file mode 100644 index 0000000000..127642a5ef --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/result-type.js @@ -0,0 +1,84 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the handling of plural unit arguments to Intl.RelativeTimeFormat.prototype.formatToParts(). +info: | + FormatRelativeTimeToParts ( relativeTimeFormat, value, unit ) + + 3. Let n be 0. + 4. For each part in parts, do: + a. Let O be ObjectCreate(%ObjectPrototype%). + b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]). + c. Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]). + d. If part has a [[Unit]] field, + i. Perform ! CreateDataPropertyOrThrow(O, "unit", part.[[Unit]]). + e. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), O). + f. Increment n by 1. + +features: [Intl.RelativeTimeFormat] +includes: [propertyHelper.js] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +const parts = rtf.formatToParts(3, "second"); + +assert.sameValue(Object.getPrototypeOf(parts), Array.prototype, "parts: prototype"); +assert.sameValue(Array.isArray(parts), true, "parts: isArray"); +assert.sameValue(parts.length, 3, "parts: length"); + +assert.sameValue(Object.getPrototypeOf(parts[0]), Object.prototype, "parts[0]: prototype"); +verifyProperty(parts[0], "type", { + value: "literal", + writable: true, + enumerable: true, + configurable: true, +}); +verifyProperty(parts[0], "value", { + value: "in ", + writable: true, + enumerable: true, + configurable: true, +}); + + +assert.sameValue(Object.getPrototypeOf(parts[1]), Object.prototype, "parts[1]: prototype"); +verifyProperty(parts[1], "type", { + value: "integer", + writable: true, + enumerable: true, + configurable: true, +}); +verifyProperty(parts[1], "value", { + value: "3", + writable: true, + enumerable: true, + configurable: true, +}); +verifyProperty(parts[1], "unit", { + value: "second", + writable: true, + enumerable: true, + configurable: true, +}); + + +assert.sameValue(Object.getPrototypeOf(parts[2]), Object.prototype, "parts[2]: prototype"); +verifyProperty(parts[2], "type", { + value: "literal", + writable: true, + enumerable: true, + configurable: true, +}); +verifyProperty(parts[2], "value", { + value: " seconds", + writable: true, + enumerable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/unit-invalid.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/unit-invalid.js new file mode 100644 index 0000000000..94e4355e09 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/unit-invalid.js @@ -0,0 +1,55 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the handling of invalid unit arguments to Intl.RelativeTimeFormat.prototype.formatToParts(). +info: | + SingularRelativeTimeUnit ( unit ) + + 10. If unit is not one of "second", "minute", "hour", "day", "week", "month", "quarter", "year", throw a RangeError exception. + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.formatToParts, "function"); + +const values = [ + undefined, + null, + true, + 1, + 0.1, + NaN, + {}, + "", + "SECOND", + "MINUTE", + "HOUR", + "DAY", + "WEEK", + "MONTH", + "QUARTER", + "YEAR", + "decade", + "decades", + "century", + "centuries", + "millisecond", + "milliseconds", + "microsecond", + "microseconds", + "nanosecond", + "nanoseconds", +]; + +for (const value of values) { + assert.throws(RangeError, () => rtf.formatToParts(0, value), String(value)); +} + +const symbol = Symbol(); +assert.throws(TypeError, () => rtf.formatToParts(0, symbol), "symbol"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/unit-plural.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/unit-plural.js new file mode 100644 index 0000000000..210ce7c8b4 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/unit-plural.js @@ -0,0 +1,54 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the handling of plural unit arguments to Intl.RelativeTimeFormat.prototype.formatToParts(). +info: | + SingularRelativeTimeUnit ( unit ) + + 2. If unit is "seconds", return "second". + 3. If unit is "minutes", return "minute". + 4. If unit is "hours", return "hour". + 5. If unit is "days", return "day". + 6. If unit is "weeks", return "week". + 7. If unit is "months", return "month". + 8. If unit is "quarters", return "quarter". + 9. If unit is "years", return "year". + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +const units = [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year", +]; + +for (const unit of units) { + const plural = rtf.formatToParts(3, unit + "s"); + const singular = rtf.formatToParts(3, unit); + + assert.sameValue(plural.length, singular.length, + `Should support unit ${unit}s as a synonym for ${unit}: length`); + + for (let i = 0; i < plural.length; ++i) { + assert.sameValue(plural[i].type, singular[i].type, + `Should support unit ${unit}s as a synonym for ${unit}: [${i}].type`); + assert.sameValue(plural[i].value, singular[i].value, + `Should support unit ${unit}s as a synonym for ${unit}: [${i}].value`); + assert.sameValue(plural[i].unit, singular[i].unit, + `Should support unit ${unit}s as a synonym for ${unit}: [${i}].unit`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-non-finite.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-non-finite.js new file mode 100644 index 0000000000..f0c888d165 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-non-finite.js @@ -0,0 +1,38 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the handling of invalid value arguments to Intl.RelativeTimeFormat.prototype.formatToParts(). +info: | + Intl.RelativeTimeFormat.prototype.formatToParts( value, unit ) + + 3. Let value be ? ToNumber(value). + + PartitionRelativeTimePattern ( relativeTimeFormat, value, unit ) + + 4. If isFinite(value) is false, then throw a RangeError exception. + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +const values = [ + [undefined, "undefined"], + [NaN, "NaN"], + [Infinity, "Infinity"], + [-Infinity, "-Infinity"], + ["string", '"string"'], + [{}, "empty object"], + [{ toString() { return NaN; }, valueOf: undefined }, "object with toString"], + [{ valueOf() { return NaN; }, toString: undefined }, "object with valueOf"], +]; + +for (const [value, name] of values) { + assert.throws(RangeError, () => rtf.formatToParts(value, "second"), name); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-symbol.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-symbol.js new file mode 100644 index 0000000000..6592cf3fa1 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-symbol.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: sec-Intl.RelativeTimeFormat.prototype.formatToParts +description: Checks the handling of invalid value arguments to Intl.RelativeTimeFormat.prototype.formatToParts(). +info: | + Intl.RelativeTimeFormat.prototype.formatToParts( value, unit ) + + 3. Let value be ? ToNumber(value). + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.formatToParts, "function", "formatToParts should be supported"); + +const symbol = Symbol(); +assert.throws(TypeError, () => rtf.formatToParts(symbol, "second")); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-tonumber.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-tonumber.js new file mode 100644 index 0000000000..7fc4c733a0 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/formatToParts/value-tonumber.js @@ -0,0 +1,52 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.format +description: Checks the handling of non-number value arguments to Intl.RelativeTimeFormat.prototype.format(). +info: | + Intl.RelativeTimeFormat.prototype.format( value, unit ) + + 3. Let value be ? ToNumber(value). + +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-US"); + +assert.sameValue(typeof rtf.format, "function", "format should be supported"); + +const values = [ + [null, 0], + + [true, 1], + [false, 0], + + ["5", 5], + ["-5", -5], + ["0", 0], + ["-0", -0], + [" 6 ", 6], + + [{ toString() { return 7; } }, 7, "object with toString"], + [{ valueOf() { return 7; } }, 7, "object with valueOf"], +]; + +for (const [input, number, name = String(input)] of values) { + const actual = rtf.formatToParts(input, "second"); + const expected = rtf.formatToParts(number, "second"); + + assert.sameValue(actual.length, expected.length, + `Should treat ${name} as ${number}: length`); + + for (let i = 0; i < actual.length; ++i) { + assert.sameValue(actual[i].type, expected[i].type, + `Should treat ${name} as ${number}: [${i}].type`); + assert.sameValue(actual[i].value, expected[i].value, + `Should treat ${name} as ${number}: [${i}].value`); + assert.sameValue(actual[i].unit, expected[i].unit, + `Should treat ${name} as ${number}: [${i}].unit`); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/prop-desc.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/prop-desc.js new file mode 100644 index 0000000000..c9aa6913c2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/prop-desc.js @@ -0,0 +1,24 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype +description: > + Checks the "prototype" property of the RelativeTimeFormat constructor. +info: | + Intl.RelativeTimeFormat.prototype + + The value of Intl.RelativeTimeFormat.prototype is %RelativeTimeFormatPrototype%. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/branding.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/branding.js new file mode 100644 index 0000000000..ba3ab34bee --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/branding.js @@ -0,0 +1,28 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.resolvedOptions +description: Verifies the branding check for the "resolvedOptions" function of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype.resolvedOptions () + + 2. If Type(relativeTimeFormat) is not Object or relativeTimeFormat does not have an [[InitializedRelativeTimeFormat]] internal slot whose value is true, throw a TypeError exception. +features: [Intl.RelativeTimeFormat] +---*/ + +const resolvedOptions = Intl.RelativeTimeFormat.prototype.resolvedOptions; + +assert.sameValue(typeof resolvedOptions, "function"); + +assert.throws(TypeError, () => resolvedOptions.call(undefined), "undefined"); +assert.throws(TypeError, () => resolvedOptions.call(null), "null"); +assert.throws(TypeError, () => resolvedOptions.call(true), "true"); +assert.throws(TypeError, () => resolvedOptions.call(""), "empty string"); +assert.throws(TypeError, () => resolvedOptions.call(Symbol()), "symbol"); +assert.throws(TypeError, () => resolvedOptions.call(1), "1"); +assert.throws(TypeError, () => resolvedOptions.call({}), "plain object"); +assert.throws(TypeError, () => resolvedOptions.call(Intl.RelativeTimeFormat), "Intl.RelativeTimeFormat"); +assert.throws(TypeError, () => resolvedOptions.call(Intl.RelativeTimeFormat.prototype), "Intl.RelativeTimeFormat.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/caching.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/caching.js new file mode 100644 index 0000000000..c00142c482 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/caching.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: sec-Intl.RelativeTimeFormat.prototype.resolvedOptions +description: Verifies that the return value of Intl.RelativeTimeFormat.prototype.resolvedOptions() is not cached. +info: | + Intl.RelativeTimeFormat.prototype.resolvedOptions () + + 4. Let options be ! ObjectCreate(%ObjectPrototype%). +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-us"); +const options1 = rtf.resolvedOptions(); +const options2 = rtf.resolvedOptions(); +assert.notSameValue(options1, options2, "Should create a new object each time."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..8c49fd2e98 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/length.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: sec-Intl.RelativeTimeFormat.prototype.resolvedOptions +description: Checks the "length" property of Intl.RelativeTimeFormat.prototype.resolvedOptions(). +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 RelativeTimeFormat 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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype.resolvedOptions, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..2305662ed6 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/name.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: sec-Intl.RelativeTimeFormat.prototype.resolvedOptions +description: Checks the "name" property of Intl.RelativeTimeFormat.prototype.resolvedOptions(). +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 }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype.resolvedOptions, "name", { + value: "resolvedOptions", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/order.js new file mode 100644 index 0000000000..c5f35fd396 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/order.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: sec-intl.relativetimeformat.prototype.resolvedoptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [compareArray.js] +features: [Intl.RelativeTimeFormat] +---*/ + +const options = new Intl.RelativeTimeFormat().resolvedOptions(); + +const expected = [ + "locale", + "style", + "numeric", + "numberingSystem", +]; + +assert.compareArray(Object.getOwnPropertyNames(options), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..cdb51d7ddd --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,30 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.resolvedOptions +description: Checks the "resolvedOptions" property of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype.resolvedOptions () + + 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. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue( + typeof Intl.RelativeTimeFormat.prototype.resolvedOptions, + "function", + "typeof Intl.RelativeTimeFormat.prototype.resolvedOptions is function" +); + +verifyProperty(Intl.RelativeTimeFormat.prototype, "resolvedOptions", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/type.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/type.js new file mode 100644 index 0000000000..4ad150eb48 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/resolvedOptions/type.js @@ -0,0 +1,42 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.RelativeTimeFormat.prototype.resolvedOptions +description: Checks the properties of the result of Intl.RelativeTimeFormat.prototype.resolvedOptions(). +info: | + Intl.RelativeTimeFormat.prototype.resolvedOptions () + + 4. Let options be ! ObjectCreate(%ObjectPrototype%). + 5. For each row of Table 1, except the header row, do + d. Perform ! CreateDataPropertyOrThrow(options, p, v). +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat] +---*/ + +const rtf = new Intl.RelativeTimeFormat("en-us", { "style": "short", "numeric": "auto" }); +const options = rtf.resolvedOptions(); +assert.sameValue(Object.getPrototypeOf(options), Object.prototype, "Prototype"); + +verifyProperty(options, "locale", { + value: "en-US", + writable: true, + enumerable: true, + configurable: true, +}); + +verifyProperty(options, "style", { + value: "short", + writable: true, + enumerable: true, + configurable: true, +}); + +verifyProperty(options, "numeric", { + value: "auto", + writable: true, + enumerable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/toString.js new file mode 100644 index 0000000000..100584e18c --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/toString.js @@ -0,0 +1,18 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.RelativeTimeFormat.prototype-@@tostringtag +description: > + Checks Object.prototype.toString with Intl.RelativeTimeFormat objects. +info: | + Intl.RelativeTimeFormat.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.RelativeTimeFormat". +features: [Intl.RelativeTimeFormat] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.RelativeTimeFormat.prototype), "[object Intl.RelativeTimeFormat]"); +assert.sameValue(Object.prototype.toString.call(new Intl.RelativeTimeFormat("en")), "[object Intl.RelativeTimeFormat]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/toStringTag.js new file mode 100644 index 0000000000..80398ba2d2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/prototype/toStringTag/toStringTag.js @@ -0,0 +1,25 @@ +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.RelativeTimeFormat.prototype-@@tostringtag +description: > + Checks the @@toStringTag property of the RelativeTimeFormat prototype object. +info: | + Intl.RelativeTimeFormat.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.RelativeTimeFormat". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.RelativeTimeFormat, Symbol.toStringTag] +---*/ + +verifyProperty(Intl.RelativeTimeFormat.prototype, Symbol.toStringTag, { + value: "Intl.RelativeTimeFormat", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/RelativeTimeFormat/shell.js b/js/src/tests/test262/intl402/RelativeTimeFormat/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/RelativeTimeFormat/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/browser.js b/js/src/tests/test262/intl402/Segmenter/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/browser.js b/js/src/tests/test262/intl402/Segmenter/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/browser.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/locales-invalid.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/locales-invalid.js new file mode 100644 index 0000000000..772e41ae59 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/locales-invalid.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks error cases for the locales argument to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 3. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). +includes: [testIntl.js] +features: [Intl.Segmenter] +---*/ + +for (const [locales, expectedError] of getInvalidLocaleArguments()) { + assert.throws(expectedError, function() { new Intl.Segmenter(locales) }) +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/locales-valid.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/locales-valid.js new file mode 100644 index 0000000000..55a9005624 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/locales-valid.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks various cases for the locales argument to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 3. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). +features: [Intl.Segmenter] +---*/ + +const defaultLocale = new Intl.Segmenter().resolvedOptions().locale; + +const tests = [ + [undefined, [defaultLocale], "undefined"], + ["EN", ["en"], "Single value"], + [[], [defaultLocale], "Empty array"], + [["sr"], ["sr"], "Single-element array"], + [["fr", "ar"], ["fr", "ar"], "Two-element array"], + [["xyz", "ar"], ["ar"], "Two-element array with unknown code"], + [["en", "EN"], ["en"], "Duplicate value (canonical first)"], + [["EN", "en"], ["en"], "Duplicate value (canonical last)"], + [{ 0: "DE", length: 0 }, [defaultLocale], "Object with zero length"], + [{ 0: "DE", length: 1 }, ["de"], "Object with length"], + [{ 0: "ja", 1: "fr" }, [defaultLocale], "Object without length, indexed from 0"], + [{ 1: "ja", 2: "fr" }, [defaultLocale], "Object without length, indexed from 1"], +]; + +const errorTests = [ + [["en-GB-oed"], "Grandfathered"], + [["x-private"], "Private", ["lookup"]], +]; + +for (const [locales, expected, name, matchers = ["best fit", "lookup"]] of tests) { + for (const localeMatcher of matchers) { + const segmenter = new Intl.Segmenter(locales, { localeMatcher }); + const actual = segmenter.resolvedOptions().locale; + assert(expected.includes(actual), `${name}: expected one of ${expected}, found ${actual}`); + } +} + +for (const [locales, name, matchers = ["best fit", "lookup"]] of errorTests) { + for (const localeMatcher of matchers) { + assert.throws(RangeError, function() { + new Intl.Segmenter(locales, { localeMatcher }); + }, name); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/newtarget-undefined.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/newtarget-undefined.js new file mode 100644 index 0000000000..e7db62bec9 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/newtarget-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Verifies the NewTarget check for Intl.Segmenter. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter, "function"); + +assert.throws(TypeError, function() { + Intl.Segmenter(); +}); + +assert.throws(TypeError, function() { + Intl.Segmenter("en"); +}); + +assert.throws(TypeError, function() { + Intl.Segmenter("not-valid-tag"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-abrupt-throws.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-abrupt-throws.js new file mode 100644 index 0000000000..f631a0eae5 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-abrupt-throws.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: Return abrupt completion from GetOption granularity +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 13. Let granularity be ? GetOption(options, "granularity", "string", « "grapheme", "word", "sentence" », "grapheme"). + + GetOption ( options, property, type, values, fallback ) + 1. Let value be ? Get(options, property). +features: [Intl.Segmenter] +---*/ + + +var options = {}; +Object.defineProperty(options, 'granularity', { + get() { throw new Test262Error(); }, +}); + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-invalid.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-invalid.js new file mode 100644 index 0000000000..9903767429 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-invalid.js @@ -0,0 +1,42 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of invalid value for the style option to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 13. Let granularity be ? GetOption(options, "granularity", "string", « "grapheme", "word", "sentence" », "grapheme"). + 14. Set segmenter.[[SegmenterGranularity]] to granularity. +features: [Intl.Segmenter] +---*/ + +const invalidOptions = [ + null, + 1, + "", + "standard", + "Grapheme", + "GRAPHEME", + "grapheme\0", + "Word", + "WORD", + "word\0", + "Sentence", + "SENTENCE", + "sentence\0", + "line", + "Line", + "LINE", + "line\0", +]; + +for (const granularity of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.Segmenter([], { granularity }); + }, `${granularity} is an invalid style option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-toString-abrupt-throws.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-toString-abrupt-throws.js new file mode 100644 index 0000000000..38b6d830a8 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-toString-abrupt-throws.js @@ -0,0 +1,59 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: Return abrupt completion from GetOption granularity + +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 13. Let granularity be ? GetOption(options, "granularity", "string", « "grapheme", "word", "sentence" », "grapheme"). + + GetOption ( options, property, type, values, fallback ) + 6. If type is "string", then + a. Let value be ? ToString(value). +features: [Intl.Segmenter, Symbol] +---*/ + +const options = { + granularity: { + toString() { + throw new Test262Error(); + } + } +}; + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}, 'from toString'); + +options.granularity = { + toString: undefined, + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}, 'from valueOf'); + +options.granularity = { + [Symbol.toPrimitive]() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}, 'from ToPrimitive'); + +options.granularity = Symbol(); + +assert.throws(TypeError, () => { + new Intl.Segmenter(undefined, options); +}, 'symbol value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-valid.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-valid.js new file mode 100644 index 0000000000..cd7732a92c --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-granularity-valid.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of valid values for the granularity option to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 11. Let granularity be ? GetOption(options, "granularity", "string", « "grapheme", "word", "sentence" », "grapheme"). + 12. Set segmenter.[[SegmenterGranularity]] to granularity. +features: [Intl.Segmenter] +---*/ + +const validOptions = [ + [undefined, "grapheme"], + ["grapheme", "grapheme"], + ["word", "word"], + ["sentence", "sentence"], + [{ toString() { return "word"; } }, "word"], +]; + +for (const [granularity, expected] of validOptions) { + const segmenter = new Intl.Segmenter([], { granularity }); + const resolvedOptions = segmenter.resolvedOptions(); + assert.sameValue(resolvedOptions.granularity, expected); +} + +assert.throws(RangeError, () => new Intl.Segmenter([], {granularity: "line"})); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-invalid.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-invalid.js new file mode 100644 index 0000000000..ca9632a861 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-invalid.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of a null options argument to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 5. Else + a. Let options be ? ToObject(options). +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter, "function"); + +assert.throws(TypeError, function() { new Intl.Segmenter([], null) }) + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-abrupt-throws.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-abrupt-throws.js new file mode 100644 index 0000000000..5a745742a3 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-abrupt-throws.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: > + Return abrupt completion from GetOption localeMatcher +info: | + Intl.Segmenter ([ locales [ , options ]]) + 1. If NewTarget is undefined, throw a TypeError exception. + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + GetOption ( options, property, type, values, fallback ) + 1. Let value be ? Get(options, property). + ... +features: [Intl.Segmenter] +---*/ + +var options = {}; +Object.defineProperty(options, 'localeMatcher', { + get() { throw new Test262Error(); }, +}); + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-invalid.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-invalid.js new file mode 100644 index 0000000000..72bfca89c4 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-invalid.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of invalid value for the localeMatcher option to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 7. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.Segmenter] +---*/ + +const invalidOptions = [ + null, + 1, + "", + "Lookup", + "LOOKUP", + "lookup\0", + "Best fit", + "BEST FIT", + "best\u00a0fit", +]; + +for (const localeMatcher of invalidOptions) { + assert.throws(RangeError, function() { + new Intl.Segmenter([], { localeMatcher }); + }, `${localeMatcher} is an invalid localeMatcher option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-toString-abrupt-throws.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-toString-abrupt-throws.js new file mode 100644 index 0000000000..edaea53201 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-toString-abrupt-throws.js @@ -0,0 +1,68 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: > + Return abrupt completion from GetOption localeMatcher +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 3. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%Segmenter.prototype%", internalSlotsList). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + + GetOption ( options, property, type, values, fallback ) + 6. If type is "string", then + a. Let value be ? ToString(value). + ... +features: [Intl.Segmenter, Symbol] +---*/ + +const options = { + localeMatcher: { + toString() { + throw new Test262Error(); + } + } +}; + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}, 'from toString'); + +options.localeMatcher = { + toString: undefined, + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}, 'from valueOf'); + +options.localeMatcher = { + [Symbol.toPrimitive]() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, () => { + new Intl.Segmenter(undefined, options); +}, 'from ToPrimitive'); + +options.localeMatcher = Symbol(); + +assert.throws(TypeError, () => { + new Intl.Segmenter(undefined, options); +}, 'symbol value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-valid.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-valid.js new file mode 100644 index 0000000000..b6b255a00a --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-localeMatcher-valid.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: > + Valid options for localeMatcher +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 3. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%Segmenter.prototype%", internalSlotsList). + ... + 8. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + ... + + GetOption ( options, property, type, values, fallback ) + + 1. Let value be ? Get(options, property). + ... +features: [Intl.Segmenter] +locale: [en] +---*/ + +// results for option values verified in the tests for resolvedOptions + +const localeMatchers = [ + undefined, + 'lookup', + 'best fit' +]; + +localeMatchers.forEach(localeMatcher => { + const obj = new Intl.Segmenter(undefined, { localeMatcher }); + + assert(obj instanceof Intl.Segmenter, `instanceof check - ${localeMatcher}`); + assert.sameValue(Object.getPrototypeOf(obj), Intl.Segmenter.prototype, `proto check - ${localeMatcher}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-null.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-null.js new file mode 100644 index 0000000000..f6cdd3ae2e --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-null.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.Segmenter +description: > + Throws TypeError if options is null +info: | + Intl.Segmenter ([ locales [ , options ]]) + 1. If NewTarget is undefined, throw a TypeError exception. + 3. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%Segmenter.prototype%", internalSlotsList). + ... + 4. If options is undefined, then + a. Let options be ObjectCreate(null). + 5. Else + a. Let options be ? ToObject(options). + ... +features: [Intl.Segmenter] +---*/ + +assert.throws(TypeError, () => { + new Intl.Segmenter(undefined, null); +}, 'null'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-order.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-order.js new file mode 100644 index 0000000000..d8f35af8c2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-order.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks the order of operations on the options argument to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 7. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). + 11. Let granularity be ? GetOption(options, "granularity", "string", « "grapheme", "word", "sentence" », "grapheme"). +includes: [compareArray.js] +features: [Intl.Segmenter] +---*/ + +const callOrder = []; + +new Intl.Segmenter([], { + get localeMatcher() { + callOrder.push("localeMatcher"); + return { + toString() { + callOrder.push("localeMatcher toString"); + return "best fit"; + } + }; + }, + get lineBreakStyle() { + callOrder.push("lineBreakStyle"); + return { + toString() { + callOrder.push("lineBreakStyle toString"); + return "strict"; + } + }; + }, + get granularity() { + callOrder.push("granularity"); + return { + toString() { + callOrder.push("granularity toString"); + return "word"; + } + }; + }, +}); + +assert.compareArray(callOrder, [ + "localeMatcher", + "localeMatcher toString", + "granularity", + "granularity toString", +]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-throwing-getters.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-throwing-getters.js new file mode 100644 index 0000000000..ccbb49749d --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-throwing-getters.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks the propagation of exceptions from the options for the Segmenter constructor. +features: [Intl.Segmenter] +---*/ + +function CustomError() {} + +const options = [ + "localeMatcher", + "granularity", +]; + +for (const option of options) { + assert.throws(CustomError, () => { + new Intl.Segmenter("en", { + get [option]() { + throw new CustomError(); + } + }); + }, `Exception from ${option} getter should be propagated`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-toobject-prototype.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-toobject-prototype.js new file mode 100644 index 0000000000..5adaaba383 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-toobject-prototype.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of non-object option arguments to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 5. Else + a. Let options be ? ToObject(options). +features: [Intl.Segmenter] +---*/ + +Object.defineProperties(Object.prototype, { + "granularity": { + value: "word", + }, +}) + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), + {}, +]; + +for (const options of optionsArguments) { + const segmenter = new Intl.Segmenter([], options); + const resolvedOptions = segmenter.resolvedOptions(); + assert.sameValue(resolvedOptions.granularity, "word", + `options argument ${String(options)} should yield the correct value for "granularity"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-toobject.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-toobject.js new file mode 100644 index 0000000000..915e7be717 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-toobject.js @@ -0,0 +1,33 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of non-object option arguments to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 5. Else + a. Let options be ? ToObject(options). +features: [Intl.Segmenter] +---*/ + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), + {}, +]; + +for (const options of optionsArguments) { + const segmenter = new Intl.Segmenter([], options); + const resolvedOptions = segmenter.resolvedOptions(); + assert.sameValue(resolvedOptions.granularity, "grapheme", + `options argument ${String(options)} should yield the correct value for "granularity"`); + assert.sameValue(resolvedOptions.lineBreakStyle, undefined, + `options argument ${String(options)} should yield the correct value for "lineBreakStyle"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-undefined.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-undefined.js new file mode 100644 index 0000000000..20a0a0452e --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-undefined.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of non-object option arguments to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 4. If options is undefined, then + a. Let options be ObjectCreate(null). +features: [Intl.Segmenter] +---*/ + +Object.defineProperties(Object.prototype, { + "localeMatcher": { + "get": function() { + throw new Error("Should not call getter on Object.prototype: localeMatcher"); + }, + }, + + "lineBreakStyle": { + "get": function() { + throw new Error("Should not call getter on Object.prototype: lineBreakStyle"); + }, + }, + + "granularity": { + "get": function() { + throw new Error("Should not call getter on Object.prototype: granularity"); + }, + }, +}); + +const optionsArguments = [ + [], + [[]], + [[], undefined], +]; + +for (const args of optionsArguments) { + const segmenter = new Intl.Segmenter(...args); + const resolvedOptions = segmenter.resolvedOptions(); + assert.sameValue(resolvedOptions.granularity, "grapheme", + `Calling with ${args.length} empty arguments should yield the correct value for "granularity"`); + assert.sameValue(Object.hasOwnProperty(resolvedOptions, "lineBreakStyle"), false, + `Calling with ${args.length} empty arguments should yield the correct value for "lineBreakStyle"`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-valid-combinations.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-valid-combinations.js new file mode 100644 index 0000000000..f2fa25f575 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/options-valid-combinations.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 the V8 project authors, Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks handling of valid values for the granularity option to the Segmenter constructor. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 11. Let granularity be ? GetOption(options, "granularity", "string", « "grapheme", "word", "sentence" », "grapheme"). + 12. Set segmenter.[[SegmenterGranularity]] to granularity. +features: [Intl.Segmenter] +---*/ + +const granularityOptions = ["grapheme", "word", "sentence"]; +const combinations = []; + +combinations.push([ + {}, + "grapheme", + undefined, +]); + +for (const granularity of granularityOptions) { + combinations.push([ + { granularity }, + granularity, + undefined, + ]); +} + +for (const [input, granularity, lineBreakStyle] of combinations) { + const segmenter = new Intl.Segmenter([], input); + const resolvedOptions = segmenter.resolvedOptions(); + assert.sameValue(resolvedOptions.granularity, granularity); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/proto-from-ctor-realm.js new file mode 100644 index 0000000000..32ecb723a0 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/proto-from-ctor-realm.js @@ -0,0 +1,61 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 1. If NewTarget is undefined, throw a TypeError exception. + 2. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%SegmenterPrototype%", « [[InitializedSegmenter]] »). + ... + 14. Return segmenter. + + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.Segmenter, cross-realm, Reflect, Symbol] +---*/ + +var other = $262.createRealm().global; +var newTarget = new other.Function(); +var seg; + +newTarget.prototype = undefined; +seg = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(seg), other.Intl.Segmenter.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +seg = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(seg), other.Intl.Segmenter.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = false; +seg = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(seg), other.Intl.Segmenter.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = 'str'; +seg = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(seg), other.Intl.Segmenter.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +seg = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(seg), other.Intl.Segmenter.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = 1; +seg = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(seg), other.Intl.Segmenter.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/shell.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/constructor/subclassing.js b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/subclassing.js new file mode 100644 index 0000000000..447c9953d0 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/constructor/subclassing.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks that Segmenter can be subclassed. +info: | + Intl.Segmenter ( [ locales [ , options ] ] ) + + 2. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%SegmenterPrototype%", « [[InitializedSegmenter]] »). +includes: [compareArray.js] +features: [Intl.Segmenter] +---*/ + +function segments(iterator) { + return [...iterator].map(result => result.segment); +} + +class CustomSegmenter extends Intl.Segmenter { + constructor(locales, options) { + super(locales, options); + this.isCustom = true; + } +} + +const locale = "de"; +const value = "Hello"; + +const real_segmenter = new Intl.Segmenter(locale); +assert.sameValue(real_segmenter.isCustom, undefined, "Custom property"); + +const custom_segmenter = new CustomSegmenter(locale); +assert.sameValue(custom_segmenter.isCustom, true, "Custom property"); + +assert.compareArray(segments(custom_segmenter.segment(value)), + segments(real_segmenter.segment(value)), + "Direct call"); + +assert.compareArray(segments(Intl.Segmenter.prototype.segment.call(custom_segmenter, value)), + segments(Intl.Segmenter.prototype.segment.call(real_segmenter, value)), + "Indirect call"); + +assert.sameValue(Object.getPrototypeOf(custom_segmenter), CustomSegmenter.prototype, "Prototype"); +assert.sameValue(Object.getPrototypeOf(CustomSegmenter), Intl.Segmenter, + "Object.getPrototypeOf(CustomSegmenter) returns Intl.Segmenter"); +assert.sameValue(Object.getPrototypeOf(CustomSegmenter.prototype), Intl.Segmenter.prototype, + "Object.getPrototypeOf(CustomSegmenter.prototype) returns Intl.Segmenter.prototype"); +assert.sameValue(custom_segmenter instanceof Intl.Segmenter, true, + "The result of `custom_segmenter instanceof Intl.Segmenter` is true"); + +assert.throws(TypeError, function() { + CustomSegmenter(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/length.js b/js/src/tests/test262/intl402/Segmenter/constructor/length.js new file mode 100644 index 0000000000..50e6a67e9e --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/length.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: > + Checks the "length" property of the Segmenter 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 Segmenter 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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/name.js b/js/src/tests/test262/intl402/Segmenter/constructor/name.js new file mode 100644 index 0000000000..b3c58e5658 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/name.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Checks the "name" property of the Segmenter 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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter, "name", { + value: "Segmenter", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/prop-desc.js b/js/src/tests/test262/intl402/Segmenter/constructor/prop-desc.js new file mode 100644 index 0000000000..4e0e80b668 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/prop-desc.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Verifies the "Segmenter" property of Intl. +info: | + Requirements for Standard Built-in ECMAScript Objects + + 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 2018 Language + Specification, 9th edition, clause 17, or successor. + + ECMAScript Standard Built-in Objects: + + 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. + +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter, "function"); + +verifyProperty(Intl, "Segmenter", { + value: Intl.Segmenter, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/prototype.js b/js/src/tests/test262/intl402/Segmenter/constructor/prototype.js new file mode 100644 index 0000000000..6ee85262cf --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/prototype.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: The prototype of the Intl.Segmenter constructor is %FunctionPrototype%. +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. + Unless otherwise specified every built-in function object has the %FunctionPrototype% object as the initial value of its [[Prototype]] internal slot. +features: [Intl.Segmenter] +---*/ + +assert.sameValue( + Object.getPrototypeOf(Intl.Segmenter), + Function.prototype, + "Object.getPrototypeOf(Intl.Segmenter) equals the value of Function.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/shell.js b/js/src/tests/test262/intl402/Segmenter/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/basic.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/basic.js new file mode 100644 index 0000000000..3cbe29059f --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/basic.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Tests that Intl.Segmenter has a supportedLocalesOf property, and it works as expected. +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "supportedLocalesOf should be supported."); + +const defaultLocale = new Intl.Segmenter().resolvedOptions().locale; +const notSupported = "zxx"; // "no linguistic content" +const requestedLocales = [defaultLocale, notSupported]; + +const supportedLocales = Intl.Segmenter.supportedLocalesOf(requestedLocales); +assert.sameValue(supportedLocales.length, 1, "The length of supported locales list is not 1."); +assert.sameValue(supportedLocales[0], defaultLocale, "The default locale is not returned in the supported list."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/branding.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/branding.js new file mode 100644 index 0000000000..d5b5ac00d9 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/branding.js @@ -0,0 +1,35 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: > + Verifies there's no branding check for Intl.Segmenter.supportedLocalesOf(). +info: | + Intl.Segmenter.supportedLocalesOf ( locales [, options ]) +features: [Intl.Segmenter] +---*/ + +const supportedLocalesOf = Intl.Segmenter.supportedLocalesOf; + +assert.sameValue(typeof supportedLocalesOf, "function"); + +const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + Intl.Segmenter, + Intl.Segmenter.prototype, +]; + +for (const thisValue of thisValues) { + const result = supportedLocalesOf.call(thisValue); + assert.sameValue(Array.isArray(result), true); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/browser.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/length.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/length.js new file mode 100644 index 0000000000..8fc7443613 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/length.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: > + Checks the "length" property of Intl.Segmenter.supportedLocalesOf(). +info: | + The value of the length property of the supportedLocalesOf method is 1. + 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, has a length property whose value is an integer. + Unless otherwise specified, the length property of a built-in function object has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter.supportedLocalesOf, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-empty.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-empty.js new file mode 100644 index 0000000000..07c91b85aa --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-empty.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 the V8 project authors, Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Checks handling of an empty locales argument to the supportedLocalesOf function. +info: | + Intl.Segmenter.supportedLocalesOf ( locales [, options ]) + + 3. Return ? SupportedLocales(availableLocales, requestedLocales, options). +includes: [compareArray.js] +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "Should support Intl.Segmenter.supportedLocalesOf."); + +assert.compareArray(Intl.Segmenter.supportedLocalesOf(), []); +assert.compareArray(Intl.Segmenter.supportedLocalesOf([]), []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-invalid.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-invalid.js new file mode 100644 index 0000000000..0524a4ee92 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-invalid.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Checks error cases for the locales argument to the supportedLocalesOf function. +info: | + Intl.Segmenter.supportedLocalesOf ( locales [, options ]) + + 2. Let requestedLocales be CanonicalizeLocaleList(locales). +includes: [testIntl.js] +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "Should support Intl.Segmenter.supportedLocalesOf."); + +for (const [locales, expectedError] of getInvalidLocaleArguments()) { + assert.throws(expectedError, () => Intl.Segmenter.supportedLocalesOf(locales)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-specific.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-specific.js new file mode 100644 index 0000000000..76ecdd9b9d --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/locales-specific.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 the V8 project authors, Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Checks handling of specific locales arguments to the supportedLocalesOf function. +info: | + Intl.Segmenter.supportedLocalesOf ( locales [, options ]) + + 3. Return ? SupportedLocales(availableLocales, requestedLocales, options). +includes: [compareArray.js] +locale: [sr, sr-Thai-RS, de, zh-CN] +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "Should support Intl.Segmenter.supportedLocalesOf."); + +assert.compareArray(Intl.Segmenter.supportedLocalesOf("sr"), ["sr"]); + +const multiLocale = ["sr-Thai-RS", "de", "zh-CN"]; +assert.compareArray(Intl.Segmenter.supportedLocalesOf(multiLocale), multiLocale); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/name.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/name.js new file mode 100644 index 0000000000..8874465ed9 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/name.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: > + Checks the "name" property of Intl.Segmenter.supportedLocalesOf(). +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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter.supportedLocalesOf, "name", { + value: "supportedLocalesOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-localeMatcher-invalid.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-localeMatcher-invalid.js new file mode 100644 index 0000000000..3ca3be44cb --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-localeMatcher-invalid.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Checks handling of invalid values for the localeMatcher option to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + b. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "Should support Intl.Segmenter.supportedLocalesOf."); + +const invalidOptions = [ + null, + 1, + "", + "Lookup", + "LOOKUP", + "lookup\0", + "Best fit", + "BEST FIT", + "best\u00a0fit", +]; + +for (const invalidOption of invalidOptions) { + assert.throws(RangeError, function() { + Intl.Segmenter.supportedLocalesOf([], {"localeMatcher": invalidOption}); + }, `${invalidOption} is an invalid localeMatcher option value`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-null.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-null.js new file mode 100644 index 0000000000..6c851e1a21 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-null.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Checks handling of a null options argument to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + a. Let options be ? ToObject(options). +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "Should support Intl.Segmenter.supportedLocalesOf."); + +assert.throws(TypeError, function() { + Intl.Segmenter.supportedLocalesOf([], null); +}, "Should throw when passing null as the options argument"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-toobject.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-toobject.js new file mode 100644 index 0000000000..54de8da435 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-toobject.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Checks handling of non-object options arguments to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + a. Let options be ? ToObject(options). +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "Should support Intl.Segmenter.supportedLocalesOf."); + +let called; +Object.defineProperties(Object.prototype, { + "localeMatcher": { + get() { + ++called; + return "best fit"; + } + } +}); + +const optionsArguments = [ + true, + "test", + 7, + Symbol(), +]; + +for (const options of optionsArguments) { + called = 0; + const result = Intl.Segmenter.supportedLocalesOf([], options); + assert.sameValue(Array.isArray(result), true, `Expected array from ${String(options)}`); + assert.sameValue(called, 1, `Expected one call from ${String(options)}`); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-undefined.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-undefined.js new file mode 100644 index 0000000000..9d1c146cd4 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/options-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Checks handling of an undefined options argument to the supportedLocalesOf function. +info: | + SupportedLocales ( availableLocales, requestedLocales, options ) + + 1. If options is not undefined, then + b. Let matcher be ? GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit"). +features: [Intl.Segmenter] +---*/ + +assert.sameValue(typeof Intl.Segmenter.supportedLocalesOf, "function", + "Should support Intl.Segmenter.supportedLocalesOf."); + +Object.defineProperties(Object.prototype, { + "localeMatcher": { + get() { throw new Error("Should not call localeMatcher getter"); } + } +}); + +assert.sameValue(Array.isArray(Intl.Segmenter.supportedLocalesOf()), true, "No arguments"); +assert.sameValue(Array.isArray(Intl.Segmenter.supportedLocalesOf([])), true, "One argument"); +assert.sameValue(Array.isArray(Intl.Segmenter.supportedLocalesOf([], undefined)), true, "Two arguments"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/prop-desc.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/prop-desc.js new file mode 100644 index 0000000000..734c1deeb0 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/prop-desc.js @@ -0,0 +1,32 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: > + Checks the "supportedLocalesOf" property of the Segmenter prototype object. +info: | + Intl.Segmenter.supportedLocalesOf ( locales [, options ]) + + 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. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +assert.sameValue( + typeof Intl.Segmenter.supportedLocalesOf, + "function", + "typeof Intl.Segmenter.supportedLocalesOf is function" +); + +verifyProperty(Intl.Segmenter, "supportedLocalesOf", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/result-type.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/result-type.js new file mode 100644 index 0000000000..1bb3c5e631 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/result-type.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.supportedLocalesOf +description: Verifies the type of the return value of Intl.Segmenter.supportedLocalesOf(). +info: | + Intl.Segmenter.supportedLocalesOf ( locales [, options ]) +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +const result = Intl.Segmenter.supportedLocalesOf("en"); +assert.sameValue(Array.isArray(result), true, + "Array.isArray() should return true"); +assert.sameValue(Object.getPrototypeOf(result), Array.prototype, + "The prototype should be Array.prototype"); +assert.sameValue(Object.isExtensible(result), true, + "Object.isExtensible() should return true"); + +assert.notSameValue(result.length, 0); +for (let i = 0; i < result.length; ++i) { + verifyProperty(result, String(i), { + "writable": true, + "enumerable": true, + "configurable": true, + }); +} + +verifyProperty(result, "length", { + "enumerable": false, + "configurable": false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/shell.js b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/constructor/supportedLocalesOf/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/ctor-custom-get-prototype-poison-throws.js b/js/src/tests/test262/intl402/Segmenter/ctor-custom-get-prototype-poison-throws.js new file mode 100644 index 0000000000..d1e0b4264a --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/ctor-custom-get-prototype-poison-throws.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: > + Return abrupt from Get Prototype from a custom NewTarget +info: | + Intl.Segmenter ([ locales [ , options ]]) + 1. If NewTarget is undefined, throw a TypeError exception. + 3. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%Segmenter.prototype%", internalSlotsList). + ... + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + ... + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + 3. Let proto be ? Get(constructor, "prototype"). +features: [Intl.Segmenter, Reflect, Proxy] +---*/ + +const custom = new Proxy(new Function(), { + get(target, key) { + if (key === 'prototype') { + throw new Test262Error(); + } + + return target[key]; + } +}); + +assert.throws(Test262Error, () => { + Reflect.construct(Intl.Segmenter, [], custom); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/ctor-custom-prototype.js b/js/src/tests/test262/intl402/Segmenter/ctor-custom-prototype.js new file mode 100644 index 0000000000..3d0cd09888 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/ctor-custom-prototype.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: > + Custom Prototype of the returned object based on the NewTarget +info: | + Intl.Segmenter ([ locales [ , options ]]) + 1. If NewTarget is undefined, throw a TypeError exception. + 3. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%Segmenter.prototype%", internalSlotsList). + ... + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + ... + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + 3. Let proto be ? Get(constructor, "prototype"). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [Intl.Segmenter, Reflect] +---*/ + +var custom = new Function(); +custom.prototype = {}; + +const obj = Reflect.construct(Intl.Segmenter, [], custom); + +assert.sameValue(Object.getPrototypeOf(obj), custom.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/ctor-default-prototype.js b/js/src/tests/test262/intl402/Segmenter/ctor-default-prototype.js new file mode 100644 index 0000000000..dd9b758b44 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/ctor-default-prototype.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: > + Prototype of the returned object is Segmenter.prototype +info: | + Intl.Segmenter ([ locales [ , options ]]) + 1. If NewTarget is undefined, throw a TypeError exception. + 3. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%Segmenter.prototype%", internalSlotsList). +features: [Intl.Segmenter] +---*/ + +var obj = new Intl.Segmenter(); + +assert.sameValue(Object.getPrototypeOf(obj), Intl.Segmenter.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/instance/browser.js b/js/src/tests/test262/intl402/Segmenter/instance/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/instance/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/instance/extensibility.js b/js/src/tests/test262/intl402/Segmenter/instance/extensibility.js new file mode 100644 index 0000000000..7a59993a60 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/instance/extensibility.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Intl.Segmenter instance object extensibility +info: | + 17 ECMAScript Standard Built-in Objects: + + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Intl.Segmenter] +---*/ + +assert.sameValue( + Object.isExtensible(new Intl.Segmenter()), + true, + "Object.isExtensible(new Intl.Segmenter()) returns true" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/instance/prototype.js b/js/src/tests/test262/intl402/Segmenter/instance/prototype.js new file mode 100644 index 0000000000..8feefa5299 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/instance/prototype.js @@ -0,0 +1,22 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter +description: Intl.Segmenter instance object is created from %SegmenterPrototype%. +info: | + Intl.Segmenter ([ locales [ , options ]]) + + 2. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%SegmenterPrototype%", « [[InitializedSegmenter]] »). +features: [Intl.Segmenter] +---*/ + +const value = new Intl.Segmenter(); +assert.sameValue( + Object.getPrototypeOf(value), + Intl.Segmenter.prototype, + "Object.getPrototypeOf(value) equals the value of Intl.Segmenter.prototype" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/instance/shell.js b/js/src/tests/test262/intl402/Segmenter/instance/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/instance/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/proto-from-ctor-realm.js b/js/src/tests/test262/intl402/Segmenter/proto-from-ctor-realm.js new file mode 100644 index 0000000000..181a28c6cd --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/proto-from-ctor-realm.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter +description: Default [[Prototype]] value derived from realm of the NewTarget. +info: | + Intl.Segmenter ([ locales [ , options ]]) + 1. If NewTarget is undefined, throw a TypeError exception. + 3. Let segmenter be ? OrdinaryCreateFromConstructor(NewTarget, "%Segmenter.prototype%", internalSlotsList). + ... + 15. Return segmenter. + OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ) + ... + 2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto). + 3. Return ObjectCreate(proto, internalSlotsList). + GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto ) + ... + 3. Let proto be ? Get(constructor, 'prototype'). + 4. If Type(proto) is not Object, then + a. Let realm be ? GetFunctionRealm(constructor). + b. Set proto to realm's intrinsic object named intrinsicDefaultProto. + 5. Return proto. +features: [cross-realm, Reflect, Symbol, Intl.Segmenter] +---*/ + +const other = $262.createRealm().global; +const newTarget = new other.Function(); +let sgm; + +newTarget.prototype = undefined; +sgm = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(sgm), other.Intl.Segmenter.prototype, 'newTarget.prototype is undefined'); + +newTarget.prototype = null; +sgm = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(sgm), other.Intl.Segmenter.prototype, 'newTarget.prototype is null'); + +newTarget.prototype = false; +sgm = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(sgm), other.Intl.Segmenter.prototype, 'newTarget.prototype is a Boolean'); + +newTarget.prototype = 'str'; +sgm = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(sgm), other.Intl.Segmenter.prototype, 'newTarget.prototype is a String'); + +newTarget.prototype = Symbol(); +sgm = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(sgm), other.Intl.Segmenter.prototype, 'newTarget.prototype is a Symbol'); + +newTarget.prototype = 1; +sgm = Reflect.construct(Intl.Segmenter, [], newTarget); +assert.sameValue(Object.getPrototypeOf(sgm), other.Intl.Segmenter.prototype, 'newTarget.prototype is a Number'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/Symbol.toStringTag.js b/js/src/tests/test262/intl402/Segmenter/prototype/Symbol.toStringTag.js new file mode 100644 index 0000000000..e69d8a041f --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/Symbol.toStringTag.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.segmenter.prototype-@@tostringtag +description: > + Property descriptor of Segmenter.prototype[@@toStringTag] +info: | + The initial value of the @@toStringTag property is the string value "Intl.Segmenter". + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Segmenter, Symbol.toStringTag] +---*/ + +verifyProperty(Intl.Segmenter.prototype, Symbol.toStringTag, { + value: "Intl.Segmenter", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/browser.js b/js/src/tests/test262/intl402/Segmenter/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/constructor/browser.js b/js/src/tests/test262/intl402/Segmenter/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/constructor/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/constructor/prop-desc.js b/js/src/tests/test262/intl402/Segmenter/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..4ce1dbdefb --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/constructor/prop-desc.js @@ -0,0 +1,27 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.constructor +description: Checks the "constructor" property of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.constructor + + The initial value of Intl.Segmenter.prototype.constructor is %Segmenter%. + + 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. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter.prototype, "constructor", { + value: Intl.Segmenter, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/constructor/shell.js b/js/src/tests/test262/intl402/Segmenter/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/constructor/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/prop-desc.js b/js/src/tests/test262/intl402/Segmenter/prototype/prop-desc.js new file mode 100644 index 0000000000..349184aef3 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype +description: Checks the "prototype" property of the Segmenter constructor. +info: | + Intl.Segmenter.prototype + + The value of Intl.Segmenter.prototype is %SegmenterPrototype%. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/branding.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/branding.js new file mode 100644 index 0000000000..8393838ec9 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/branding.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.resolvedOptions +description: Verifies the branding check for the "resolvedOptions" function of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.resolvedOptions () + + 2. If Type(pr) is not Object or pr does not have an [[InitializedSegmenter]] internal slot, throw a TypeError exception. +features: [Intl.Segmenter] +---*/ + +const resolvedOptions = Intl.Segmenter.prototype.resolvedOptions; + +assert.sameValue(typeof resolvedOptions, "function"); + +assert.throws(TypeError, () => resolvedOptions.call(undefined), "undefined"); +assert.throws(TypeError, () => resolvedOptions.call(null), "null"); +assert.throws(TypeError, () => resolvedOptions.call(true), "true"); +assert.throws(TypeError, () => resolvedOptions.call(""), "empty string"); +assert.throws(TypeError, () => resolvedOptions.call(Symbol()), "symbol"); +assert.throws(TypeError, () => resolvedOptions.call(1), "1"); +assert.throws(TypeError, () => resolvedOptions.call({}), "plain object"); +assert.throws(TypeError, () => resolvedOptions.call(Intl.Segmenter), "Intl.Segmenter"); +assert.throws(TypeError, () => resolvedOptions.call(Intl.Segmenter.prototype), "Intl.Segmenter.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/browser.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/caching.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/caching.js new file mode 100644 index 0000000000..1dca8c00e9 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/caching.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.resolvedOptions +description: Verifies that the return value of Intl.Segmenter.prototype.resolvedOptions() is not cached. +info: | + Intl.Segmenter.prototype.resolvedOptions () + + 3. Let options be ! ObjectCreate(%ObjectPrototype%). +features: [Intl.Segmenter] +---*/ + +const s = new Intl.Segmenter("en-us"); +const options1 = s.resolvedOptions(); +const options2 = s.resolvedOptions(); +assert.notSameValue(options1, options2, "Should create a new object each time."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/length.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/length.js new file mode 100644 index 0000000000..99646b36bc --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/length.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.resolvedOptions +description: Checks the "length" property of Intl.Segmenter.prototype.resolvedOptions(). +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 Segmenter 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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter.prototype.resolvedOptions, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/name.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/name.js new file mode 100644 index 0000000000..eba2a52a3f --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/name.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.resolvedOptions +description: Checks the "name" property of Intl.Segmenter.prototype.resolvedOptions(). +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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter.prototype.resolvedOptions, "name", { + value: "resolvedOptions", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/order.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/order.js new file mode 100644 index 0000000000..8da78e8f2f --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/order.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.resolvedOptions +description: Verifies the property order for the object returned by resolvedOptions(). +includes: [compareArray.js] +features: [Intl.Segmenter] +---*/ + +const options = new Intl.Segmenter([], { + "granularity": "word", +}).resolvedOptions(); + +const expected = [ + "locale", + "granularity", +]; + +assert.compareArray(Object.getOwnPropertyNames(options), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/prop-desc.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/prop-desc.js new file mode 100644 index 0000000000..6bbecd0ebe --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/prop-desc.js @@ -0,0 +1,30 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.resolvedOptions +description: Checks the "resolvedOptions" property of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.resolvedOptions () + + 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. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +assert.sameValue( + typeof Intl.Segmenter.prototype.resolvedOptions, + "function", + "typeof Intl.Segmenter.prototype.resolvedOptions is function" +); + +verifyProperty(Intl.Segmenter.prototype, "resolvedOptions", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/shell.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/type-without-lbs.js b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/type-without-lbs.js new file mode 100644 index 0000000000..76c1cb4df8 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/resolvedOptions/type-without-lbs.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.resolvedOptions +description: Checks the properties of the result of Intl.Segmenter.prototype.resolvedOptions(). +info: | + Intl.Segmenter.prototype.resolvedOptions () + + 3. Let options be ! ObjectCreate(%ObjectPrototype%). + 4. For each row of Table 1, except the header row, do + c. If v is not undefined, then + i. Perform ! CreateDataPropertyOrThrow(options, p, v). +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +const rtf = new Intl.Segmenter("en-us", { "lineBreakStyle": "loose", "granularity": "word" }); +const options = rtf.resolvedOptions(); +assert.sameValue(Object.getPrototypeOf(options), Object.prototype, "Prototype"); + +verifyProperty(options, "locale", { + value: "en-US", + writable: true, + enumerable: true, + configurable: true, +}); + +verifyProperty(options, "granularity", { + value: "word", + writable: true, + enumerable: true, + configurable: true, +}); + +verifyProperty(options, "lineBreakStyle", undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/branding.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/branding.js new file mode 100644 index 0000000000..35d1b79ab7 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/branding.js @@ -0,0 +1,29 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Verifies the branding check for the "segment" function of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.segment( string ) + + 2. If Type(segment) is not Object or segment does not have an [[InitializedSegmenter]] internal slot, throw a TypeError exception. +features: [Intl.Segmenter] +---*/ + +const segment = Intl.Segmenter.prototype.segment; + +assert.sameValue(typeof segment, "function"); + +assert.throws(TypeError, () => segment.call(undefined), "undefined"); +assert.throws(TypeError, () => segment.call(null), "null"); +assert.throws(TypeError, () => segment.call(true), "true"); +assert.throws(TypeError, () => segment.call(""), "empty string"); +assert.throws(TypeError, () => segment.call(Symbol()), "symbol"); +assert.throws(TypeError, () => segment.call(1), "1"); +assert.throws(TypeError, () => segment.call({}), "plain object"); +assert.throws(TypeError, () => segment.call(Intl.Segmenter), "Intl.Segmenter"); +assert.throws(TypeError, () => segment.call(Intl.Segmenter.prototype), "Intl.Segmenter.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/browser.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/branding.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/branding.js new file mode 100644 index 0000000000..95ef58674f --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/branding.js @@ -0,0 +1,28 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the branding check for the "segment" function of the %Segments.prototype%.containing. +info: | + %Segments.prototype%.containing ( index ) + 1. Let segments be the this value. + 2. Perform ? RequireInternalSlot(segments, [[SegmentsSegmenter]]). + +features: [Intl.Segmenter] +---*/ +const segment = (new Intl.Segmenter()).segment("123"); +const containing = segment.containing; +assert.sameValue(typeof containing, "function"); +assert.throws(TypeError, () => containing.call(undefined), "undefined"); +assert.throws(TypeError, () => containing.call(null), "null"); +assert.throws(TypeError, () => containing.call(true), "true"); +assert.throws(TypeError, () => containing.call(""), "empty string"); +assert.throws(TypeError, () => containing.call(Symbol()), "symbol"); +assert.throws(TypeError, () => containing.call(1), "1"); +assert.throws(TypeError, () => containing.call({}), "plain object"); +assert.throws(TypeError, () => containing.call(Intl.Segmenter), "Intl.Segmenter"); +assert.throws(TypeError, () => containing.call(Intl.Segmenter.prototype), "Intl.Segmenter.prototype"); +assert.sameValue(undefined, containing.call(segment, -1)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/breakable-input.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/breakable-input.js new file mode 100644 index 0000000000..1029a59373 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/breakable-input.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the cases which the input is breakable. +info: | + %Segments.prototype%.containing ( index ) + + 8. Let startIndex be ! FindBoundary(segmenter, string, n, before). + 9. Let endIndex be ! FindBoundary(segmenter, string, n, after). + +features: [Intl.Segmenter] +---*/ + +// The inputs are breakable for "grapheme" and "word" but not for "sentence" +const granularities = [undefined, "grapheme", "word"]; +// The following all contains more than one segments in either "grapheme" or "word" +// granularity. +const inputs = [ + "123 ", + "a ", + " a", + " \ud800\udc00", // SPACE + surrogate + "\ud800\udc00 ", // surrogate + SPACE + "\udc00\ud800", // incorrect surrogate- tail + leading + "\ud800 ", // only leading surrogate + SPACE + "\udc00 ", // only trailing surrogate + SPACE + " \ud800", // SPACE + only leading surrogate + " \udc00", // SPACE + only trailing surrogate + " 台", // SPACE + a Han character + "台 ", // a Han character + SPACE + "\u0301 ", // a modifier + SPACE +]; + +granularities.forEach( + function(granularity) { + const segmenter = new Intl.Segmenter(undefined, {granularity}); + inputs.forEach(function(input) { + const segment = segmenter.segment(input); + let msg = `granularity: ${granularity} input: ${input}`; + const first = segment.containing(0); + assert.sameValue(0, first.index, `${msg} containing(0) index`); + assert.sameValue(input, first.input, `${msg} containing(0) input`); + assert.sameValue(false, first.segment == input, + `${msg} containing(0) segment`); + const last = segment.containing(input.length - 1); + msg += ` containing(${input.length - 1}) ` + assert.sameValue(true, last.index > 0, `${msg} index > 0`); + assert.sameValue(true, last.index < input.length, `${msg} index`); + assert.sameValue(input, last.input, `${msg} input`); + assert.sameValue(false, last.segment == input, `${msg} segment`); + }); + }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/browser.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/index-throws.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/index-throws.js new file mode 100644 index 0000000000..4d399c71ae --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/index-throws.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the cases which the value of index which throws. +info: | + %Segments.prototype%.containing ( index ) + + 6. Let n be ? ToInteger(index). + 7. If n < 0 or n ≥ len, return undefined. + 8. Let startIndex be ! FindBoundary(segmenter, string, n, before). + + ToInteger ( argument ) + 1. Let number be ? ToNumber(argument). + + ToNumber ( argument ) + Symbol | Throw a TypeError exception. + BigInt | Throw a TypeError exception. + +features: [Intl.Segmenter] +---*/ + +const input = "a b c"; +const granularities = [undefined, "grapheme", "word", "sentence"]; +const index_throws = [ + // Symbol + Symbol(), + // BigInt + 0n, + -1n, + 1n, + BigInt(0), + BigInt(1), + BigInt(-1), + BigInt(input.length), +]; + +granularities.forEach( + function(granularity) { + const segmenter = new Intl.Segmenter(undefined, {granularity}); + const segment = segmenter.segment(input); + index_throws.forEach(function(index) { + assert.throws(TypeError, () => {segment.containing(index);}) + }); + }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/iswordlike.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/iswordlike.js new file mode 100644 index 0000000000..9f3b240b0e --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/iswordlike.js @@ -0,0 +1,57 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the isWordLike in the result when granularity is not "word". +info: | + %Segments.prototype%.containing ( index ) + + 10. Return ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex). + + CreateSegmentDataObject ( segmenter, string, startIndex, endIndex ) + 11. If granularity is "word", then + a. Let isWordLike be a Boolean value indicating whether the segment in string is "word-like" according to locale segmenter.[[Locale]]. + b. Perform ! CreateDataPropertyOrThrow(result, "isWordLike", isWordLike). + +features: [Intl.Segmenter] +---*/ + +const other_granularities = [undefined, "grapheme", "sentence"]; +// Some text +const inputs = [ + "Hello world!", // English + "Jedovatou mambu objevila žena v zahrádkářské kolonii.", // Czech + "Việt Nam: Nhất thể hóa sẽ khác Trung Quốc?", // Vietnamese + "Σοβαρές ενστάσεις Κομισιόν για τον προϋπολογισμό της Ιταλίας", // Greek + "Решение Индии о покупке российских С-400 расценили как вызов США", // Russian + "הרופא שהציל נשים והנערה ששועבדה ע", // Hebrew, + "ترامب للملك سلمان: أنا جاد للغاية.. عليك دفع المزيد", // Arabic + "भारत की एस 400 मिसाइल के मुकाबले पाक की थाड, जानें कौन कितना ताकतवर", // Hindi + "ரெட் அலர்ட் எச்சரிக்கை; புதுச்சேரியில் நாளை அரசு விடுமுறை!", // Tamil + "'ఉత్తర్వులు అందే వరకు ఓటర్ల తుది జాబితాను వెబ్సైట్లో పెట్టవద్దు'", // Telugu + "台北》抹黑柯P失敗?朱學恒酸:姚文智氣pupu嗆大老闆", // Chinese + "วัดไทรตีระฆังเบาลงช่วงเข้าพรรษา เจ้าอาวาสเผยคนร้องเรียนรับผลกรรมแล้ว", // Thai + "九州北部の一部が暴風域に入りました(日直予報士 2018年10月06日) - 日本気象協会 tenki.jp", // Japanese + "법원 “다스 지분 처분권·수익권 모두 MB가 보유”", // Korean +]; + +other_granularities.forEach( + function(granularity) { + const segmenter = new Intl.Segmenter(undefined, {granularity}); + inputs.forEach(function(input) { + const segment = segmenter.segment(input); + for (let index = 0; index < input.length; index++) { + const result = segment.containing(index); + const msg = + `granularity: ${granularity} input: ${input} containing(${index})`; + assert.sameValue(true, result.index >= 0, `${msg} index >= 0`); + assert.sameValue(true, result.index < input.length, `${msg} index`); + assert.sameValue("string", typeof result.input, `${msg} input`); + assert.sameValue(undefined, result.isWordLike, + `${msg} isWordLike should be undefined`); + } + }); + }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/length.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/length.js new file mode 100644 index 0000000000..f9ffd00590 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/length.js @@ -0,0 +1,25 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%segmentsprototype%.containing +description: Checks the "length" property of %Segments.prototype%.containing() +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 Segmenter 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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +const segment = (new Intl.Segmenter()).segment(""); +verifyProperty(segment.containing, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/name.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/name.js new file mode 100644 index 0000000000..5a8139ec32 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/name.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Checks the "name" property of %Segments.prototype%.containing ( index ) +info: | + %Segments.prototype%.containing ( index ) + 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 2020 Language Specification, 11th 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 }. + +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ +const segment = (new Intl.Segmenter()).segment(""); +verifyProperty(segment.containing, "name", { + value: "containing", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/one-index.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/one-index.js new file mode 100644 index 0000000000..41f1cdbbd9 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/one-index.js @@ -0,0 +1,67 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the cases which the value of index turn into 1. +info: | + %Segments.prototype%.containing ( index ) + + 6. Let n be ? ToInteger(index). + 7. If n < 0 or n ≥ len, return undefined. + 8. Let startIndex be ! FindBoundary(segmenter, string, n, before). + + ToInteger ( argument ) + 1. Let number be ? ToNumber(argument). + 2. If number is NaN, +0, or -0, return +0. + 4. Let integer be the Number value that is the same sign as number and whose magnitude is floor(abs(number)). + 5. If integer is -0, return +0. + 6. Return integer. + + ToNumber ( argument ) + Undefined | Return NaN. + Null | Return +0. + Boolean | If argument is true, return 1. If argument is false, return +0. + +features: [Intl.Segmenter] +---*/ + +const input = "a c"; +const granularities = [undefined, "grapheme", "word"]; +const index_to_one = [ + 1, + 1.49, + 14.9E-1, + 14.9e-1, + "1.49", + "14.9E-1", + "14.9e-1", + true, +]; + +// Except granularity: "sentence", check the result.segment is " ". +granularities.forEach( + function(granularity) { + const segmenter = new Intl.Segmenter(undefined, {granularity}); + const segment = segmenter.segment(input); + index_to_one.forEach(function(index) { + const result = segment.containing(index); + const msg = "granularity: " + granularity + " index: " + index; + assert.sameValue(1, result.index, msg + " index"); + assert.sameValue(" ", result.segment, msg + " segment"); + assert.sameValue(input, result.input, msg + " input"); + }); + }); + +// For granularity: "sentence", result.segment is input +const segmenter = new Intl.Segmenter(undefined, {granularity: "sentence"}); +const segment = segmenter.segment(input); +index_to_one.forEach(function(index) { + const result = segment.containing(index); + const msg = "granularity: sentence index: " + index; + assert.sameValue(0, result.index, msg + " index"); + assert.sameValue(input, result.segment, msg + " segment"); + assert.sameValue(input, result.input, msg + " input"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/out-of-bound-index.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/out-of-bound-index.js new file mode 100644 index 0000000000..755dd8fd8e --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/out-of-bound-index.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the cases which the value of index turn into out of bound. +info: | + %Segments.prototype%.containing ( index ) + + 6. Let n be ? ToInteger(index). + 7. If n < 0 or n ≥ len, return undefined. + 8. Let startIndex be ! FindBoundary(segmenter, string, n, before). + + ToInteger ( argument ) + 1. Let number be ? ToNumber(argument). + 2. If number is NaN, +0, or -0, return +0. + 4. Let integer be the Number value that is the same sign as number and whose magnitude is floor(abs(number)). + 5. If integer is -0, return +0. + 6. Return integer. + + ToNumber ( argument ) + String | See grammar and conversion algorithm below. + +features: [Intl.Segmenter] +---*/ + +const input = "a b c"; +const granularities = [undefined, "grapheme", "word", "sentence"]; +const index_to_out_of_bound = [ + input.length, + input.length + 0.1, + -1, + -2, + "-1", + "-2", + "-1.1", + Infinity, + -Infinity, + "Infinity", + "-Infinity", +]; + +granularities.forEach( + function(granularity) { + const segmenter = new Intl.Segmenter(undefined, {granularity}); + const segment = segmenter.segment(input); + index_to_out_of_bound.forEach(function(index) { + const result = segment.containing(index); + assert.sameValue(undefined, result); + }); + }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/prop-desc.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/prop-desc.js new file mode 100644 index 0000000000..7fd3e1c807 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%segmentsprototype%.containing +description: Checks the "containing" property of the %Segments.prototype% object. +info: | + %Segments.prototype%.containing ( index ) + + 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. + +features: [Intl.Segmenter] +---*/ + +const segment = (new Intl.Segmenter()).segment(""); +assert.sameValue( + typeof segment.containing, + "function", + "typeof %Segments.prototype%.containing is function" +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/shell.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/unbreakable-input.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/unbreakable-input.js new file mode 100644 index 0000000000..965cce0740 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/unbreakable-input.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the cases which the input is unbreakable. +info: | + %Segments.prototype%.containing ( index ) + + 8. Let startIndex be ! FindBoundary(segmenter, string, n, before). + 9. Let endIndex be ! FindBoundary(segmenter, string, n, after). + +features: [Intl.Segmenter] +---*/ + +const granularities = [undefined, "grapheme", "word", "sentence"]; +// The following all contains only one segment in any granularity. +const inputs = [ + "a", + " ", + "\ud800\udc00", // surrogate + "\ud800", // only leading surrogate + "\udc00", // only trailing surrogate + "台", // a Han character + "\u0301", // a modifier + "a\u0301", // ASCII + a modifier + "ซิ่", // a Thai cluster + "𐂰", // a Surrogate pair + "\uD83D\uDC4B\uD83C\uDFFB", // Emoji short sequence: waving_hand_light_skin_tone + "\uD83D\uDC68\uD83C\uDFFB\u200D\uD83E\uDDB0", // Emoji long sequence: man_light_skin_tone_red_hair + "\u1102", // Jamo L + "\u1162", // Jamo V + "\u11A9", // Jamo T + "\u1102\u1162", // Jamo LV + "\u1102\u1162\u11A9", // Jamo LVT + "\u1102\u1102", // Jamo L L + "\u1102\u1102\u1162", // Jamo L L V + "\u1102\u1102\u1162\u11A9", // Jamo L L V T + "\u1162\u1162", // Jamo V V + "\u1162\u11A9", // Jamo V T + "\u1102\u1162\u1162", // Jamo V V + "\u11A9\u11A9", // Jamo T T + "\u1102\u1162\u11A9\u11A9", // Jamo LVT T +]; + +granularities.forEach( + function(granularity) { + const segmenter = new Intl.Segmenter(undefined, {granularity}); + inputs.forEach(function(input) { + const segment = segmenter.segment(input); + for (let index = 0; index < input.length; index++) { + const result = segment.containing(index); + assert.sameValue(0, result.index); + assert.sameValue(input, result.input); + assert.sameValue(input, result.segment); + } + }); + }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/word-iswordlike.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/word-iswordlike.js new file mode 100644 index 0000000000..698637b4f9 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/word-iswordlike.js @@ -0,0 +1,55 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the isWordLike in the result when granularity is "word". +info: | + %Segments.prototype%.containing ( index ) + + 10. Return ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex). + + CreateSegmentDataObject ( segmenter, string, startIndex, endIndex ) + 11. If granularity is "word", then + a. Let isWordLike be a Boolean value indicating whether the segment in string is "word-like" according to locale segmenter.[[Locale]]. + b. Perform ! CreateDataPropertyOrThrow(result, "isWordLike", isWordLike). + +features: [Intl.Segmenter] +---*/ + +// Some text +const inputs = [ + "Hello world!", // English + "Jedovatou mambu objevila žena v zahrádkářské kolonii.", // Czech + "Việt Nam: Nhất thể hóa sẽ khác Trung Quốc?", // Vietnamese + "Σοβαρές ενστάσεις Κομισιόν για τον προϋπολογισμό της Ιταλίας", // Greek + "Решение Индии о покупке российских С-400 расценили как вызов США", // Russian + "הרופא שהציל נשים והנערה ששועבדה ע", // Hebrew, + "ترامب للملك سلمان: أنا جاد للغاية.. عليك دفع المزيد", // Arabic + "भारत की एस 400 मिसाइल के मुकाबले पाक की थाड, जानें कौन कितना ताकतवर", // Hindi + "ரெட் அலர்ட் எச்சரிக்கை; புதுச்சேரியில் நாளை அரசு விடுமுறை!", // Tamil + "'ఉత్తర్వులు అందే వరకు ఓటర్ల తుది జాబితాను వెబ్సైట్లో పెట్టవద్దు'", // Telugu + "台北》抹黑柯P失敗?朱學恒酸:姚文智氣pupu嗆大老闆", // Chinese + "วัดไทรตีระฆังเบาลงช่วงเข้าพรรษา เจ้าอาวาสเผยคนร้องเรียนรับผลกรรมแล้ว", // Thai + "九州北部の一部が暴風域に入りました(日直予報士 2018年10月06日) - 日本気象協会 tenki.jp", // Japanese + "법원 “다스 지분 처분권·수익권 모두 MB가 보유”", // Korean +]; + +const granularity = "word"; +const segmenter = new Intl.Segmenter(undefined, {granularity}); +inputs.forEach(function(input) { + const segment = segmenter.segment(input); + for (let index = 0; index < input.length; index++) { + const result = segment.containing(index); + const msg = "granularity: " + granularity + " input: " + input + + " containing(" + index + ") "; + assert.sameValue(true, result.index >= 0, msg + "index >= 0"); + assert.sameValue(true, result.index < input.length, + msg + "index < " + input.length); + assert.sameValue("string", typeof result.input, msg + "input"); + assert.sameValue("boolean", typeof result.isWordLike, + msg + "isWordLike should be boolean"); + } +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/zero-index.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/zero-index.js new file mode 100644 index 0000000000..96e752aa6a --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/containing/zero-index.js @@ -0,0 +1,69 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%segmentsprototype%.containing +description: Verifies the cases which the value of index turn into 0. +info: | + %Segments.prototype%.containing ( index ) + + 6. Let n be ? ToInteger(index). + 7. If n < 0 or n ≥ len, return undefined. + 8. Let startIndex be ! FindBoundary(segmenter, string, n, before). + + ToInteger ( argument ) + 1. Let number be ? ToNumber(argument). + 2. If number is NaN, +0, or -0, return +0. + 4. Let integer be the Number value that is the same sign as number and whose magnitude is floor(abs(number)). + 5. If integer is -0, return +0. + 6. Return integer. + + ToNumber ( argument ) + Undefined | Return NaN. + Null | Return +0. + Boolean | If argument is true, return 1. If argument is false, return +0. + +features: [Intl.Segmenter] +---*/ + +const input = "a b c"; +const granularities = [undefined, "grapheme", "word", "sentence"]; +const index_to_zeros = [ + 0, + -0, + NaN, + 0.49, + -0.49, + null, + undefined, + false, + "\ud800\udc00", // surrogate + "\ud800", // only leading surrogate + "\udc00", // only trailing surrogate + "a", + "g", + "\u00DD", + "0", + "+0", + "-0", + "0.49", + "+0.49", + "-0.49", + "4.9e-1", + "-4.9e-1", + "4.9E-1", + "-4.9E-1", +]; + +granularities.forEach( + function(granularity) { + const segmenter = new Intl.Segmenter(undefined, {granularity}); + const segment = segmenter.segment(input); + index_to_zeros.forEach(function(index) { + const result = segment.containing(index); + assert.sameValue(0, result.index); + assert.sameValue(input, result.input); + }); + }); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/length.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/length.js new file mode 100644 index 0000000000..a8b870ae88 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/length.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Checks the "length" property of Intl.Segmenter.prototype.segment(). +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 Segmenter 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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter.prototype.segment, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/name.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/name.js new file mode 100644 index 0000000000..5bada44a93 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/name.js @@ -0,0 +1,23 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Checks the "name" property of Intl.Segmenter.prototype.segment(). +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 }. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +verifyProperty(Intl.Segmenter.prototype.segment, "name", { + value: "segment", + writable: false, + enumerable: false, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/nested-next.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/nested-next.js new file mode 100644 index 0000000000..8ea6ba595c --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/nested-next.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors, Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%segmentsprototype%-@@iterator +description: Test to ensure the nested calling of the next method won't caused confusion to each other. +info: | + %Segments.prototype% [ @@iterator ] () + 5. Return ! CreateSegmentIterator(segmenter, string) + + CreateSegmentIterator ( segmenter, string ) + 1. Let internalSlotsList be « [[IteratingSegmenter]], [[IteratedString]], [[IteratedStringNextSegmentCodeUnitIndex]] ». + 2. Let iterator be ! ObjectCreate(%SegmentIterator.prototype%, internalSlotsList). + 3. Set iterator.[[IteratingSegmenter]] to segmenter. + 4. Set iterator.[[IteratedString]] to string. + 5. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to 0. + 6. Return iterator. + + %SegmentIterator.prototype%.next () + 5. Let startIndex be iterator.[[IteratedStringNextSegmentCodeUnitIndex]]. + +features: [Intl.Segmenter] +---*/ + +const segmenter = new Intl.Segmenter(); +const input = "ABCD"; +const segments = segmenter.segment(input); +let result = ""; +for (let v1 of segments) { + for (let v2 of segments) { + result += v1.segment; + result += v2.segment; + } + result += ":"; +} +assert.sameValue("AAABACAD:BABBBCBD:CACBCCCD:DADBDCDD:", result); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/next-inside-next.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/next-inside-next.js new file mode 100644 index 0000000000..79fc94815e --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/next-inside-next.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors, Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%segmentsprototype%-@@iterator +description: Test to ensure the next on two segments of the segmenter won't interfer each other. +info: | + %Segments.prototype% [ @@iterator ] () + 5. Return ! CreateSegmentIterator(segmenter, string) + + CreateSegmentIterator ( segmenter, string ) + 1. Let internalSlotsList be « [[IteratingSegmenter]], [[IteratedString]], [[IteratedStringNextSegmentCodeUnitIndex]] ». + 2. Let iterator be ! ObjectCreate(%SegmentIterator.prototype%, internalSlotsList). + 3. Set iterator.[[IteratingSegmenter]] to segmenter. + 4. Set iterator.[[IteratedString]] to string. + 5. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to 0. + 6. Return iterator. + + %SegmentIterator.prototype%.next () + 5. Let startIndex be iterator.[[IteratedStringNextSegmentCodeUnitIndex]]. + +features: [Intl.Segmenter] +---*/ + +const segmenter = new Intl.Segmenter(); +const input1 = "ABCD"; +const input2 = "123"; +const segments1 = segmenter.segment(input1); +const segments2 = segmenter.segment(input2); +let result = ""; +for (let v1 of segments1) { + for (let v2 of segments2) { + result += v1.segment; + result += v2.segment; + } + result += ":"; +} +// Now loop segments2 . +for (let v2 of segments2) { + for (let v1 of segments1) { + result += v2.segment; + result += v1.segment; + } + result += ":"; +} +assert.sameValue( + "A1A2A3:B1B2B3:C1C2C3:D1D2D3:1A1B1C1D:2A2B2C2D:3A3B3C3D:", result); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/next-mix-with-containing.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/next-mix-with-containing.js new file mode 100644 index 0000000000..a09e5c1f5a --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/next-mix-with-containing.js @@ -0,0 +1,55 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2020 the V8 project authors, Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%segmentsprototype%-@@iterator +description: Test to ensure the the calling of containing() won't impact the calling of the next(). +info: | + %Segments.prototype% [ @@iterator ] () + 5. Return ! CreateSegmentIterator(segmenter, string) + + CreateSegmentIterator ( segmenter, string ) + 1. Let internalSlotsList be « [[IteratingSegmenter]], [[IteratedString]], [[IteratedStringNextSegmentCodeUnitIndex]] ». + 2. Let iterator be ! ObjectCreate(%SegmentIterator.prototype%, internalSlotsList). + 3. Set iterator.[[IteratingSegmenter]] to segmenter. + 4. Set iterator.[[IteratedString]] to string. + 5. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to 0. + 6. Return iterator. + + %SegmentIterator.prototype%.next () + 5. Let startIndex be iterator.[[IteratedStringNextSegmentCodeUnitIndex]]. + + %Segments.prototype%.containing ( index ) + 3. Let segmenter be segments.[[SegmentsSegmenter]]. + 4. Let string be segments.[[SegmentsString]]. + + +features: [Intl.Segmenter] +---*/ + +const segmenter = new Intl.Segmenter(); +const input = "ABC"; +const segments = segmenter.segment(input); +let next_result = ""; +for (let i = 0; i < input.length; i++) { + let containing_result = segments.containing(i); + let msg = "containing(" + i + ") before the loop. "; + assert.sameValue(input[i], containing_result.segment, msg + "segment"); + assert.sameValue(i, containing_result.index, msg + "index"); + assert.sameValue(input, containing_result.input, msg + "input"); + for (let v of segments) { + next_result += v.segment; + next_result += ":"; + // Ensure the value n passing into segments.containing(n) will not impact + // the result of next(). + msg = "containing(" + i + ") inside the loop. "; + containing_result = segments.containing(i); + assert.sameValue(input[i], containing_result.segment, msg + "segment"); + assert.sameValue(i, containing_result.index, msg + "index"); + assert.sameValue(input, containing_result.input, msg + "input"); + } +} +assert.sameValue("A:B:C:A:B:C:A:B:C:", next_result); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/prop-desc.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/prop-desc.js new file mode 100644 index 0000000000..5b5252b906 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/prop-desc.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Checks the "segment" property of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.segment( string ) + + 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. +includes: [propertyHelper.js] +features: [Intl.Segmenter] +---*/ + +assert.sameValue( + typeof Intl.Segmenter.prototype.segment, + "function", + "typeof Intl.Segmenter.prototype.segment is function" +); + +verifyProperty(Intl.Segmenter.prototype, "segment", { + writable: true, + enumerable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-grapheme-iterable.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-grapheme-iterable.js new file mode 100644 index 0000000000..ebb588e414 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-grapheme-iterable.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 the V8 project authors. All rights reserved. +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Verifies the behavior for the "segment" function of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.segment( string ) +features: [Intl.Segmenter] +---*/ + +const seg = new Intl.Segmenter([], {granularity: "grapheme"}) +for (const text of [ + "Hello world!", // English + " Hello world! ", // English with space before/after + " Hello world? Foo bar!", // English + "Jedovatou mambu objevila žena v zahrádkářské kolonii.", // Czech + "Việt Nam: Nhất thể hóa sẽ khác Trung Quốc?", // Vietnamese + "Σοβαρές ενστάσεις Κομισιόν για τον προϋπολογισμό της Ιταλίας", // Greek + "Решение Индии о покупке российских С-400 расценили как вызов США", // Russian + "הרופא שהציל נשים והנערה ששועבדה ע", // Hebrew, + "ترامب للملك سلمان: أنا جاد للغاية.. عليك دفع المزيد", // Arabic + "भारत की एस 400 मिसाइल के मुकाबले पाक की थाड, जानें कौन कितना ताकतवर", // Hindi + "ரெட் அலர்ட் எச்சரிக்கை; புதுச்சேரியில் நாளை அரசு விடுமுறை!", // Tamil + "'ఉత్తర్వులు అందే వరకు ఓటర్ల తుది జాబితాను వెబ్సైట్లో పెట్టవద్దు'", // Telugu + "台北》抹黑柯P失敗?朱學恒酸:姚文智氣pupu嗆大老闆", // Chinese + "วัดไทรตีระฆังเบาลงช่วงเข้าพรรษา เจ้าอาวาสเผยคนร้องเรียนรับผลกรรมแล้ว", // Thai + "九州北部の一部が暴風域に入りました(日直予報士 2018年10月06日) - 日本気象協会 tenki.jp", // Japanese + "법원 “다스 지분 처분권·수익권 모두 MB가 보유”", // Korean + ]) { + let segments = []; + for (const v of seg.segment(text)) { + assert.sameValue(undefined, v.isWordLike); + assert.sameValue(false, v.hasOwnProperty("isWordLike")); + assert.sameValue("string", typeof v.segment); + assert(v.segment.length > 0); + assert.sameValue("string", typeof v.input); + assert.sameValue(text, v.input); + segments.push(v.segment); + } + assert.sameValue(text, segments.join('')); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-sentence-iterable.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-sentence-iterable.js new file mode 100644 index 0000000000..80608a0574 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-sentence-iterable.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 the V8 project authors. All rights reserved. +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Verifies the behavior for the "segment" function of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.segment( string ) +features: [Intl.Segmenter] +---*/ + +const seg = new Intl.Segmenter([], {granularity: "sentence"}) +for (const text of [ + "Hello world!", // English + " Hello world! ", // English with space before/after + " Hello world? Foo bar!", // English + "Jedovatou mambu objevila žena v zahrádkářské kolonii.", // Czech + "Việt Nam: Nhất thể hóa sẽ khác Trung Quốc?", // Vietnamese + "Σοβαρές ενστάσεις Κομισιόν για τον προϋπολογισμό της Ιταλίας", // Greek + "Решение Индии о покупке российских С-400 расценили как вызов США", // Russian + "הרופא שהציל נשים והנערה ששועבדה ע", // Hebrew, + "ترامب للملك سلمان: أنا جاد للغاية.. عليك دفع المزيد", // Arabic + "भारत की एस 400 मिसाइल के मुकाबले पाक की थाड, जानें कौन कितना ताकतवर", // Hindi + "ரெட் அலர்ட் எச்சரிக்கை; புதுச்சேரியில் நாளை அரசு விடுமுறை!", // Tamil + "'ఉత్తర్వులు అందే వరకు ఓటర్ల తుది జాబితాను వెబ్సైట్లో పెట్టవద్దు'", // Telugu + "台北》抹黑柯P失敗?朱學恒酸:姚文智氣pupu嗆大老闆", // Chinese + "วัดไทรตีระฆังเบาลงช่วงเข้าพรรษา เจ้าอาวาสเผยคนร้องเรียนรับผลกรรมแล้ว", // Thai + "九州北部の一部が暴風域に入りました(日直予報士 2018年10月06日) - 日本気象協会 tenki.jp", // Japanese + "법원 “다스 지분 처분권·수익권 모두 MB가 보유”", // Korean + ]) { + let segments = []; + for (const v of seg.segment(text)) { + assert.sameValue(undefined, v.isWordLike); + assert.sameValue(false, v.hasOwnProperty("isWordLike")); + assert.sameValue("string", typeof v.segment); + assert(v.segment.length > 0); + assert.sameValue("string", typeof v.input); + assert.sameValue(text, v.input); + segments.push(v.segment); + } + assert.sameValue(text, segments.join('')); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-tostring.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-tostring.js new file mode 100644 index 0000000000..2a264d056c --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-tostring.js @@ -0,0 +1,37 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 the V8 project authors, Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Verifies the string coercion in the "segment" function of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.segment( string ) + + 3. Let string be ? ToString(string). +features: [Intl.Segmenter] +---*/ + +const tests = [ + [[], "undefined"], + [[undefined], "undefined"], + [[null], "null"], + [[true], "true"], + [[false], "false"], + [[12], "12"], + [[1.23], "1.23"], + [[["a", "b"]], "a"], + [[{}], "["], // "[object Object]" +]; + +const segmenter = new Intl.Segmenter("en", { "granularity": "word" }); +for (const [args, expected] of tests) { + const segments = segmenter.segment(...args); + const actual = [...segments][0].segment; + assert.sameValue(actual, expected, `Expected segment "${expected}", found "${actual}" for arguments ${args}`); +} + +const symbol = Symbol(); +assert.throws(TypeError, () => segmenter.segment(symbol)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-word-iterable.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-word-iterable.js new file mode 100644 index 0000000000..e1bc5cf4a0 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/segment-word-iterable.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 the V8 project authors. All rights reserved. +// Copyright 2020 Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-Intl.Segmenter.prototype.segment +description: Verifies the behavior for the "segment" function of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype.segment( string ) +features: [Intl.Segmenter] +---*/ + +const seg = new Intl.Segmenter([], {granularity: "word"}) +for (const text of [ + "Hello world!", // English + " Hello world! ", // English with space before/after + " Hello world? Foo bar!", // English + "Jedovatou mambu objevila žena v zahrádkářské kolonii.", // Czech + "Việt Nam: Nhất thể hóa sẽ khác Trung Quốc?", // Vietnamese + "Σοβαρές ενστάσεις Κομισιόν για τον προϋπολογισμό της Ιταλίας", // Greek + "Решение Индии о покупке российских С-400 расценили как вызов США", // Russian + "הרופא שהציל נשים והנערה ששועבדה ע", // Hebrew, + "ترامب للملك سلمان: أنا جاد للغاية.. عليك دفع المزيد", // Arabic + "भारत की एस 400 मिसाइल के मुकाबले पाक की थाड, जानें कौन कितना ताकतवर", // Hindi + "ரெட் அலர்ட் எச்சரிக்கை; புதுச்சேரியில் நாளை அரசு விடுமுறை!", // Tamil + "'ఉత్తర్వులు అందే వరకు ఓటర్ల తుది జాబితాను వెబ్సైట్లో పెట్టవద్దు'", // Telugu + "台北》抹黑柯P失敗?朱學恒酸:姚文智氣pupu嗆大老闆", // Chinese + "วัดไทรตีระฆังเบาลงช่วงเข้าพรรษา เจ้าอาวาสเผยคนร้องเรียนรับผลกรรมแล้ว", // Thai + "九州北部の一部が暴風域に入りました(日直予報士 2018年10月06日) - 日本気象協会 tenki.jp", // Japanese + "법원 “다스 지분 처분권·수익권 모두 MB가 보유”", // Korean + ]) { + let segments = []; + for (const v of seg.segment(text)) { + assert.sameValue("boolean", typeof v.isWordLike); + assert.sameValue(true, v.hasOwnProperty("isWordLike")); + assert.sameValue("string", typeof v.segment); + assert(v.segment.length > 0); + assert.sameValue("string", typeof v.input); + assert.sameValue(text, v.input); + segments.push(v.segment); + } + assert.sameValue(text, segments.join('')); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/segment/shell.js b/js/src/tests/test262/intl402/Segmenter/prototype/segment/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/segment/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/shell.js b/js/src/tests/test262/intl402/Segmenter/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/browser.js b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/shell.js b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/toString.js b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/toString.js new file mode 100644 index 0000000000..a0b251f80f --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/toString.js @@ -0,0 +1,19 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.Segmenter.prototype-@@tostringtag +description: > + Checks Object.prototype.toString with Intl.Segmenter objects. +info: | + Intl.Segmenter.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.Segmenter". +features: [Intl.Segmenter] +---*/ + +assert.sameValue(Object.prototype.toString.call(Intl.Segmenter.prototype), "[object Intl.Segmenter]"); +assert.sameValue(Object.prototype.toString.call(new Intl.Segmenter()), "[object Intl.Segmenter]"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/toStringTag.js b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/toStringTag.js new file mode 100644 index 0000000000..d3053866c5 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/prototype/toStringTag/toStringTag.js @@ -0,0 +1,26 @@ +// |reftest| skip -- Intl.Segmenter is not supported +// Copyright 2018 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.Segmenter.prototype-@@tostringtag +description: > + Checks the @@toStringTag property of the Segmenter prototype object. +info: | + Intl.Segmenter.prototype[ @@toStringTag ] + + The initial value of the @@toStringTag property is the string value "Intl.Segmenter". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Intl.Segmenter, Symbol.toStringTag] +---*/ + +verifyProperty(Intl.Segmenter.prototype, Symbol.toStringTag, { + value: "Intl.Segmenter", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/Segmenter/shell.js b/js/src/tests/test262/intl402/Segmenter/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/Segmenter/shell.js diff --git a/js/src/tests/test262/intl402/String/browser.js b/js/src/tests/test262/intl402/String/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/browser.js diff --git a/js/src/tests/test262/intl402/String/prototype/browser.js b/js/src/tests/test262/intl402/String/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/browser.js diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/browser.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/browser.js diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/builtin.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/builtin.js new file mode 100644 index 0000000000..ea9820bab9 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/builtin.js @@ -0,0 +1,30 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.1.1_L15 +description: > + Tests that String.prototype.localeCompare meets the requirements + for built-in objects defined by the introduction of chapter 17 of + the ECMAScript Language Specification. +author: Norbert Lindenberg +includes: [isConstructor.js] +features: [Reflect.construct] +---*/ + +assert.sameValue(Object.prototype.toString.call(String.prototype.localeCompare), "[object Function]", + "The [[Class]] internal property of a built-in function must be " + + "\"Function\"."); + +assert(Object.isExtensible(String.prototype.localeCompare), + "Built-in objects must be extensible."); + +assert.sameValue(Object.getPrototypeOf(String.prototype.localeCompare), Function.prototype); + +assert.sameValue(String.prototype.localeCompare.hasOwnProperty("prototype"), false, + "Built-in functions that aren't constructors must not have a prototype property."); + +assert.sameValue(isConstructor(String.prototype.localeCompare), false, + "Built-in functions don't implement [[Construct]] unless explicitly specified."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/default-options-object-prototype.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/default-options-object-prototype.js new file mode 100644 index 0000000000..dac753245b --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/default-options-object-prototype.js @@ -0,0 +1,21 @@ +// Copyright (C) 2017 Daniel Ehrenberg. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-initializecollator +description: > + Monkey-patching Object.prototype does not change the default + options for Collator as a null prototype is used. +info: | + InitializeCollator ( collator, locales, options ) + + 1. If _options_ is *undefined*, then + 1. Let _options_ be ObjectCreate(*null*). +---*/ + +if (new Intl.Collator("en").resolvedOptions().locale === "en") { + Object.prototype.sensitivity = "base"; + assert.sameValue("a".localeCompare("A"), -1); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/length.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/length.js new file mode 100644 index 0000000000..6f657c420d --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/length.js @@ -0,0 +1,33 @@ +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-String.prototype.localeCompare +description: > + String.prototype.localeCompare.length is 1. +info: | + String.prototype.localeCompare ( that [ , locales [ , options ] ] ) + + 17 ECMAScript Standard Built-in Objects: + + 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 }. + +includes: [propertyHelper.js] +---*/ + +assert.sameValue(String.prototype.localeCompare.length, 1); + +verifyNotEnumerable(String.prototype.localeCompare, "length"); +verifyNotWritable(String.prototype.localeCompare, "length"); +verifyConfigurable(String.prototype.localeCompare, "length"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/missing-arguments-coerced-to-undefined.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/missing-arguments-coerced-to-undefined.js new file mode 100644 index 0000000000..2b80e84a89 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/missing-arguments-coerced-to-undefined.js @@ -0,0 +1,21 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.1.1_3_2 +description: > + Tests that String.prototype.localeCompare treats a missing "that" + argument, undefined, and "undefined" as equivalent. +author: Norbert Lindenberg +---*/ + +var thisValues = ["a", "t", "u", "undefined", "UNDEFINED", "nicht definiert", "xyz", "未定义"]; + +var i; +for (i = 0; i < thisValues.length; i++) { + var thisValue = thisValues[i]; + assert.sameValue(thisValue.localeCompare(), thisValue.localeCompare(undefined), "String.prototype.localeCompare does not treat missing 'that' argument as undefined."); + assert.sameValue(thisValue.localeCompare(undefined), thisValue.localeCompare("undefined"), "String.prototype.localeCompare does not treat undefined 'that' argument as \"undefined\"."); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/return-abrupt-this-value.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/return-abrupt-this-value.js new file mode 100644 index 0000000000..21de34a98d --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/return-abrupt-this-value.js @@ -0,0 +1,20 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.1.1_1 +description: > + Tests that localeCompare rejects values that can't be coerced to + an object. +author: Norbert Lindenberg +---*/ + +var invalidValues = [undefined, null]; + +invalidValues.forEach(function (value) { + assert.throws(TypeError, function() { + var result = String.prototype.localeCompare.call(value, ""); + }, "String.prototype.localeCompare did not reject this = " + value + "."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/returns-same-results-as-Collator.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/returns-same-results-as-Collator.js new file mode 100644 index 0000000000..c93530777d --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/returns-same-results-as-Collator.js @@ -0,0 +1,32 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.1.1_7 +description: > + Tests that localeCompare produces the same results as + Intl.Collator. +author: Norbert Lindenberg +includes: [compareArray.js] +---*/ + +var strings = ["d", "O", "od", "oe", "of", "ö", "o\u0308", "X", "y", "Z", "Z.", "𠮷野家", "吉野家", "!A", "A", "b", "C"]; +var locales = [undefined, ["de"], ["de-u-co-phonebk"], ["en"], ["ja"], ["sv"]]; +var options = [ + undefined, + {usage: "search"}, + {sensitivity: "base", ignorePunctuation: true} +]; + +locales.forEach(function (locales) { + options.forEach(function (options) { + var referenceCollator = new Intl.Collator(locales, options); + var referenceSorted = strings.slice().sort(referenceCollator.compare); + + strings.sort(function (a, b) { return a.localeCompare(b, locales, options); }); + assert.compareArray(strings, referenceSorted, + "(Testing with locales " + locales + "; options " + JSON.stringify(options) + ".)"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/shell.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/taint-Intl-Collator.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/taint-Intl-Collator.js new file mode 100644 index 0000000000..2955b6a8f0 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/taint-Intl-Collator.js @@ -0,0 +1,16 @@ +// Copyright 2013 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +es5id: 13.1.1_6_2 +description: > + Tests that String.prototype.localeCompare uses the standard + built-in Intl.Collator constructor. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintDataProperty(Intl, "Collator"); +"a".localeCompare("b"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/that-arg-coerced-to-string.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/that-arg-coerced-to-string.js new file mode 100644 index 0000000000..8de5a8129c --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/that-arg-coerced-to-string.js @@ -0,0 +1,22 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.1.1_3_1 +description: Tests that localeCompare coerces that to a string. +author: Norbert Lindenberg +---*/ + +var thisValues = ["true", "5", "hello", "good bye"]; +var thatValues = [true, 5, "hello", {toString: function () { return "good bye"; }}]; + +var i; +for (i = 0; i < thisValues.length; i++) { + var j; + for (j = 0; j < thatValues.length; j++) { + var result = String.prototype.localeCompare.call(thisValues[i], thatValues[j]); + assert.sameValue((result === 0), (i === j), "localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as " + (result === 0 ? "equal" : "different") + "."); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/this-value-coerced-to-string.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/this-value-coerced-to-string.js new file mode 100644 index 0000000000..b8c999059e --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/this-value-coerced-to-string.js @@ -0,0 +1,22 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.1.1_2 +description: Tests that localeCompare coerces this to a string. +author: Norbert Lindenberg +---*/ + +var thisValues = [true, 5, "hello", {toString: function () { return "good bye"; }}]; +var thatValues = ["true", "5", "hello", "good bye"]; + +var i; +for (i = 0; i < thisValues.length; i++) { + var j; + for (j = 0; j < thatValues.length; j++) { + var result = String.prototype.localeCompare.call(thisValues[i], thatValues[j]); + assert.sameValue((result === 0), (i === j), "localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as " + (result === 0 ? "equal" : "different") + "."); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/localeCompare/throws-same-exceptions-as-Collator.js b/js/src/tests/test262/intl402/String/prototype/localeCompare/throws-same-exceptions-as-Collator.js new file mode 100644 index 0000000000..3910154616 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/localeCompare/throws-same-exceptions-as-Collator.js @@ -0,0 +1,47 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 13.1.1_6_1 +description: > + Tests that String.prototype.localeCompare throws the same + exceptions as Intl.Collator. +author: Norbert Lindenberg +---*/ + +var locales = [null, [NaN], ["i"], ["de_DE"]]; +var options = [ + {localeMatcher: null}, + {usage: "invalid"}, + {sensitivity: "invalid"} +]; + +locales.forEach(function (locales) { + var referenceError, error; + try { + var collator = new Intl.Collator(locales); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.Collator for locales " + locales + "."); + + assert.throws(referenceError.constructor, function() { + var result = "".localeCompare("", locales); + }, "String.prototype.localeCompare didn't throw exception for locales " + locales + "."); +}); + +options.forEach(function (options) { + var referenceError, error; + try { + var collator = new Intl.Collator([], options); + } catch (e) { + referenceError = e; + } + assert.notSameValue(referenceError, undefined, "Internal error: Expected exception was not thrown by Intl.Collator for options " + JSON.stringify(options) + "."); + + assert.throws(referenceError.constructor, function() { + var result = "".localeCompare("", [], options); + }, "String.prototype.localeCompare didn't throw exception for options " + JSON.stringify(options) + "."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/shell.js b/js/src/tests/test262/intl402/String/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/shell.js diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/browser.js b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/browser.js diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/capital_I_with_dot.js b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/capital_I_with_dot.js new file mode 100644 index 0000000000..aa273e7a50 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/capital_I_with_dot.js @@ -0,0 +1,17 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Check if String.prototype.toLocaleLowerCase supports mappings defined in SpecialCasings +info: | + The result must be derived according to the case mappings in the Unicode character database (this explicitly + includes not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it). +es5id: 15.5.4.16 +es6id: 21.1.3.20 +---*/ + +// Locale-sensitive for Turkish and Azeri. +assert.sameValue("\u0130".toLocaleLowerCase("und"), "\u0069\u0307", "LATIN CAPITAL LETTER I WITH DOT ABOVE"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/shell.js b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/shell.js diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Azeri.js b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Azeri.js new file mode 100644 index 0000000000..82989e6874 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Azeri.js @@ -0,0 +1,87 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Check if String.prototype.toLocaleLowerCase supports language-sensitive mappings defined in SpecialCasings (Azeri) +info: | + The result must be derived according to the case mappings in the Unicode character database (this explicitly + includes not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it). +es5id: 15.5.4.16 +es6id: 21.1.3.20 +---*/ + +// SpecialCasing.txt, conditional, language-sensitive mappings (Azeri). + +// LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130) changed to LATIN SMALL LETTER I when lowercasing. +assert.sameValue( + "\u0130".toLocaleLowerCase("az"), + "i", + "LATIN CAPITAL LETTER I WITH DOT ABOVE" +); + + +// COMBINING DOT ABOVE (U+0307) removed after LATIN CAPITAL LETTER I when lowercasing. +// - COMBINING DOT BELOW (U+0323), combining class 220 (Below) +// - PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE (U+101FD = D800 DDFD), combining class 220 (Below) +assert.sameValue( + "I\u0307".toLocaleLowerCase("az"), + "i", + "LATIN CAPITAL LETTER I followed by COMBINING DOT ABOVE" +); +assert.sameValue( + "I\u0323\u0307".toLocaleLowerCase("az"), + "i\u0323", + "LATIN CAPITAL LETTER I followed by COMBINING DOT BELOW, COMBINING DOT ABOVE" +); +assert.sameValue( + "I\uD800\uDDFD\u0307".toLocaleLowerCase("az"), + "i\uD800\uDDFD", + "LATIN CAPITAL LETTER I followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, COMBINING DOT ABOVE" +); + + +// COMBINING DOT ABOVE (U+0307) not removed when character is preceded by a character of combining class 0. +assert.sameValue( + "IA\u0307".toLocaleLowerCase("az"), + "\u0131a\u0307", + "LATIN CAPITAL LETTER I followed by LATIN CAPITAL LETTER A, COMBINING DOT ABOVE" +); + + +// COMBINING DOT ABOVE (U+0307) not removed when character is preceded by a character of combining class 230. +// - COMBINING GRAVE ACCENT (U+0300), combining class 230 (Above) +// - MUSICAL SYMBOL COMBINING DOIT (U+1D185, D834 DD85), combining class 230 (Above) +assert.sameValue( + "I\u0300\u0307".toLocaleLowerCase("az"), + "\u0131\u0300\u0307", + "LATIN CAPITAL LETTER I followed by COMBINING GRAVE ACCENT, COMBINING DOT ABOVE" +); +assert.sameValue( + "I\uD834\uDD85\u0307".toLocaleLowerCase("az"), + "\u0131\uD834\uDD85\u0307", + "LATIN CAPITAL LETTER I followed by MUSICAL SYMBOL COMBINING DOIT, COMBINING DOT ABOVE" +); + + +// LATIN CAPITAL LETTER I changed to LATIN SMALL LETTER DOTLESS I (U+0131) when lowercasing. +assert.sameValue( + "I".toLocaleLowerCase("az"), + "\u0131", + "LATIN CAPITAL LETTER I" +); + + +// No changes when lowercasing LATIN SMALL LETTER I and LATIN SMALL LETTER DOTLESS I (U+0131). +assert.sameValue( + "i".toLocaleLowerCase("az"), + "i", + "LATIN SMALL LETTER I" +); +assert.sameValue( + "\u0131".toLocaleLowerCase("az"), + "\u0131", + "LATIN SMALL LETTER DOTLESS I" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Lithuanian.js b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Lithuanian.js new file mode 100644 index 0000000000..73f38e190c --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Lithuanian.js @@ -0,0 +1,195 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Check if String.prototype.toLocaleLowerCase supports language-sensitive mappings defined in SpecialCasings (Lithuanian) +info: | + The result must be derived according to the case mappings in the Unicode character database (this explicitly + includes not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it). +es5id: 15.5.4.16 +es6id: 21.1.3.20 +---*/ + +// SpecialCasing.txt, conditional, language-sensitive mappings (Lithuanian). + +// COMBINING DOT ABOVE added when lowercasing capital I, J and I WITH OGONEK (U+012E). +// Character directly followed by character of combining class 230 (Above). +// - COMBINING GRAVE ACCENT (U+0300), combining class 230 (Above) +assert.sameValue( + "I\u0300".toLocaleLowerCase("lt"), + "i\u0307\u0300", + "LATIN CAPITAL LETTER I followed by COMBINING GRAVE ACCENT" +); +assert.sameValue( + "J\u0300".toLocaleLowerCase("lt"), + "j\u0307\u0300", + "LATIN CAPITAL LETTER J followed by COMBINING GRAVE ACCENT" +); +assert.sameValue( + "\u012E\u0300".toLocaleLowerCase("lt"), + "\u012F\u0307\u0300", + "LATIN CAPITAL LETTER I WITH OGONEK followed by COMBINING GRAVE ACCENT" +); + + +// COMBINING DOT ABOVE added when lowercasing capital I, J and I WITH OGONEK (U+012E). +// Character directly followed by character of combining class 230 (Above). +// - MUSICAL SYMBOL COMBINING DOIT (U+1D185, D834 DD85), combining class 230 (Above) +assert.sameValue( + "I\uD834\uDD85".toLocaleLowerCase("lt"), + "i\u0307\uD834\uDD85", + "LATIN CAPITAL LETTER I followed by MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "J\uD834\uDD85".toLocaleLowerCase("lt"), + "j\u0307\uD834\uDD85", + "LATIN CAPITAL LETTER J followed by MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "\u012E\uD834\uDD85".toLocaleLowerCase("lt"), + "\u012F\u0307\uD834\uDD85", + "LATIN CAPITAL LETTER I WITH OGONEK followed by MUSICAL SYMBOL COMBINING DOIT" +); + + +// COMBINING DOT ABOVE added when lowercasing capital I, J and I WITH OGONEK (U+012E). +// Character not directly followed by character of combining class 230 (Above). +// - COMBINING RING BELOW (U+0325), combining class 220 (Below) +// - COMBINING GRAVE ACCENT (U+0300), combining class 230 (Above) +assert.sameValue( + "I\u0325\u0300".toLocaleLowerCase("lt"), + "i\u0307\u0325\u0300", + "LATIN CAPITAL LETTER I followed by COMBINING RING BELOW, COMBINING GRAVE ACCENT" +); +assert.sameValue( + "J\u0325\u0300".toLocaleLowerCase("lt"), + "j\u0307\u0325\u0300", + "LATIN CAPITAL LETTER J followed by COMBINING RING BELOW, COMBINING GRAVE ACCENT" +); +assert.sameValue( + "\u012E\u0325\u0300".toLocaleLowerCase("lt"), + "\u012F\u0307\u0325\u0300", + "LATIN CAPITAL LETTER I WITH OGONEK followed by COMBINING RING BELOW, COMBINING GRAVE ACCENT" +); + + +// COMBINING DOT ABOVE added when lowercasing capital I, J and I WITH OGONEK (U+012E). +// Character not directly followed by character of combining class 230 (Above). +// - PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE (U+101FD, D800 DDFD), combining class 220 (Below) +// - COMBINING GRAVE ACCENT (U+0300), combining class 230 (Above) +assert.sameValue( + "I\uD800\uDDFD\u0300".toLocaleLowerCase("lt"), + "i\u0307\uD800\uDDFD\u0300", + "LATIN CAPITAL LETTER I followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, COMBINING GRAVE ACCENT" +); +assert.sameValue( + "J\uD800\uDDFD\u0300".toLocaleLowerCase("lt"), + "j\u0307\uD800\uDDFD\u0300", + "LATIN CAPITAL LETTER J followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, COMBINING GRAVE ACCENT" +); +assert.sameValue( + "\u012E\uD800\uDDFD\u0300".toLocaleLowerCase("lt"), + "\u012F\u0307\uD800\uDDFD\u0300", + "LATIN CAPITAL LETTER I WITH OGONEK followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, COMBINING GRAVE ACCENT" +); + + +// COMBINING DOT ABOVE added when lowercasing capital I, J and I WITH OGONEK (U+012E). +// Character not directly followed by character of combining class 230 (Above). +// - COMBINING RING BELOW (U+0325), combining class 220 (Below) +// - MUSICAL SYMBOL COMBINING DOIT (U+1D185, D834 DD85), combining class 230 (Above) +assert.sameValue( + "I\u0325\uD834\uDD85".toLocaleLowerCase("lt"), + "i\u0307\u0325\uD834\uDD85", + "LATIN CAPITAL LETTER I followed by COMBINING RING BELOW, MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "J\u0325\uD834\uDD85".toLocaleLowerCase("lt"), + "j\u0307\u0325\uD834\uDD85", + "LATIN CAPITAL LETTER J followed by COMBINING RING BELOW, MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "\u012E\u0325\uD834\uDD85".toLocaleLowerCase("lt"), + "\u012F\u0307\u0325\uD834\uDD85", + "LATIN CAPITAL LETTER I WITH OGONEK followed by COMBINING RING BELOW, MUSICAL SYMBOL COMBINING DOIT" +); + + +// COMBINING DOT ABOVE added when lowercasing capital I, J and I WITH OGONEK (U+012E). +// Character not directly followed by character of combining class 230 (Above). +// - PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE (U+101FD, D800 DDFD), combining class 220 (Below) +// - MUSICAL SYMBOL COMBINING DOIT (U+1D185, D834 DD85), combining class 230 (Above) +assert.sameValue( + "I\uD800\uDDFD\uD834\uDD85".toLocaleLowerCase("lt"), + "i\u0307\uD800\uDDFD\uD834\uDD85", + "LATIN CAPITAL LETTER I followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "J\uD800\uDDFD\uD834\uDD85".toLocaleLowerCase("lt"), + "j\u0307\uD800\uDDFD\uD834\uDD85", + "LATIN CAPITAL LETTER J followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "\u012E\uD800\uDDFD\uD834\uDD85".toLocaleLowerCase("lt"), + "\u012F\u0307\uD800\uDDFD\uD834\uDD85", + "LATIN CAPITAL LETTER I WITH OGONEK followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, MUSICAL SYMBOL COMBINING DOIT" +); + + +// COMBINING DOT ABOVE not added when character is followed by a character of combining class 0. +// - COMBINING GRAVE ACCENT (U+0300), combining class 230 (Above) +assert.sameValue( + "IA\u0300".toLocaleLowerCase("lt"), + "ia\u0300", + "LATIN CAPITAL LETTER I followed by LATIN CAPITAL LETTER A, COMBINING GRAVE ACCENT" +); +assert.sameValue( + "JA\u0300".toLocaleLowerCase("lt"), + "ja\u0300", + "LATIN CAPITAL LETTER J followed by LATIN CAPITAL LETTER A, COMBINING GRAVE ACCENT" +); +assert.sameValue( + "\u012EA\u0300".toLocaleLowerCase("lt"), + "\u012Fa\u0300", + "LATIN CAPITAL LETTER I WITH OGONEK followed by LATIN CAPITAL LETTER A, COMBINING GRAVE ACCENT" +); + + +// COMBINING DOT ABOVE not added when character is followed by a character of combining class 0. +// - MUSICAL SYMBOL COMBINING DOIT (U+1D185, D834 DD85), combining class 230 (Above) +assert.sameValue( + "IA\uD834\uDD85".toLocaleLowerCase("lt"), + "ia\uD834\uDD85", + "LATIN CAPITAL LETTER I followed by LATIN CAPITAL LETTER A, MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "JA\uD834\uDD85".toLocaleLowerCase("lt"), + "ja\uD834\uDD85", + "LATIN CAPITAL LETTER J followed by LATIN CAPITAL LETTER A, MUSICAL SYMBOL COMBINING DOIT" +); +assert.sameValue( + "\u012EA\uD834\uDD85".toLocaleLowerCase("lt"), + "\u012Fa\uD834\uDD85", + "LATIN CAPITAL LETTER I WITH OGONEK (U+012E) followed by LATIN CAPITAL LETTER A, MUSICAL SYMBOL COMBINING DOIT" +); + + +// Precomposed characters with accents above. +assert.sameValue( + "\u00CC".toLocaleLowerCase("lt"), + "\u0069\u0307\u0300", + "LATIN CAPITAL LETTER I WITH GRAVE" +); +assert.sameValue( + "\u00CD".toLocaleLowerCase("lt"), + "\u0069\u0307\u0301", + "LATIN CAPITAL LETTER I WITH ACUTE" +); +assert.sameValue( + "\u0128".toLocaleLowerCase("lt"), + "\u0069\u0307\u0303", + "LATIN CAPITAL LETTER I WITH TILDE" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Turkish.js b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Turkish.js new file mode 100644 index 0000000000..bbd4578243 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleLowerCase/special_casing_Turkish.js @@ -0,0 +1,87 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Check if String.prototype.toLocaleLowerCase supports language-sensitive mappings defined in SpecialCasings (Turkish) +info: | + The result must be derived according to the case mappings in the Unicode character database (this explicitly + includes not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it). +es5id: 15.5.4.16 +es6id: 21.1.3.20 +---*/ + +// SpecialCasing.txt, conditional, language-sensitive mappings (Turkish). + +// LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130) changed to LATIN SMALL LETTER I when lowercasing. +assert.sameValue( + "\u0130".toLocaleLowerCase("tr"), + "i", + "LATIN CAPITAL LETTER I WITH DOT ABOVE" +); + + +// COMBINING DOT ABOVE (U+0307) removed after LATIN CAPITAL LETTER I when lowercasing. +// - COMBINING DOT BELOW (U+0323), combining class 220 (Below) +// - PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE (U+101FD = D800 DDFD), combining class 220 (Below) +assert.sameValue( + "I\u0307".toLocaleLowerCase("tr"), + "i", + "LATIN CAPITAL LETTER I followed by COMBINING DOT ABOVE" +); +assert.sameValue( + "I\u0323\u0307".toLocaleLowerCase("tr"), + "i\u0323", + "LATIN CAPITAL LETTER I followed by COMBINING DOT BELOW, COMBINING DOT ABOVE" +); +assert.sameValue( + "I\uD800\uDDFD\u0307".toLocaleLowerCase("tr"), + "i\uD800\uDDFD", + "LATIN CAPITAL LETTER I followed by PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, COMBINING DOT ABOVE" +); + + +// COMBINING DOT ABOVE (U+0307) not removed when character is preceded by a character of combining class 0. +assert.sameValue( + "IA\u0307".toLocaleLowerCase("tr"), + "\u0131a\u0307", + "LATIN CAPITAL LETTER I followed by LATIN CAPITAL LETTER A, COMBINING DOT ABOVE" +); + + +// COMBINING DOT ABOVE (U+0307) not removed when character is preceded by a character of combining class 230. +// - COMBINING GRAVE ACCENT (U+0300), combining class 230 (Above) +// - MUSICAL SYMBOL COMBINING DOIT (U+1D185, D834 DD85), combining class 230 (Above) +assert.sameValue( + "I\u0300\u0307".toLocaleLowerCase("tr"), + "\u0131\u0300\u0307", + "LATIN CAPITAL LETTER I followed by COMBINING GRAVE ACCENT, COMBINING DOT ABOVE" +); +assert.sameValue( + "I\uD834\uDD85\u0307".toLocaleLowerCase("tr"), + "\u0131\uD834\uDD85\u0307", + "LATIN CAPITAL LETTER I followed by MUSICAL SYMBOL COMBINING DOIT, COMBINING DOT ABOVE" +); + + +// LATIN CAPITAL LETTER I changed to LATIN SMALL LETTER DOTLESS I (U+0131) when lowercasing. +assert.sameValue( + "I".toLocaleLowerCase("tr"), + "\u0131", + "LATIN CAPITAL LETTER I" +); + + +// No changes when lowercasing LATIN SMALL LETTER I and LATIN SMALL LETTER DOTLESS I (U+0131). +assert.sameValue( + "i".toLocaleLowerCase("tr"), + "i", + "LATIN SMALL LETTER I" +); +assert.sameValue( + "\u0131".toLocaleLowerCase("tr"), + "\u0131", + "LATIN SMALL LETTER DOTLESS I" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/browser.js b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/browser.js diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/shell.js b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/shell.js diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Azeri.js b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Azeri.js new file mode 100644 index 0000000000..8b5021555a --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Azeri.js @@ -0,0 +1,47 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Check if String.prototype.toLocaleUpperCase supports language-sensitive mappings defined in SpecialCasings (Azeri) +info: | + The result must be derived according to the case mappings in the Unicode character database (this explicitly + includes not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it). +es5id: 15.5.4.16 +es6id: 21.1.3.21 +---*/ + +// SpecialCasing.txt, conditional, language-sensitive mappings (Azeri). + +// LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130) not changed when uppercasing. +assert.sameValue( + "\u0130".toLocaleUpperCase("az"), + "\u0130", + "LATIN CAPITAL LETTER I WITH DOT ABOVE" +); + + +// LATIN CAPITAL LETTER I not changed when uppercasing. +assert.sameValue( + "I".toLocaleUpperCase("az"), + "I", + "LATIN CAPITAL LETTER I" +); + + +// LATIN SMALL LETTER I changed to LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130) when uppercasing. +assert.sameValue( + "i".toLocaleUpperCase("az"), + "\u0130", + "LATIN SMALL LETTER I" +); + + +// LATIN SMALL LETTER DOTLESS I (U+0131) changed to LATIN CAPITAL LETTER I when uppercasing. +assert.sameValue( + "\u0131".toLocaleUpperCase("az"), + "I", + "LATIN SMALL LETTER DOTLESS I" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian.js b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian.js new file mode 100644 index 0000000000..2dfefd9851 --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian.js @@ -0,0 +1,115 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Check if String.prototype.toLocaleUpperCase supports language-sensitive mappings defined in SpecialCasings (Lithuanian) +info: | + The result must be derived according to the case mappings in the Unicode character database (this explicitly + includes not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it). +es5id: 15.5.4.16 +es6id: 21.1.3.21 +---*/ + +// SpecialCasing.txt, conditional, language-sensitive mappings (Lithuanian). + +// COMBINING DOT ABOVE (U+0307) not removed when uppercasing capital I and J. +assert.sameValue( + "I\u0307".toLocaleUpperCase("lt"), + "I\u0307", + "COMBINING DOT ABOVE preceded by LATIN CAPITAL LETTER I" +); +assert.sameValue( + "J\u0307".toLocaleUpperCase("lt"), + "J\u0307", + "COMBINING DOT ABOVE preceded by LATIN CAPITAL LETTER J" +); + + +// Code points with Soft_Dotted property (Unicode 5.1, PropList.txt) +var softDotted = [ + "\u0069", "\u006A", // LATIN SMALL LETTER I..LATIN SMALL LETTER J + "\u012F", // LATIN SMALL LETTER I WITH OGONEK + "\u0249", // LATIN SMALL LETTER J WITH STROKE + "\u0268", // LATIN SMALL LETTER I WITH STROKE + "\u029D", // LATIN SMALL LETTER J WITH CROSSED-TAIL + "\u02B2", // MODIFIER LETTER SMALL J + "\u03F3", // GREEK LETTER YOT + "\u0456", // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + "\u0458", // CYRILLIC SMALL LETTER JE + "\u1D62", // LATIN SUBSCRIPT SMALL LETTER I + "\u1D96", // LATIN SMALL LETTER I WITH RETROFLEX HOOK + "\u1DA4", // MODIFIER LETTER SMALL I WITH STROKE + "\u1DA8", // MODIFIER LETTER SMALL J WITH CROSSED-TAIL + "\u1E2D", // LATIN SMALL LETTER I WITH TILDE BELOW + "\u1ECB", // LATIN SMALL LETTER I WITH DOT BELOW + "\u2071", // SUPERSCRIPT LATIN SMALL LETTER I + "\u2148", "\u2149", // DOUBLE-STRUCK ITALIC SMALL I..DOUBLE-STRUCK ITALIC SMALL J + "\u2C7C", // LATIN SUBSCRIPT SMALL LETTER J + "\uD835\uDC22", "\uD835\uDC23", // MATHEMATICAL BOLD SMALL I..MATHEMATICAL BOLD SMALL J + "\uD835\uDC56", "\uD835\uDC57", // MATHEMATICAL ITALIC SMALL I..MATHEMATICAL ITALIC SMALL J + "\uD835\uDC8A", "\uD835\uDC8B", // MATHEMATICAL BOLD ITALIC SMALL I..MATHEMATICAL BOLD ITALIC SMALL J + "\uD835\uDCBE", "\uD835\uDCBF", // MATHEMATICAL SCRIPT SMALL I..MATHEMATICAL SCRIPT SMALL J + "\uD835\uDCF2", "\uD835\uDCF3", // MATHEMATICAL BOLD SCRIPT SMALL I..MATHEMATICAL BOLD SCRIPT SMALL J + "\uD835\uDD26", "\uD835\uDD27", // MATHEMATICAL FRAKTUR SMALL I..MATHEMATICAL FRAKTUR SMALL J + "\uD835\uDD5A", "\uD835\uDD5B", // MATHEMATICAL DOUBLE-STRUCK SMALL I..MATHEMATICAL DOUBLE-STRUCK SMALL J + "\uD835\uDD8E", "\uD835\uDD8F", // MATHEMATICAL BOLD FRAKTUR SMALL I..MATHEMATICAL BOLD FRAKTUR SMALL J + "\uD835\uDDC2", "\uD835\uDDC3", // MATHEMATICAL SANS-SERIF SMALL I..MATHEMATICAL SANS-SERIF SMALL J + "\uD835\uDDF6", "\uD835\uDDF7", // MATHEMATICAL SANS-SERIF BOLD SMALL I..MATHEMATICAL SANS-SERIF BOLD SMALL J + "\uD835\uDE2A", "\uD835\uDE2B", // MATHEMATICAL SANS-SERIF ITALIC SMALL I..MATHEMATICAL SANS-SERIF ITALIC SMALL J + "\uD835\uDE5E", "\uD835\uDE5F", // MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J + "\uD835\uDE92", "\uD835\uDE93", // MATHEMATICAL MONOSPACE SMALL I..MATHEMATICAL MONOSPACE SMALL J +]; +assert.sameValue(softDotted.length, 46, "Total code points with Soft_Dotted property"); + +function charInfo(ch) { + function hexString(n) { + var s = n.toString(16).toUpperCase(); + return "0000".slice(s.length) + s; + } + + if (ch.length === 1) { + return "U+" + hexString(ch.charCodeAt(0)); + } + var high = ch.charCodeAt(0); + var low = ch.charCodeAt(1); + var codePoint = ((high << 10) + low) + (0x10000 - (0xD800 << 10) - 0xDC00); + return "U+" + hexString(codePoint) + " = " + hexString(high) + " " + hexString(low); +} + + +// COMBINING DOT ABOVE (U+0307) removed when preceded by Soft_Dotted. +// Character directly preceded by Soft_Dotted. +for (var i = 0; i < softDotted.length; ++i) { + assert.sameValue( + (softDotted[i] + "\u0307").toLocaleUpperCase("lt"), + softDotted[i].toLocaleUpperCase("und"), + "COMBINING DOT ABOVE preceded by Soft_Dotted (" + charInfo(softDotted[i]) + ")" + ); +} + + +// COMBINING DOT ABOVE (U+0307) removed if preceded by Soft_Dotted. +// Character not directly preceded by Soft_Dotted. +// - COMBINING DOT BELOW (U+0323), combining class 220 (Below) +for (var i = 0; i < softDotted.length; ++i) { + assert.sameValue( + (softDotted[i] + "\u0323\u0307").toLocaleUpperCase("lt"), + softDotted[i].toLocaleUpperCase("und") + "\u0323", + "COMBINING DOT ABOVE preceded by Soft_Dotted (" + charInfo(softDotted[i]) + "), COMBINING DOT BELOW" + ); +} + + +// COMBINING DOT ABOVE removed if preceded by Soft_Dotted. +// Character not directly preceded by Soft_Dotted. +// - PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE (U+101FD = D800 DDFD), combining class 220 (Below) +for (var i = 0; i < softDotted.length; ++i) { + assert.sameValue( + (softDotted[i] + "\uD800\uDDFD\u0307").toLocaleUpperCase("lt"), + softDotted[i].toLocaleUpperCase("und") + "\uD800\uDDFD", + "COMBINING DOT ABOVE preceded by Soft_Dotted (" + charInfo(softDotted[i]) + "), PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Turkish.js b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Turkish.js new file mode 100644 index 0000000000..12597a407a --- /dev/null +++ b/js/src/tests/test262/intl402/String/prototype/toLocaleUpperCase/special_casing_Turkish.js @@ -0,0 +1,47 @@ +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Check if String.prototype.toLocaleUpperCase supports language-sensitive mappings defined in SpecialCasings (Turkish) +info: | + The result must be derived according to the case mappings in the Unicode character database (this explicitly + includes not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it). +es5id: 15.5.4.16 +es6id: 21.1.3.21 +---*/ + +// SpecialCasing.txt, conditional, language-sensitive mappings (Turkish). + +// LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130) not changed when uppercasing. +assert.sameValue( + "\u0130".toLocaleUpperCase("tr"), + "\u0130", + "LATIN CAPITAL LETTER I WITH DOT ABOVE" +); + + +// LATIN CAPITAL LETTER I not changed when uppercasing. +assert.sameValue( + "I".toLocaleUpperCase("tr"), + "I", + "LATIN CAPITAL LETTER I" +); + + +// LATIN SMALL LETTER I changed to LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130) when uppercasing. +assert.sameValue( + "i".toLocaleUpperCase("tr"), + "\u0130", + "LATIN SMALL LETTER I" +); + + +// LATIN SMALL LETTER DOTLESS I (U+0131) changed to LATIN CAPITAL LETTER I when uppercasing. +assert.sameValue( + "\u0131".toLocaleUpperCase("tr"), + "I", + "LATIN SMALL LETTER DOTLESS I" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/String/shell.js b/js/src/tests/test262/intl402/String/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/String/shell.js diff --git a/js/src/tests/test262/intl402/TypedArray/browser.js b/js/src/tests/test262/intl402/TypedArray/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/TypedArray/browser.js diff --git a/js/src/tests/test262/intl402/TypedArray/prototype/browser.js b/js/src/tests/test262/intl402/TypedArray/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/TypedArray/prototype/browser.js diff --git a/js/src/tests/test262/intl402/TypedArray/prototype/shell.js b/js/src/tests/test262/intl402/TypedArray/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/TypedArray/prototype/shell.js diff --git a/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/browser.js b/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/browser.js diff --git a/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/calls-toLocaleString-number-elements.js b/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/calls-toLocaleString-number-elements.js new file mode 100644 index 0000000000..c6b895e5db --- /dev/null +++ b/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/calls-toLocaleString-number-elements.js @@ -0,0 +1,25 @@ +// Copyright (C) 2018 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-array.prototype.tolocalestring +description: > + Ensure "toLocaleString" is called with locale and options on number elements. +includes: [testTypedArray.js] +features: [TypedArray] +---*/ + +var n = 0; + +var locale = "th-u-nu-thai"; +var options = { + minimumFractionDigits: 3 +}; + +var expected = n.toLocaleString(locale, options); + +testWithTypedArrayConstructors(function(TA) { + assert.sameValue(new TA([n]).toLocaleString(locale, options), expected); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/shell.js b/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/shell.js new file mode 100644 index 0000000000..e9580b3113 --- /dev/null +++ b/js/src/tests/test262/intl402/TypedArray/prototype/toLocaleString/shell.js @@ -0,0 +1,124 @@ +// GENERATED, DO NOT EDIT +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/intl402/TypedArray/shell.js b/js/src/tests/test262/intl402/TypedArray/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/TypedArray/shell.js diff --git a/js/src/tests/test262/intl402/browser.js b/js/src/tests/test262/intl402/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/intl402/browser.js diff --git a/js/src/tests/test262/intl402/constructors-string-and-single-element-array.js b/js/src/tests/test262/intl402/constructors-string-and-single-element-array.js new file mode 100644 index 0000000000..a73c7581c9 --- /dev/null +++ b/js/src/tests/test262/intl402/constructors-string-and-single-element-array.js @@ -0,0 +1,73 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.1_3 +description: > + Tests that a single string instead of a locale list is treated as + the locale list containing that string. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var validAndInvalidLanguageTags = [ + "de", // ISO 639 language code + "de-DE", // + ISO 3166-1 country code + "DE-de", // tags are case-insensitive + "cmn", // ISO 639 language code + "cmn-Hans", // + script code + "CMN-hANS", // tags are case-insensitive + "cmn-hans-cn", // + ISO 3166-1 country code + "es-419", // + UN M.49 region code + "es-419-u-nu-latn-cu-bob", // + Unicode locale extension sequence + "i-klingon", // grandfathered tag + "cmn-hans-cn-t-ca-u-ca-x-t-u", // singleton subtags can also be used as private use subtags + "de-gregory-u-ca-gregory", // variant and extension subtags may be the same + "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", + "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 +]; + +testWithIntlConstructors(function (Constructor) { + validAndInvalidLanguageTags.forEach(function (locale) { + var obj1, obj2, locale1, locale2, error1, error2; + try { + obj1 = new Constructor(locale); + locale1 = obj1.resolvedOptions().locale; + } catch (e) { + error1 = e; + } + try { + obj2 = new Constructor([locale]); + locale2 = obj2.resolvedOptions().locale; + } catch (e) { + error2 = e; + } + + assert.sameValue((error1 === undefined), (error2 === undefined), "Single locale string " + locale + " was " + (error1 === undefined ? "accepted" : "rejected") + ", but locale list containing that string wasn't."); + if (error1 === undefined) { + assert.sameValue(locale1, locale2, "Single locale string " + locale + " results in " + locale1 + ", but locale list [" + locale + "] results in " + locale2 + "."); + } else { + assert.sameValue(error1.name, error2.name, "Single locale string " + locale + " results in error " + error1.name + ", but locale list [" + locale + "] results in error " + error2.name + "."); + } + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/constructors-taint-Object-prototype-2.js b/js/src/tests/test262/intl402/constructors-taint-Object-prototype-2.js new file mode 100644 index 0000000000..b2c829293c --- /dev/null +++ b/js/src/tests/test262/intl402/constructors-taint-Object-prototype-2.js @@ -0,0 +1,20 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.5_6 +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintProperties(["dataLocale", "nu", "ca", "co", "locale"]); + +testWithIntlConstructors(function (Constructor) { + var locale = new Constructor(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; + assert(isCanonicalizedStructurallyValidLanguageTag(locale), "Constructor returns invalid locale " + locale + "."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/constructors-taint-Object-prototype.js b/js/src/tests/test262/intl402/constructors-taint-Object-prototype.js new file mode 100644 index 0000000000..5363296a83 --- /dev/null +++ b/js/src/tests/test262/intl402/constructors-taint-Object-prototype.js @@ -0,0 +1,20 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.3_5 +description: > + Tests that the behavior of a Record is not affected by + adversarial changes to Object.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintProperties(["locale", "extension", "extensionIndex"]); + +testWithIntlConstructors(function (Constructor) { + var locale = new Constructor(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale; + assert(isCanonicalizedStructurallyValidLanguageTag(locale), "Constructor returns invalid locale " + locale + "."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/default-locale-is-canonicalized.js b/js/src/tests/test262/intl402/default-locale-is-canonicalized.js new file mode 100644 index 0000000000..36a31b2ce2 --- /dev/null +++ b/js/src/tests/test262/intl402/default-locale-is-canonicalized.js @@ -0,0 +1,18 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.2.4 +description: > + Tests that the default locale is a String value representing the + structurally valid and canonicalized BCP 47 language tag. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var defaultLocale = new Constructor().resolvedOptions().locale; + assert(isCanonicalizedStructurallyValidLanguageTag(defaultLocale), "Default locale \"" + defaultLocale + "\" is not canonicalized and structurally valid language tag."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/default-locale-is-supported.js b/js/src/tests/test262/intl402/default-locale-is-supported.js new file mode 100644 index 0000000000..27d55154b3 --- /dev/null +++ b/js/src/tests/test262/intl402/default-locale-is-supported.js @@ -0,0 +1,17 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.1_a +description: Tests that default locale is available. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var defaultLocale = new Constructor().resolvedOptions().locale; + var supportedLocales = Constructor.supportedLocalesOf([defaultLocale]); + assert.notSameValue(supportedLocales.indexOf(defaultLocale), -1, "Default locale is not reported as available."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/fallback-locales-are-supported.js b/js/src/tests/test262/intl402/fallback-locales-are-supported.js new file mode 100644 index 0000000000..37e22ba795 --- /dev/null +++ b/js/src/tests/test262/intl402/fallback-locales-are-supported.js @@ -0,0 +1,35 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.1_b +description: > + Tests that appropriate fallback locales are provided for + supported locales. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var info = getLocaleSupportInfo(Constructor); + for (var locale of info.supported) { + var match = /^([a-z]{2,3})(-[A-Z][a-z]{3})?(-(?:[A-Z]{2}|[0-9]{3}))?$/.exec(locale); + assert.notSameValue(match, null, "Locale " + locale + " is supported, but can't be parsed.") + + var [language, script, region] = match.slice(1); + + if (script !== undefined) { + var fallback = language + script; + assert(info.supported.includes(fallback) || info.byFallback.includes(fallback), + "Locale " + locale + " is supported, but fallback " + fallback + " isn't."); + } + + if (region !== undefined) { + var fallback = language + region; + assert(info.supported.includes(fallback) || info.byFallback.includes(fallback), + "Locale " + locale + " is supported, but fallback " + fallback + " isn't."); + } + } +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/language-tags-canonicalized.js b/js/src/tests/test262/intl402/language-tags-canonicalized.js new file mode 100644 index 0000000000..f3c4035142 --- /dev/null +++ b/js/src/tests/test262/intl402/language-tags-canonicalized.js @@ -0,0 +1,55 @@ +// Copyright 2011-2012 Norbert Lindenberg. All rights reserved. +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.2.3 +description: Tests that language tags are canonicalized in return values. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var canonicalizedTags = { + "de": ["de"], + "de-DE": ["de-DE", "de"], + "DE-de": ["de-DE", "de"], + "cmn": ["zh"], + "CMN-hANS": ["zh-Hans", "zh"], + "cmn-hans-cn": ["zh-Hans-CN", "zh-Hans", "zh"], + "es-419": ["es-419", "es"], + "es-419-u-nu-latn": ["es-419-u-nu-latn", "es-419", "es", "es-u-nu-latn"], + // -u-ca is incomplete, so it will not show up in resolvedOptions().locale + "cmn-hans-cn-u-ca-t-ca-x-t-u": ["zh-Hans-CN-t-ca-u-ca-x-t-u", "zh-Hans-CN-t-ca-x-t-u", "zh-Hans-CN-t-ca-x-t", "zh-Hans-CN-t-ca", "zh-Hans-CN", "zh-Hans", "zh"], + "de-gregory-u-ca-gregory": ["de-gregory-u-ca-gregory", "de-gregory", "de-u-ca-gregory", "de"], + "sgn-GR": ["gss"], + "ji": ["yi"], + "de-DD": ["de-DE", "de"], + "in": ["id"], +}; + +// make sure the data above is correct +Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) { + canonicalizedTags[tag].forEach(function (canonicalTag) { + assert(isCanonicalizedStructurallyValidLanguageTag(canonicalTag), "Test data \"" + canonicalTag + "\" is not canonicalized and structurally valid language tag."); + }); +}); + +// now the actual test +testWithIntlConstructors(function (Constructor) { + var defaultLocale = new Constructor().resolvedOptions().locale; + Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) { + // use lookup locale matcher to keep the set of possible return values predictable + + // Variant 1: construct an object and see whether its locale is canonicalized. + // In this variant, shortened forms or the default locale may be returned + var object = new Constructor([tag], { localeMatcher: "lookup" }); + var locale = object.resolvedOptions().locale; + assert(canonicalizedTags[tag].indexOf(locale) !== -1 || locale === defaultLocale, "For " + tag + " got " + locale + "; expected one of " + canonicalizedTags[tag].join(", ") + "."); + + // Variant 2: get the supported locales. If the tag is supported, it should be returned canonicalized but unshortened + var supported = Constructor.supportedLocalesOf([tag]); + assert(supported.length === 0 || supported[0] === canonicalizedTags[tag][0], "For " + tag + " got " + supported[0] + "; expected " + canonicalizedTags[tag][0] + "."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/language-tags-invalid.js b/js/src/tests/test262/intl402/language-tags-invalid.js new file mode 100644 index 0000000000..0579ed24c3 --- /dev/null +++ b/js/src/tests/test262/intl402/language-tags-invalid.js @@ -0,0 +1,24 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.2.2_c +description: > + Tests that language tags with invalid subtag sequences are not + accepted. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var invalidLanguageTags = getInvalidLanguageTags(); + +testWithIntlConstructors(function (Constructor) { + invalidLanguageTags.forEach(function (tag) { + // this must throw an exception for an invalid language tag + assert.throws(RangeError, function() { + var obj = new Constructor([tag]); + }, "Invalid language tag " + tag + " was not rejected."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/language-tags-valid.js b/js/src/tests/test262/intl402/language-tags-valid.js new file mode 100644 index 0000000000..f9a7372d52 --- /dev/null +++ b/js/src/tests/test262/intl402/language-tags-valid.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.2.2_a +description: Tests that structurally valid language tags are accepted. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var validLanguageTags = [ + "de", // ISO 639 language code + "de-DE", // + ISO 3166-1 country code + "DE-de", // tags are case-insensitive + "cmn", // ISO 639 language code + "cmn-Hans", // + script code + "CMN-hANS", // tags are case-insensitive + "cmn-hans-cn", // + ISO 3166-1 country code + "es-419", // + UN M.49 region code + "es-419-u-nu-latn-cu-bob", // + Unicode locale extension sequence + "cmn-hans-cn-t-ca-u-ca-x-t-u", // singleton subtags can also be used as private use subtags + "de-gregory-u-ca-gregory", // variant and extension subtags may be the same + "aa-a-foo-x-a-foo-bar", // variant subtags can also be used as private use subtags +]; + +testWithIntlConstructors(function (Constructor) { + validLanguageTags.forEach(function (tag) { + // this must not throw an exception for a valid language tag + var obj = new Constructor([tag]); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/language-tags-with-underscore.js b/js/src/tests/test262/intl402/language-tags-with-underscore.js new file mode 100644 index 0000000000..912b2827e5 --- /dev/null +++ b/js/src/tests/test262/intl402/language-tags-with-underscore.js @@ -0,0 +1,35 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 6.2.2_b +description: Tests that language tags with "_" are not accepted. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var invalidLanguageTags = [ + "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", + "de-tester-Tester", // Case-insensitive duplicate variant subtag + "de-DE-u-kn-true-U-kn-true", // Case-insensitive duplicate singleton subtag +]; + +testWithIntlConstructors(function (Constructor) { + invalidLanguageTags.forEach(function (tag) { + // this must throw an exception for an invalid language tag + assert.throws(RangeError, function() { + var obj = new Constructor([tag]); + }, "Invalid language tag " + tag + " was not rejected."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/shell.js b/js/src/tests/test262/intl402/shell.js new file mode 100644 index 0000000000..410d6516d4 --- /dev/null +++ b/js/src/tests/test262/intl402/shell.js @@ -0,0 +1,2371 @@ +// 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 + - isValidNumberingSystem + - testNumberFormat + - getDateTimeComponents + - getDateTimeComponentValues + - isCanonicalizedStructurallyValidTimeZoneName +---*/ +/** + */ + + +/** + * @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) { + $ERROR("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() { + $ERROR("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 + * @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) { + 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], {localeMatcher: "lookup"}).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)) { + $ERROR("Option property " + property + " is returned, but shouldn't be."); + } + } else { + actual = obj.resolvedOptions()[property]; + if (isILD) { + if (actual !== undefined && values.indexOf(actual) === -1) { + $ERROR("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)) { + $ERROR("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) { + $ERROR("Invalid option value " + value + " for property " + property + " was not rejected."); + } else if (error.name !== "RangeError") { + $ERROR("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) { + $ERROR("Option fallback value " + fallback + " for property " + property + + " was not used; got " + actual + " instead."); + } + } else { + if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) { + $ERROR("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]) { + $ERROR("RegExp has unexpected property " + property + " with value " + + RegExp[property] + "."); + } + }); +} + + +/** + * 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) { + + // source: CLDR file common/bcp47/number.xml; version CLDR 36.1. + var numberingSystems = [ + "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", + "khmr", + "knda", + "lana", + "lanatham", + "laoo", + "latn", + "lepc", + "limb", + "mathbold", + "mathdbl", + "mathmono", + "mathsanb", + "mathsans", + "mlym", + "modi", + "mong", + "mroo", + "mtei", + "mymr", + "mymrshan", + "mymrtlng", + "native", + "newa", + "nkoo", + "olck", + "orya", + "osma", + "rohg", + "roman", + "romanlow", + "saur", + "shrd", + "sind", + "sinh", + "sora", + "sund", + "takr", + "talu", + "taml", + "tamldec", + "telu", + "thai", + "tirh", + "tibt", + "traditio", + "vaii", + "wara", + "wcho", + ]; + + 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: "꤀꤁꤂꤃꤄꤅꤆꤇꤈꤉", + khmr: "០១២៣៤៥៦៧៨៩", + knda: "೦೧೨೩೪೫೬೭೮೯", + lana: "᪀᪁᪂᪃᪄᪅᪆᪇᪈᪉", + lanatham: "᪐᪑᪒᪓᪔᪕᪖᪗᪘᪙", + laoo: "໐໑໒໓໔໕໖໗໘໙", + latn: "0123456789", + lepc: "᱀᱁᱂᱃᱄᱅᱆᱇᱈᱉", + limb: "\u1946\u1947\u1948\u1949\u194A\u194B\u194C\u194D\u194E\u194F", + 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: "௦௧௨௩௪௫௬௭௮௯", + telu: "౦౧౨౩౪౫౬౭౮౯", + thai: "๐๑๒๓๔๕๖๗๘๙", + tibt: "༠༡༢༣༤༥༦༧༨༩", + tirh: "𑓐𑓑𑓒𑓓𑓔𑓕𑓖𑓗𑓘𑓙", + vaii: "꘠꘡꘢꘣꘤꘥꘦꘧꘨꘩", + wara: "𑣠𑣡𑣢𑣣𑣤𑣥𑣦𑣧𑣨𑣩", + wcho: "𞋰𞋱𞋲𞋳𞋴𞋵𞋶𞋷𞋸𞋹", +}; + + +/** + * 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) { + $ERROR("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) { + $ERROR("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) { + $ERROR("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); +} diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-consistent-with-resolvedOptions.js b/js/src/tests/test262/intl402/supportedLocalesOf-consistent-with-resolvedOptions.js new file mode 100644 index 0000000000..6d68b584b8 --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-consistent-with-resolvedOptions.js @@ -0,0 +1,37 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.2 +description: > + Tests that locales that are reported by resolvedOptions are also + reported by supportedLocalesOf. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var info = getLocaleSupportInfo(Constructor); + // this test should work equally for both matching algorithms + ["lookup", "best fit"].forEach(function (matcher) { + var supportedByConstructor = info.supported.concat(info.byFallback); + var supported = Constructor.supportedLocalesOf(supportedByConstructor, + {localeMatcher: matcher}); + // we could check the length first, but it's probably more interesting which locales are missing + var i = 0; + var limit = Math.min(supportedByConstructor.length, supported.length); + while (i < limit && supportedByConstructor[i] === supported[i]) { + i++; + } + assert.sameValue(i < supportedByConstructor.length, false, "Locale " + supportedByConstructor[i] + " is returned by resolvedOptions but not by supportedLocalesOf."); + assert.sameValue(i < supported.length, false, "Locale " + supported[i] + " is returned by supportedLocalesOf but not by resolvedOptions."); + }); + + // this test is only valid for lookup - best fit may find additional locales supported + var unsupportedByConstructor = info.unsupported; + var supported = Constructor.supportedLocalesOf(unsupportedByConstructor, + {localeMatcher: "lookup"}); + assert.sameValue(supported.length > 0, false, "Locale " + supported[0] + " is returned by supportedLocalesOf but not by resolvedOptions."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-default-locale-and-zxx-locale.js b/js/src/tests/test262/intl402/supportedLocalesOf-default-locale-and-zxx-locale.js new file mode 100644 index 0000000000..456c669f5f --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-default-locale-and-zxx-locale.js @@ -0,0 +1,26 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.6_4_c +description: > + Tests that LookupSupportedLocales includes the default locale and + doesn't include the "no linguistic content" locale. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + // this test should work equally for both matching algorithms + ["lookup", "best fit"].forEach(function (matcher) { + var defaultLocale = new Constructor().resolvedOptions().locale; + var noLinguisticContent = "zxx"; + var supported = Constructor.supportedLocalesOf([defaultLocale, noLinguisticContent], + {localeMatcher: matcher}); + assert.notSameValue(supported.indexOf(defaultLocale), -1, "SupportedLocales didn't return default locale with matcher " + matcher + "."); + assert.sameValue(supported.indexOf(noLinguisticContent), -1, "SupportedLocales returned the \"no linguistic content\" locale with matcher " + matcher + "."); + assert.sameValue(supported.length > 1, false, "SupportedLocales returned stray locales: " + supported.join(", ") + " with matcher " + matcher + "."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-duplicate-elements-removed.js b/js/src/tests/test262/intl402/supportedLocalesOf-duplicate-elements-removed.js new file mode 100644 index 0000000000..6b8d818d13 --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-duplicate-elements-removed.js @@ -0,0 +1,19 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.1_8_c_vi +description: > + Tests that canonicalization of locale lists removes duplicate + language tags. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var defaultLocale = new Constructor().resolvedOptions().locale; + var canonicalized = Constructor.supportedLocalesOf([defaultLocale, defaultLocale]); + assert.sameValue(canonicalized.length > 1, false, "Canonicalization didn't remove duplicate language tags from locale list."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-empty-and-undefined.js b/js/src/tests/test262/intl402/supportedLocalesOf-empty-and-undefined.js new file mode 100644 index 0000000000..2959f5ba7b --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-empty-and-undefined.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.1_1 +description: > + Tests that canonicalization of locale lists treats undefined and + empty lists the same. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var supportedForUndefined = Constructor.supportedLocalesOf(undefined); + var supportedForEmptyList = Constructor.supportedLocalesOf([]); + assert.sameValue(supportedForUndefined.length, supportedForEmptyList.length, "Supported locales differ between undefined and empty list input."); + // we don't compare the elements because length should be 0 - let's just verify that + assert.sameValue(supportedForUndefined.length, 0, "Internal test error: Assumption about length being 0 is invalid."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-locales-arg-coered-to-object.js b/js/src/tests/test262/intl402/supportedLocalesOf-locales-arg-coered-to-object.js new file mode 100644 index 0000000000..9abbeeae27 --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-locales-arg-coered-to-object.js @@ -0,0 +1,33 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.1_4 +description: > + Tests that non-objects are converted to objects before + canonicalization. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + // undefined is handled separately + + // null should result in a TypeError + assert.throws(TypeError, function() { + var supportedForNull = Constructor.supportedLocalesOf(null); + }, "Null as locale list was not rejected."); + + // let's use an empty list for comparison + var supportedForEmptyList = Constructor.supportedLocalesOf([]); + // we don't compare the elements because length should be 0 - let's just verify that + assert.sameValue(supportedForEmptyList.length, 0, "Internal test error: Assumption about length being 0 is invalid."); + + // most non-objects will be interpreted as empty lists because a missing length property is interpreted as 0 + var supportedForNumber = Constructor.supportedLocalesOf(5); + assert.sameValue(supportedForNumber.length, supportedForEmptyList.length, "Supported locales differ between numeric and empty list input."); + var supportedForBoolean = Constructor.supportedLocalesOf(true); + assert.sameValue(supportedForBoolean.length, supportedForEmptyList.length, "Supported locales differ between boolean and empty list input."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-locales-arg-empty-array.js b/js/src/tests/test262/intl402/supportedLocalesOf-locales-arg-empty-array.js new file mode 100644 index 0000000000..87009af4c8 --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-locales-arg-empty-array.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.6_4 +description: > + Tests that LookupSupportedLocales returns an empty list when + given an empty list. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + // this test should work equally for both matching algorithms + ["lookup", "best fit"].forEach(function (matcher) { + var supported = Constructor.supportedLocalesOf([], {localeMatcher: matcher}); + assert.sameValue(supported.length, 0, "SupportedLocales with matcher " + matcher + " returned a non-empty list for an empty list."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-returned-array-elements-are-not-frozen.js b/js/src/tests/test262/intl402/supportedLocalesOf-returned-array-elements-are-not-frozen.js new file mode 100644 index 0000000000..3055f0d71f --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-returned-array-elements-are-not-frozen.js @@ -0,0 +1,35 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.8_4 +description: > + Tests that the array returned by SupportedLocales is extensible, + writable and configurable. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +function testNormalProperty(obj, property) { + var desc = Object.getOwnPropertyDescriptor(obj, property); + assert.sameValue(desc.writable, true, "Property " + property + " of object returned by SupportedLocales is not writable."); + assert.sameValue(desc.configurable, true, "Property " + property + " of object returned by SupportedLocales is not configurable."); +} + +function testLengthProperty(obj, property) { + var desc = Object.getOwnPropertyDescriptor(obj, property); + assert.sameValue(desc.writable, true, "Property " + property + " of object returned by SupportedLocales is not writable."); + assert.sameValue(desc.configurable, false, "Property " + property + " of object returned by SupportedLocales is configurable."); +} + +testWithIntlConstructors(function (Constructor) { + var defaultLocale = new Constructor().resolvedOptions().locale; + var supported = Constructor.supportedLocalesOf([defaultLocale]); + assert(Object.isExtensible(supported), "Object returned by SupportedLocales is not extensible."); + for (var i = 0; i < supported.length; i++) { + testNormalProperty(supported, i); + } + testLengthProperty(supported, "length"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-taint-Array-2.js b/js/src/tests/test262/intl402/supportedLocalesOf-taint-Array-2.js new file mode 100644 index 0000000000..d21cf3d5e6 --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-taint-Array-2.js @@ -0,0 +1,25 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.6_2 +description: > + Tests that the behavior of a List is not affected by adversarial + changes to Array.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintArray(); + +testWithIntlConstructors(function (Constructor) { + // this test should work equally for both matching algorithms + ["lookup", "best fit"].forEach(function (matcher) { + var defaultLocale = new Constructor().resolvedOptions().locale; + var canonicalized = Constructor.supportedLocalesOf([defaultLocale, defaultLocale], + {localeMatcher: matcher}); + assert.sameValue(canonicalized.length > 1, false, "Canonicalization with matcher " + matcher + " didn't remove duplicate language tags from locale list."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-taint-Array.js b/js/src/tests/test262/intl402/supportedLocalesOf-taint-Array.js new file mode 100644 index 0000000000..ca9db65933 --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-taint-Array.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.1_2 +description: > + Tests that the behavior of a List is not affected by adversarial + changes to Array.prototype. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +taintArray(); + +testWithIntlConstructors(function (Constructor) { + var defaultLocale = new Constructor().resolvedOptions().locale; + var canonicalized = Constructor.supportedLocalesOf([defaultLocale, defaultLocale]); + assert.sameValue(canonicalized.length > 1, false, "Canonicalization didn't remove duplicate language tags from locale list."); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-test-option-localeMatcher.js b/js/src/tests/test262/intl402/supportedLocalesOf-test-option-localeMatcher.js new file mode 100644 index 0000000000..a29cb11742 --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-test-option-localeMatcher.js @@ -0,0 +1,27 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.8_1_c +description: Tests that the option localeMatcher is processed correctly. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var defaultLocale = new Constructor().resolvedOptions().locale; + + var validValues = [undefined, "lookup", "best fit", {toString: function () { return "lookup"; }}]; + validValues.forEach(function (value) { + var supported = Constructor.supportedLocalesOf([defaultLocale], {localeMatcher: value}); + }); + + var invalidValues = [null, 0, 5, NaN, true, false, "invalid"]; + invalidValues.forEach(function (value) { + assert.throws(RangeError, function() { + var supported = Constructor.supportedLocalesOf([defaultLocale], {localeMatcher: value}); + }, "Invalid localeMatcher value " + value + " was not rejected."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-throws-if-element-not-string-or-object.js b/js/src/tests/test262/intl402/supportedLocalesOf-throws-if-element-not-string-or-object.js new file mode 100644 index 0000000000..efcdd7d04c --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-throws-if-element-not-string-or-object.js @@ -0,0 +1,21 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.1_8_c_ii +description: Tests that values other than strings are not accepted as locales. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +var notStringOrObject = [undefined, null, true, false, 0, 5, -5, NaN]; + +testWithIntlConstructors(function (Constructor) { + notStringOrObject.forEach(function (value) { + assert.throws(TypeError, function() { + var supported = Constructor.supportedLocalesOf([value]); + }, "" + value + " as locale was not rejected."); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/intl402/supportedLocalesOf-unicode-extensions-ignored.js b/js/src/tests/test262/intl402/supportedLocalesOf-unicode-extensions-ignored.js new file mode 100644 index 0000000000..b269211e7c --- /dev/null +++ b/js/src/tests/test262/intl402/supportedLocalesOf-unicode-extensions-ignored.js @@ -0,0 +1,41 @@ +// Copyright 2012 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +es5id: 9.2.6_4_b +description: > + Tests that Unicode locale extension sequences do not affect + whether a locale is considered supported, but are reported back. +author: Norbert Lindenberg +includes: [testIntl.js] +---*/ + +testWithIntlConstructors(function (Constructor) { + var info = getLocaleSupportInfo(Constructor); + + // this test should work equally for both matching algorithms + ["lookup", "best fit"].forEach(function (matcher) { + var allLocales = info.supported.concat(info.byFallback, info.unsupported); + allLocales.forEach(function (locale) { + var validExtension = "-u-co-phonebk-nu-latn"; + var invalidExtension = "-u-nu-invalid"; + var supported1 = Constructor.supportedLocalesOf([locale], + {localeMatcher: matcher}); + var supported2 = Constructor.supportedLocalesOf([locale + validExtension], + {localeMatcher: matcher}); + var supported3 = Constructor.supportedLocalesOf([locale + invalidExtension], + {localeMatcher: matcher}); + if (supported1.length === 1) { + assert.sameValue(supported2.length, 1, "#1.1: Presence of Unicode locale extension sequence affects whether locale " + locale + " is considered supported with matcher " + matcher + "."); + assert.sameValue(supported3.length, 1, "#1.2: Presence of Unicode locale extension sequence affects whether locale " + locale + " is considered supported with matcher " + matcher + "."); + assert.sameValue(supported2[0], locale + validExtension, "#2.1: Unicode locale extension sequence is not correctly returned for locale " + locale + " with matcher " + matcher + "."); + assert.sameValue(supported3[0], locale + invalidExtension, "#2.2: Unicode locale extension sequence is not correctly returned for locale " + locale + " with matcher " + matcher + "."); + } else { + assert.sameValue(supported2.length, 0, "#3.1: Presence of Unicode locale extension sequence affects whether locale " + locale + " is considered supported with matcher " + matcher + "."); + assert.sameValue(supported3.length, 0, "#3.2: Presence of Unicode locale extension sequence affects whether locale " + locale + " is considered supported with matcher " + matcher + "."); + } + }); + }); +}); + +reportCompare(0, 0); |