diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..3fef34e81a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +root = true + +[*] +charset = utf-8 +indent_style = tab +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[{README.md,package.json,.travis.yml,*.sh,*.js}] +indent_style = space +indent_size = 2 + +[{.jshintrc,*.py}] +indent_style = space +indent_size = 4 diff --git a/harness/Date_constants.js b/harness/Date_constants.js index b9e072f533..66589c4cb3 100644 --- a/harness/Date_constants.js +++ b/harness/Date_constants.js @@ -35,49 +35,50 @@ var $LocalTZ, $DST_end_minutes; (function () { - /** - * Finds the first date, starting from |start|, where |predicate| - * holds. - */ - var findNearestDateBefore = function(start, predicate) { - var current = start; - var month = 1000 * 60 * 60 * 24 * 30; - for (var step = month; step > 0; step = Math.floor(step / 3)) { - if (!predicate(current)) { - while (!predicate(current)) - current = new Date(current.getTime() + step); - current = new Date(current.getTime() - step); - } - } + /** + * Finds the first date, starting from |start|, where |predicate| + * holds. + */ + var findNearestDateBefore = function(start, predicate) { + var current = start; + var month = 1000 * 60 * 60 * 24 * 30; + for (var step = month; step > 0; step = Math.floor(step / 3)) { + if (!predicate(current)) { while (!predicate(current)) { - current = new Date(current.getTime() + 1); + current = new Date(current.getTime() + step); + current = new Date(current.getTime() - step); } - return current; - }; + } + } + while (!predicate(current)) { + current = new Date(current.getTime() + 1); + } + return current; + }; - var juneDate = new Date(2000, 5, 20, 0, 0, 0, 0); - var decemberDate = new Date(2000, 11, 20, 0, 0, 0, 0); - var juneOffset = juneDate.getTimezoneOffset(); - var decemberOffset = decemberDate.getTimezoneOffset(); - var isSouthernHemisphere = (juneOffset > decemberOffset); - var winterTime = isSouthernHemisphere ? juneDate : decemberDate; - var summerTime = isSouthernHemisphere ? decemberDate : juneDate; + var juneDate = new Date(2000, 5, 20, 0, 0, 0, 0); + var decemberDate = new Date(2000, 11, 20, 0, 0, 0, 0); + var juneOffset = juneDate.getTimezoneOffset(); + var decemberOffset = decemberDate.getTimezoneOffset(); + var isSouthernHemisphere = (juneOffset > decemberOffset); + var winterTime = isSouthernHemisphere ? juneDate : decemberDate; + var summerTime = isSouthernHemisphere ? decemberDate : juneDate; - var dstStart = findNearestDateBefore(winterTime, function (date) { - return date.getTimezoneOffset() == summerTime.getTimezoneOffset(); - }); - $DST_start_month = dstStart.getMonth(); - $DST_start_sunday = dstStart.getDate() > 15 ? '"last"' : '"first"'; - $DST_start_hour = dstStart.getHours(); - $DST_start_minutes = dstStart.getMinutes(); + var dstStart = findNearestDateBefore(winterTime, function (date) { + return date.getTimezoneOffset() == summerTime.getTimezoneOffset(); + }); + $DST_start_month = dstStart.getMonth(); + $DST_start_sunday = dstStart.getDate() > 15 ? '"last"' : '"first"'; + $DST_start_hour = dstStart.getHours(); + $DST_start_minutes = dstStart.getMinutes(); - var dstEnd = findNearestDateBefore(summerTime, function (date) { - return date.getTimezoneOffset() == winterTime.getTimezoneOffset(); - }); - $DST_end_month = dstEnd.getMonth(); - $DST_end_sunday = dstEnd.getDate() > 15 ? '"last"' : '"first"'; - $DST_end_hour = dstEnd.getHours(); - $DST_end_minutes = dstEnd.getMinutes(); + var dstEnd = findNearestDateBefore(summerTime, function (date) { + return date.getTimezoneOffset() == winterTime.getTimezoneOffset(); + }); + $DST_end_month = dstEnd.getMonth(); + $DST_end_sunday = dstEnd.getDate() > 15 ? '"last"' : '"first"'; + $DST_end_hour = dstEnd.getHours(); + $DST_end_minutes = dstEnd.getMinutes(); - return; + return; })(); diff --git a/harness/PromiseHelper.js b/harness/PromiseHelper.js index 59ba0c74c9..963b93f441 100644 --- a/harness/PromiseHelper.js +++ b/harness/PromiseHelper.js @@ -1,9 +1,9 @@ //----------------------------------------------------------------------------- function checkSequence(arr, message) { - arr.forEach(function(e, i) { - if (e !== (i+1)) { - $ERROR((message ? message : "Steps in unexpected sequence:") + - " '" + arr.join(',') + "'"); - } - }); + arr.forEach(function(e, i) { + if (e !== (i+1)) { + $ERROR((message ? message : "Steps in unexpected sequence:") + + " '" + arr.join(',') + "'"); + } + }); } diff --git a/harness/arrayContains.js b/harness/arrayContains.js index b295de5f3f..47af86b8f2 100644 --- a/harness/arrayContains.js +++ b/harness/arrayContains.js @@ -1,17 +1,17 @@ //----------------------------------------------------------------------------- function arrayContains(arr, expected) { - var found; - for (var i = 0; i < expected.length; i++) { - found = false; - for (var j = 0; j < arr.length; j++) { - if (expected[i] === arr[j]) { - found = true; - break; - } - } - if (!found) { - return false; - } + var found; + for (var i = 0; i < expected.length; i++) { + found = false; + for (var j = 0; j < arr.length; j++) { + if (expected[i] === arr[j]) { + found = true; + break; + } } - return true; + if (!found) { + return false; + } + } + return true; } diff --git a/harness/assert.js b/harness/assert.js index 1cf2c9a489..545b965f26 100644 --- a/harness/assert.js +++ b/harness/assert.js @@ -1,81 +1,81 @@ function assert(mustBeTrue, message) { - if (mustBeTrue === true) { - return; - } + if (mustBeTrue === true) { + return; + } - if (message === undefined) { - message = 'Expected true but got ' + String(mustBeTrue); - } - $ERROR(message); + if (message === undefined) { + message = 'Expected true but got ' + String(mustBeTrue); + } + $ERROR(message); } assert._isSameValue = function (a, b) { - if (a === b) { - // Handle +/-0 vs. -/+0 - return a !== 0 || 1 / a === 1 / b; - } + if (a === b) { + // Handle +/-0 vs. -/+0 + return a !== 0 || 1 / a === 1 / b; + } - // Handle NaN vs. NaN - return a !== a && b !== b; + // Handle NaN vs. NaN + return a !== a && b !== b; }; assert.sameValue = function (actual, expected, message) { - if (assert._isSameValue(actual, expected)) { - return; - } + if (assert._isSameValue(actual, expected)) { + return; + } - if (message === undefined) { - message = ''; - } else { - message += ' '; - } + if (message === undefined) { + message = ''; + } else { + message += ' '; + } - message += 'Expected SameValue(«' + String(actual) + '», «' + String(expected) + '») to be true'; + message += 'Expected SameValue(«' + String(actual) + '», «' + String(expected) + '») to be true'; - $ERROR(message); + $ERROR(message); }; assert.notSameValue = function (actual, unexpected, message) { - if (!assert._isSameValue(actual, unexpected)) { - return; - } + if (!assert._isSameValue(actual, unexpected)) { + return; + } - if (message === undefined) { - message = ''; - } else { - message += ' '; - } + if (message === undefined) { + message = ''; + } else { + message += ' '; + } - message += 'Expected SameValue(«' + String(actual) + '», «' + String(unexpected) + '») to be false'; + message += 'Expected SameValue(«' + String(actual) + '», «' + String(unexpected) + '») to be false'; - $ERROR(message); + $ERROR(message); }; assert.throws = function (expectedErrorConstructor, func, message) { - if (typeof func !== "function") { - $ERROR('assert.throws requires two arguments: the error constructor ' + - 'and a function to run'); - return; - } - if (message === undefined) { - message = ''; - } else { - message += ' '; - } + if (typeof func !== "function") { + $ERROR('assert.throws requires two arguments: the error constructor ' + + 'and a function to run'); + return; + } + if (message === undefined) { + message = ''; + } else { + message += ' '; + } - try { - func(); - } catch (thrown) { - if (typeof thrown !== 'object' || thrown === null) { - message += 'Thrown value was not an object!'; - $ERROR(message); - } else if (thrown.constructor !== expectedErrorConstructor) { - message += 'Expected a ' + expectedErrorConstructor.name + ' but got a ' + thrown.constructor.name; - $ERROR(message); - } - return; + try { + func(); + } catch (thrown) { + if (typeof thrown !== 'object' || thrown === null) { + message += 'Thrown value was not an object!'; + $ERROR(message); + } else if (thrown.constructor !== expectedErrorConstructor) { + message += 'Expected a ' + expectedErrorConstructor.name + ' but got a ' + thrown.constructor.name; + $ERROR(message); } + return; + } - message += 'Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all'; - $ERROR(message); + message += 'Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all'; + $ERROR(message); }; diff --git a/harness/cth.js b/harness/cth.js index fe30153194..e478554d71 100644 --- a/harness/cth.js +++ b/harness/cth.js @@ -1,36 +1,36 @@ -/// Copyright (c) 2012 Ecma International. All rights reserved. -/// This code is governed by the BSD license found in the LICENSE file. - -function testRun(id, path, description, codeString, result, error) { - if (result!=="pass") { - throw new Error("Test '" + path + "'failed: " + error); - } -} - -// define a default `print` function for async tests where there is no -// global `print` -var print; - -// in node use console.log -if (typeof console === "object") { - print = function () { - var args = Array.prototype.slice.call(arguments); - console.log(args.join(" ")); - }; -} - -// in WScript, use WScript.Echo -if (typeof WScript === "object") { - print = function () { - var args = Array.prototype.slice.call(arguments); - WScript.Echo(args.join(" ")); - }; - - // also override $ERROR to force a nonzero exit code exit - // TODO? report syntax errors - var oldError = $ERROR; - $ERROR = function (message) { - print("Test262 Error: " + message); - WScript.Quit(1); - }; -} +/// Copyright (c) 2012 Ecma International. All rights reserved. +/// This code is governed by the BSD license found in the LICENSE file. + +function testRun(id, path, description, codeString, result, error) { + if (result!=="pass") { + throw new Error("Test '" + path + "'failed: " + error); + } +} + +// define a default `print` function for async tests where there is no +// global `print` +var print; + +// in node use console.log +if (typeof console === "object") { + print = function () { + var args = Array.prototype.slice.call(arguments); + console.log(args.join(" ")); + }; +} + +// in WScript, use WScript.Echo +if (typeof WScript === "object") { + print = function () { + var args = Array.prototype.slice.call(arguments); + WScript.Echo(args.join(" ")); + }; + + // also override $ERROR to force a nonzero exit code exit + // TODO? report syntax errors + var oldError = $ERROR; + $ERROR = function (message) { + print("Test262 Error: " + message); + WScript.Quit(1); + }; +} diff --git a/harness/doneprintHandle.js b/harness/doneprintHandle.js index 101a36bd49..e5e43821d9 100644 --- a/harness/doneprintHandle.js +++ b/harness/doneprintHandle.js @@ -1,10 +1,10 @@ function __consolePrintHandle__(msg){ - print(msg); + print(msg); } function $DONE(){ - if(!arguments[0]) - __consolePrintHandle__('Test262:AsyncTestComplete'); - else - __consolePrintHandle__('Error: ' + arguments[0]); + if(!arguments[0]) + __consolePrintHandle__('Test262:AsyncTestComplete'); + else + __consolePrintHandle__('Error: ' + arguments[0]); } diff --git a/harness/fnGlobalObject.js b/harness/fnGlobalObject.js index 0a68c2da73..9b39cdd9e0 100644 --- a/harness/fnGlobalObject.js +++ b/harness/fnGlobalObject.js @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- var __globalObject = Function("return this;")(); function fnGlobalObject() { - return __globalObject; + return __globalObject; } diff --git a/harness/propertyHelper.js b/harness/propertyHelper.js index 5bb1ed4157..6d67e40511 100644 --- a/harness/propertyHelper.js +++ b/harness/propertyHelper.js @@ -1,127 +1,126 @@ function isConfigurable(obj, name) { - try { - delete obj[name]; - } catch (e) { - if (!(e instanceof TypeError)) { - $ERROR("Expected TypeError, got " + e); - } + try { + delete obj[name]; + } catch (e) { + if (!(e instanceof TypeError)) { + $ERROR("Expected TypeError, got " + e); } - return !Object.prototype.hasOwnProperty.call(obj, name); + } + return !Object.prototype.hasOwnProperty.call(obj, name); } function isEnumerable(obj, name) { - var stringCheck; - - if (typeof name === "string") { - for (var x in obj) { - if (x === name) { - stringCheck = true; - break; - } - } - } else { - // skip it if name is not string, works for Symbol names. - stringCheck = true; - } + var stringCheck; - return stringCheck && - Object.prototype.hasOwnProperty.call(obj, name) && - Object.prototype.propertyIsEnumerable.call(obj, name); + if (typeof name === "string") { + for (var x in obj) { + if (x === name) { + stringCheck = true; + break; + } + } + } else { + // skip it if name is not string, works for Symbol names. + stringCheck = true; + } + + return stringCheck && + Object.prototype.hasOwnProperty.call(obj, name) && + Object.prototype.propertyIsEnumerable.call(obj, name); } function isEqualTo(obj, name, expectedValue) { - var actualValue = obj[name]; + var actualValue = obj[name]; - return assert._isSameValue(actualValue, expectedValue); + return assert._isSameValue(actualValue, expectedValue); } function isWritable(obj, name, verifyProp, value) { - var newValue = value || "unlikelyValue"; - var hadValue = Object.prototype.hasOwnProperty.call(obj, name); - var oldValue = obj[name]; - var writeSucceeded; + var newValue = value || "unlikelyValue"; + var hadValue = Object.prototype.hasOwnProperty.call(obj, name); + var oldValue = obj[name]; + var writeSucceeded; - try { - obj[name] = newValue; - } catch (e) { - if (!(e instanceof TypeError)) { - $ERROR("Expected TypeError, got " + e); - } + try { + obj[name] = newValue; + } catch (e) { + if (!(e instanceof TypeError)) { + $ERROR("Expected TypeError, got " + e); } + } - writeSucceeded = isEqualTo(obj, verifyProp || name, newValue); + writeSucceeded = isEqualTo(obj, verifyProp || name, newValue); - // Revert the change only if it was successful (in other cases, reverting - // is unnecessary and may trigger exceptions for certain property - // configurations) - if (writeSucceeded) { - if (hadValue) { - obj[name] = oldValue; - } else { - delete obj[name]; - } + // Revert the change only if it was successful (in other cases, reverting + // is unnecessary and may trigger exceptions for certain property + // configurations) + if (writeSucceeded) { + if (hadValue) { + obj[name] = oldValue; + } else { + delete obj[name]; } + } - return writeSucceeded; + return writeSucceeded; } function verifyEqualTo(obj, name, value) { - if (!isEqualTo(obj, name, value)) { - $ERROR("Expected obj[" + String(name) + "] to equal " + value + - ", actually " + obj[name]); - } + if (!isEqualTo(obj, name, value)) { + $ERROR("Expected obj[" + String(name) + "] to equal " + value + + ", actually " + obj[name]); + } } function verifyWritable(obj, name, verifyProp, value) { - if (!verifyProp) { - assert(Object.getOwnPropertyDescriptor(obj, name).writable, - "Expected obj[" + String(name) + "] to have writable:true."); - } - if (!isWritable(obj, name, verifyProp, value)) { - $ERROR("Expected obj[" + String(name) + "] to be writable, but was not."); - } + if (!verifyProp) { + assert(Object.getOwnPropertyDescriptor(obj, name).writable, + "Expected obj[" + String(name) + "] to have writable:true."); + } + if (!isWritable(obj, name, verifyProp, value)) { + $ERROR("Expected obj[" + String(name) + "] to be writable, but was not."); + } } function verifyNotWritable(obj, name, verifyProp, value) { - if (!verifyProp) { - assert(!Object.getOwnPropertyDescriptor(obj, name).writable, - "Expected obj[" + String(name) + "] to have writable:false."); - } - if (isWritable(obj, name, verifyProp)) { - $ERROR("Expected obj[" + String(name) + "] NOT to be writable, but was."); - } + if (!verifyProp) { + assert(!Object.getOwnPropertyDescriptor(obj, name).writable, + "Expected obj[" + String(name) + "] to have writable:false."); + } + if (isWritable(obj, name, verifyProp)) { + $ERROR("Expected obj[" + String(name) + "] NOT to be writable, but was."); + } } function verifyEnumerable(obj, name) { - assert(Object.getOwnPropertyDescriptor(obj, name).enumerable, - "Expected obj[" + String(name) + "] to have enumerable:true."); - if (!isEnumerable(obj, name)) { - $ERROR("Expected obj[" + String(name) + "] to be enumerable, but was not."); - } + assert(Object.getOwnPropertyDescriptor(obj, name).enumerable, + "Expected obj[" + String(name) + "] to have enumerable:true."); + if (!isEnumerable(obj, name)) { + $ERROR("Expected obj[" + String(name) + "] to be enumerable, but was not."); + } } function verifyNotEnumerable(obj, name) { - assert(!Object.getOwnPropertyDescriptor(obj, name).enumerable, - "Expected obj[" + String(name) + "] to have enumerable:false."); - if (isEnumerable(obj, name)) { - $ERROR("Expected obj[" + String(name) + "] NOT to be enumerable, but was."); - } + assert(!Object.getOwnPropertyDescriptor(obj, name).enumerable, + "Expected obj[" + String(name) + "] to have enumerable:false."); + if (isEnumerable(obj, name)) { + $ERROR("Expected obj[" + String(name) + "] NOT to be enumerable, but was."); + } } function verifyConfigurable(obj, name) { - assert(Object.getOwnPropertyDescriptor(obj, name).configurable, - "Expected obj[" + String(name) + "] to have configurable:true."); - if (!isConfigurable(obj, name)) { - $ERROR("Expected obj[" + String(name) + "] to be configurable, but was not."); - } + assert(Object.getOwnPropertyDescriptor(obj, name).configurable, + "Expected obj[" + String(name) + "] to have configurable:true."); + if (!isConfigurable(obj, name)) { + $ERROR("Expected obj[" + String(name) + "] to be configurable, but was not."); + } } function verifyNotConfigurable(obj, name) { - assert(!Object.getOwnPropertyDescriptor(obj, name).configurable, - "Expected obj[" + String(name) + "] to have configurable:false."); - if (isConfigurable(obj, name)) { - $ERROR("Expected obj[" + String(name) + "] NOT to be configurable, but was."); - } + assert(!Object.getOwnPropertyDescriptor(obj, name).configurable, + "Expected obj[" + String(name) + "] to have configurable:false."); + if (isConfigurable(obj, name)) { + $ERROR("Expected obj[" + String(name) + "] NOT to be configurable, but was."); + } } - diff --git a/harness/proxyTrapsHelper.js b/harness/proxyTrapsHelper.js index 04a504b85e..402684cfbc 100644 --- a/harness/proxyTrapsHelper.js +++ b/harness/proxyTrapsHelper.js @@ -1,22 +1,22 @@ function allowProxyTraps(overrides) { - function throwTest262Error(msg) { - return function () { throw new Test262Error(msg); }; - } - if (!overrides) { overrides = {}; } - return { - getPrototypeOf: overrides.getPrototypeOf || throwTest262Error('[[GetPrototypeOf]] trap called'), - setPrototypeOf: overrides.setPrototypeOf || throwTest262Error('[[SetPrototypeOf]] trap called'), - isExtensible: overrides.isExtensible || throwTest262Error('[[IsExtensible]] trap called'), - preventExtensions: overrides.preventExtensions || throwTest262Error('[[PreventExtensions]] trap called'), - getOwnPropertyDescriptor: overrides.getOwnPropertyDescriptor || throwTest262Error('[[GetOwnProperty]] trap called'), - has: overrides.has || throwTest262Error('[[HasProperty]] trap called'), - get: overrides.get || throwTest262Error('[[Get]] trap called'), - set: overrides.set || throwTest262Error('[[Set]] trap called'), - deleteProperty: overrides.deleteProperty || throwTest262Error('[[Delete]] trap called'), - defineProperty: overrides.defineProperty || throwTest262Error('[[DefineOwnProperty]] trap called'), - enumerate: throwTest262Error('[[Enumerate]] trap called: this trap has been removed'), - ownKeys: overrides.ownKeys || throwTest262Error('[[OwnPropertyKeys]] trap called'), - apply: overrides.apply || throwTest262Error('[[Call]] trap called'), - construct: overrides.construct || throwTest262Error('[[Construct]] trap called') - }; + function throwTest262Error(msg) { + return function () { throw new Test262Error(msg); }; + } + if (!overrides) { overrides = {}; } + return { + getPrototypeOf: overrides.getPrototypeOf || throwTest262Error('[[GetPrototypeOf]] trap called'), + setPrototypeOf: overrides.setPrototypeOf || throwTest262Error('[[SetPrototypeOf]] trap called'), + isExtensible: overrides.isExtensible || throwTest262Error('[[IsExtensible]] trap called'), + preventExtensions: overrides.preventExtensions || throwTest262Error('[[PreventExtensions]] trap called'), + getOwnPropertyDescriptor: overrides.getOwnPropertyDescriptor || throwTest262Error('[[GetOwnProperty]] trap called'), + has: overrides.has || throwTest262Error('[[HasProperty]] trap called'), + get: overrides.get || throwTest262Error('[[Get]] trap called'), + set: overrides.set || throwTest262Error('[[Set]] trap called'), + deleteProperty: overrides.deleteProperty || throwTest262Error('[[Delete]] trap called'), + defineProperty: overrides.defineProperty || throwTest262Error('[[DefineOwnProperty]] trap called'), + enumerate: throwTest262Error('[[Enumerate]] trap called: this trap has been removed'), + ownKeys: overrides.ownKeys || throwTest262Error('[[OwnPropertyKeys]] trap called'), + apply: overrides.apply || throwTest262Error('[[Call]] trap called'), + construct: overrides.construct || throwTest262Error('[[Construct]] trap called') + }; } diff --git a/harness/simdUtilities.js b/harness/simdUtilities.js index efb4cd2d59..c8396a7773 100644 --- a/harness/simdUtilities.js +++ b/harness/simdUtilities.js @@ -3,14 +3,14 @@ function minNum(x, y) { return x != x ? y : - y != y ? x : - Math.min(x, y); + y != y ? x : + Math.min(x, y); } function maxNum(x, y) { return x != x ? y : - y != y ? x : - Math.max(x, y); + y != y ? x : + Math.max(x, y); } function sameValue(x, y) { @@ -26,13 +26,13 @@ if (typeof Math.imul !== "undefined") { binaryImul = Math.imul; } else { binaryImul = function(a, b) { - var ah = (a >>> 16) & 0xffff; - var al = a & 0xffff; - var bh = (b >>> 16) & 0xffff; - var bl = b & 0xffff; - // the shift by 0 fixes the sign on the high part - // the final |0 converts the unsigned value into a signed value - return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0); + var ah = (a >>> 16) & 0xffff; + var al = a & 0xffff; + var bh = (b >>> 16) & 0xffff; + var bl = b & 0xffff; + // the shift by 0 fixes the sign on the high part + // the final |0 converts the unsigned value into a signed value + return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0); }; } @@ -236,9 +236,9 @@ uint16x8.fromBits = [float32x4, int32x4, int16x8, int8x16, uint32x4, uint8x16]; uint8x16.fromBits = [float32x4, int32x4, int16x8, int8x16, uint32x4, uint16x8]; var simdTypes = [float32x4, - int32x4, int16x8, int8x16, - uint32x4, uint16x8, uint8x16, - bool32x4, bool16x8, bool8x16]; + int32x4, int16x8, int8x16, + uint32x4, uint16x8, uint8x16, + bool32x4, bool16x8, bool8x16]; if (typeof simdPhase2 !== "undefined") { var float64x2 = { @@ -254,7 +254,7 @@ if (typeof simdPhase2 !== "undefined") { view: Float64Array, buffer: _f64x2, mulFn: binaryMul, - } + }; var bool64x2 = { name: "Bool64x2", @@ -263,7 +263,7 @@ if (typeof simdPhase2 !== "undefined") { lanes: 2, laneSize: 8, interestingValues: [true, false], - } + }; float64x2.boolType = bool64x2; @@ -332,12 +332,12 @@ function checkValue(type, a, expect) { fail = true; } if (fail) { - var lanes = []; - for (var i = 0; i < type.lanes; i++){ - lanes.push(simdConvert(type, expect(i))); - } - $ERROR("expected SIMD." + type.name + "(" + lanes + - ") but found " + a.toString()); + var lanes = []; + for (var i = 0; i < type.lanes; i++){ + lanes.push(simdConvert(type, expect(i))); + } + $ERROR("expected SIMD." + type.name + "(" + lanes + + ") but found " + a.toString()); } } @@ -356,13 +356,13 @@ function simdToLocaleString(type, value) { function equalInt32x4(a, b) { assert.sameValue(SIMD.Int32x4.extractLane(a, 0), - SIMD.Int32x4.extractLane(b, 0)); + SIMD.Int32x4.extractLane(b, 0)); assert.sameValue(SIMD.Int32x4.extractLane(a, 1), - SIMD.Int32x4.extractLane(b, 1)); + SIMD.Int32x4.extractLane(b, 1)); assert.sameValue(SIMD.Int32x4.extractLane(a, 2), - SIMD.Int32x4.extractLane(b, 2)); + SIMD.Int32x4.extractLane(b, 2)); assert.sameValue(SIMD.Int32x4.extractLane(a, 3), - SIMD.Int32x4.extractLane(b, 3)); + SIMD.Int32x4.extractLane(b, 3)); } // Compare unary op's behavior to ref op at each lane. @@ -384,7 +384,7 @@ function testBinaryOp(type, op, refOp) { for (var av of type.interestingValues) { for (var bv of type.interestingValues) { var expected = simdConvert(type, refOp(simdConvert(type, av), - simdConvert(type, bv))); + simdConvert(type, bv))); var a = type.fn.splat(av); var b = type.fn.splat(bv); var result = type.fn[op](a, b); @@ -416,7 +416,7 @@ var skipValueTests = false; function testSimdFunction(name, func) { currentName = name; if (typeof skipValueTests !== "undefined" && skipValueTests && - name.indexOf("value semantics") != -1) return; + name.indexOf("value semantics") != -1) return; try { func(); } catch (e) { diff --git a/harness/sta.js b/harness/sta.js index 10a6bb3fab..d3254f8e97 100644 --- a/harness/sta.js +++ b/harness/sta.js @@ -1,19 +1,19 @@ -/// Copyright (c) 2012 Ecma International. All rights reserved. -/// This code is governed by the BSD license found in the LICENSE file. - -function Test262Error(message) { - this.message = message || ""; -} - -Test262Error.prototype.toString = function () { - return "Test262Error: " + this.message; -}; - -var $ERROR; -$ERROR = function $ERROR(message) { - throw new Test262Error(message); -}; - -function testFailed(message) { - $ERROR(message); -} +/// Copyright (c) 2012 Ecma International. All rights reserved. +/// This code is governed by the BSD license found in the LICENSE file. + +function Test262Error(message) { + this.message = message || ""; +} + +Test262Error.prototype.toString = function () { + return "Test262Error: " + this.message; +}; + +var $ERROR; +$ERROR = function $ERROR(message) { + throw new Test262Error(message); +}; + +function testFailed(message) { + $ERROR(message); +} diff --git a/harness/testAtomics.js b/harness/testAtomics.js index a0f57a5271..2570e3ab81 100644 --- a/harness/testAtomics.js +++ b/harness/testAtomics.js @@ -9,24 +9,24 @@ * @param f - the function to call for each bad index. */ function testWithAtomicsOutOfBoundsIndices(f) { - var bad_indices = [ - (view) => -1, - (view) => view.length, - (view) => view.length*2, - (view) => Number.POSITIVE_INFINITY, - (view) => Number.NEGATIVE_INFINITY, - (view) => ({ valueOf: () => 125 }), - (view) => ({ toString: () => '125', valueOf: false }) // non-callable valueOf triggers invocation of toString - ]; + var bad_indices = [ + (view) => -1, + (view) => view.length, + (view) => view.length*2, + (view) => Number.POSITIVE_INFINITY, + (view) => Number.NEGATIVE_INFINITY, + (view) => ({ valueOf: () => 125 }), + (view) => ({ toString: () => '125', valueOf: false }) // non-callable valueOf triggers invocation of toString + ]; - for (let IdxGen of bad_indices) { - try { - f(IdxGen); - } catch (e) { - e.message += " (Testing with index gen " + IdxGen + ".)"; - throw e; - } + for (let IdxGen of bad_indices) { + try { + f(IdxGen); + } catch (e) { + e.message += " (Testing with index gen " + IdxGen + ".)"; + throw e; } + } } /** @@ -38,29 +38,29 @@ function testWithAtomicsOutOfBoundsIndices(f) { * @param f - the function to call for each good index. */ function testWithAtomicsInBoundsIndices(f) { - // Most of these are eventually coerced to +0 by ToIndex. - var good_indices = [ - (view) => 0/-1, - (view) => '-0', - (view) => undefined, - (view) => NaN, - (view) => 0.5, - (view) => '0.5', - (view) => -0.9, - (view) => ({ password: "qumquat" }), - (view) => view.length - 1, - (view) => ({ valueOf: () => 0 }), - (view) => ({ toString: () => '0', valueOf: false }) // non-callable valueOf triggers invocation of toString - ]; + // Most of these are eventually coerced to +0 by ToIndex. + var good_indices = [ + (view) => 0/-1, + (view) => '-0', + (view) => undefined, + (view) => NaN, + (view) => 0.5, + (view) => '0.5', + (view) => -0.9, + (view) => ({ password: "qumquat" }), + (view) => view.length - 1, + (view) => ({ valueOf: () => 0 }), + (view) => ({ toString: () => '0', valueOf: false }) // non-callable valueOf triggers invocation of toString + ]; - for (let IdxGen of good_indices) { - try { - f(IdxGen); - } catch (e) { - e.message += " (Testing with index gen " + IdxGen + ".)"; - throw e; - } + for (let IdxGen of good_indices) { + try { + f(IdxGen); + } catch (e) { + e.message += " (Testing with index gen " + IdxGen + ".)"; + throw e; } + } } /** @@ -71,44 +71,44 @@ function testWithAtomicsInBoundsIndices(f) { */ function testWithAtomicsNonViewValues(f) { - var values = [ - null, - undefined, - true, - false, - new Boolean(true), - 10, - 3.14, - new Number(4), - "Hi there", - new Date, - /a*utomaton/g, - { password: "qumquat" }, - new DataView(new ArrayBuffer(10)), - new ArrayBuffer(128), - new SharedArrayBuffer(128), - new Error("Ouch"), - [1,1,2,3,5,8], - ((x) => -x), - new Map(), - new Set(), - new WeakMap(), - new WeakSet(), - Symbol("halleluja"), - // TODO: Proxy? - Object, - Int32Array, - Date, - Math, - Atomics - ]; + var values = [ + null, + undefined, + true, + false, + new Boolean(true), + 10, + 3.14, + new Number(4), + "Hi there", + new Date, + /a*utomaton/g, + { password: "qumquat" }, + new DataView(new ArrayBuffer(10)), + new ArrayBuffer(128), + new SharedArrayBuffer(128), + new Error("Ouch"), + [1,1,2,3,5,8], + ((x) => -x), + new Map(), + new Set(), + new WeakMap(), + new WeakSet(), + Symbol("halleluja"), + // TODO: Proxy? + Object, + Int32Array, + Date, + Math, + Atomics + ]; - for (let nonView of values) { - try { - f(nonView); - } catch (e) { - e.message += " (Testing with non-view value " + nonView + ".)"; - throw e; - } + for (let nonView of values) { + try { + f(nonView); + } catch (e) { + e.message += " (Testing with non-view value " + nonView + ".)"; + throw e; } + } } diff --git a/harness/testBuiltInObject.js b/harness/testBuiltInObject.js index a9c498c136..c3ce749825 100644 --- a/harness/testBuiltInObject.js +++ b/harness/testBuiltInObject.js @@ -3,122 +3,121 @@ /** * @description Tests that obj meets the requirements for built-in objects - * defined by the introduction of chapter 15 of the ECMAScript Language Specification. + * defined by the introduction of chapter 15 of the ECMAScript Language Specification. * @param {Object} obj the object to be tested. * @param {boolean} isFunction whether the specification describes obj as a function. * @param {boolean} isConstructor whether the specification describes obj as a constructor. * @param {String[]} properties an array with the names of the built-in properties of obj, - * excluding length, prototype, or properties with non-default attributes. + * excluding length, prototype, or properties with non-default attributes. * @param {number} length for functions only: the length specified for the function - * or derived from the argument list. + * or derived from the argument list. * @author Norbert Lindenberg */ function testBuiltInObject(obj, isFunction, isConstructor, properties, length) { - if (obj === undefined) { - $ERROR("Object being tested is undefined."); + if (obj === undefined) { + $ERROR("Object being tested is undefined."); + } + + var objString = Object.prototype.toString.call(obj); + if (isFunction) { + if (objString !== "[object Function]") { + $ERROR("The [[Class]] internal property of a built-in function must be " + + "\"Function\", but toString() returns " + objString); + } + } else { + if (objString !== "[object Object]") { + $ERROR("The [[Class]] internal property of a built-in non-function object must be " + + "\"Object\", but toString() returns " + objString); + } + } + + if (!Object.isExtensible(obj)) { + $ERROR("Built-in objects must be extensible."); + } + + if (isFunction && Object.getPrototypeOf(obj) !== Function.prototype) { + $ERROR("Built-in functions must have Function.prototype as their prototype."); + } + + if (isConstructor && Object.getPrototypeOf(obj.prototype) !== Object.prototype) { + $ERROR("Built-in prototype objects must have Object.prototype as their prototype."); + } + + // verification of the absence of the [[Construct]] internal property has + // been moved to the end of the test + + // verification of the absence of the prototype property has + // been moved to the end of the test + + if (isFunction) { + + if (typeof obj.length !== "number" || obj.length !== Math.floor(obj.length)) { + $ERROR("Built-in functions must have a length property with an integer value."); } - var objString = Object.prototype.toString.call(obj); - if (isFunction) { - if (objString !== "[object Function]") { - $ERROR("The [[Class]] internal property of a built-in function must be " + - "\"Function\", but toString() returns " + objString); - } - } else { - if (objString !== "[object Object]") { - $ERROR("The [[Class]] internal property of a built-in non-function object must be " + - "\"Object\", but toString() returns " + objString); - } + if (obj.length !== length) { + $ERROR("Function's length property doesn't have specified value; expected " + + length + ", got " + obj.length + "."); } - if (!Object.isExtensible(obj)) { - $ERROR("Built-in objects must be extensible."); + var desc = Object.getOwnPropertyDescriptor(obj, "length"); + if (desc.writable) { + $ERROR("The length property of a built-in function must not be writable."); } - - if (isFunction && Object.getPrototypeOf(obj) !== Function.prototype) { - $ERROR("Built-in functions must have Function.prototype as their prototype."); + if (desc.enumerable) { + $ERROR("The length property of a built-in function must not be enumerable."); } - - if (isConstructor && Object.getPrototypeOf(obj.prototype) !== Object.prototype) { - $ERROR("Built-in prototype objects must have Object.prototype as their prototype."); + if (!desc.configurable) { + $ERROR("The length property of a built-in function must be configurable."); } + } - // verification of the absence of the [[Construct]] internal property has - // been moved to the end of the test - - // verification of the absence of the prototype property has - // been moved to the end of the test - - if (isFunction) { - - if (typeof obj.length !== "number" || obj.length !== Math.floor(obj.length)) { - $ERROR("Built-in functions must have a length property with an integer value."); - } - - if (obj.length !== length) { - $ERROR("Function's length property doesn't have specified value; expected " + - length + ", got " + obj.length + "."); - } - - var desc = Object.getOwnPropertyDescriptor(obj, "length"); - if (desc.writable) { - $ERROR("The length property of a built-in function must not be writable."); - } - if (desc.enumerable) { - $ERROR("The length property of a built-in function must not be enumerable."); - } - if (!desc.configurable) { - $ERROR("The length property of a built-in function must be configurable."); - } + properties.forEach(function(prop) { + var desc = Object.getOwnPropertyDescriptor(obj, prop); + if (desc === undefined) { + $ERROR("Missing property " + prop + "."); } - - properties.forEach(function(prop) { - var desc = Object.getOwnPropertyDescriptor(obj, prop); - if (desc === undefined) { - $ERROR("Missing property " + prop + "."); - } - // accessor properties don't have writable attribute - if (desc.hasOwnProperty("writable") && !desc.writable) { - $ERROR("The " + prop + " property of this built-in object must be writable."); - } - if (desc.enumerable) { - $ERROR("The " + prop + " property of this built-in object must not be enumerable."); - } - if (!desc.configurable) { - $ERROR("The " + prop + " property of this built-in object must be configurable."); - } - }); - - // The remaining sections have been moved to the end of the test because - // unbound non-constructor functions written in JavaScript cannot possibly - // pass them, and we still want to test JavaScript implementations as much - // as possible. - - var exception; - if (isFunction && !isConstructor) { - // this is not a complete test for the presence of [[Construct]]: - // if it's absent, the exception must be thrown, but it may also - // be thrown if it's present and just has preconditions related to - // arguments or the this value that this statement doesn't meet. - try { - /*jshint newcap:false*/ - var instance = new obj(); - } catch (e) { - exception = e; - } - if (exception === undefined || exception.name !== "TypeError") { - $ERROR("Built-in functions that aren't constructors must throw TypeError when " + - "used in a \"new\" statement."); - } + // accessor properties don't have writable attribute + if (desc.hasOwnProperty("writable") && !desc.writable) { + $ERROR("The " + prop + " property of this built-in object must be writable."); } - - if (isFunction && !isConstructor && obj.hasOwnProperty("prototype")) { - $ERROR("Built-in functions that aren't constructors must not have a prototype property."); + if (desc.enumerable) { + $ERROR("The " + prop + " property of this built-in object must not be enumerable."); } + if (!desc.configurable) { + $ERROR("The " + prop + " property of this built-in object must be configurable."); + } + }); - // passed the complete test! - return true; + // The remaining sections have been moved to the end of the test because + // unbound non-constructor functions written in JavaScript cannot possibly + // pass them, and we still want to test JavaScript implementations as much + // as possible. + + var exception; + if (isFunction && !isConstructor) { + // this is not a complete test for the presence of [[Construct]]: + // if it's absent, the exception must be thrown, but it may also + // be thrown if it's present and just has preconditions related to + // arguments or the this value that this statement doesn't meet. + try { + /*jshint newcap:false*/ + var instance = new obj(); + } catch (e) { + exception = e; + } + if (exception === undefined || exception.name !== "TypeError") { + $ERROR("Built-in functions that aren't constructors must throw TypeError when " + + "used in a \"new\" statement."); + } + } + + if (isFunction && !isConstructor && obj.hasOwnProperty("prototype")) { + $ERROR("Built-in functions that aren't constructors must not have a prototype property."); + } + + // passed the complete test! + return true; } - diff --git a/harness/testIntl.js b/harness/testIntl.js index 61340d48b2..ddf953acd3 100644 --- a/harness/testIntl.js +++ b/harness/testIntl.js @@ -14,23 +14,23 @@ * the Intl object, until f returns a falsy value. It returns the result of the * last call to f, mapped to a boolean. * @param {Function} f the function to call for each service constructor in - * the Intl object. - * @param {Function} Constructor the constructor object to test with. + * the Intl object. + * @param {Function} Constructor the constructor object to test with. * @result {Boolean} whether the test succeeded. */ function testWithIntlConstructors(f) { - var constructors = ["Collator", "NumberFormat", "DateTimeFormat"]; - return constructors.every(function (constructor) { - var Constructor = Intl[constructor]; - var result; - try { - result = f(Constructor); - } catch (e) { - e.message += " (Testing with " + constructor + ".)"; - throw e; - } - return result; - }); + var constructors = ["Collator", "NumberFormat", "DateTimeFormat"]; + return constructors.every(function (constructor) { + var Constructor = Intl[constructor]; + var result; + try { + result = f(Constructor); + } catch (e) { + e.message += " (Testing with " + constructor + ".)"; + throw e; + } + return result; + }); } @@ -41,16 +41,16 @@ function testWithIntlConstructors(f) { * @return {string} the name of the constructor */ function getConstructorName(Constructor) { - switch (Constructor) { - case Intl.Collator: - return "Collator"; - case Intl.NumberFormat: - return "NumberFormat"; - case Intl.DateTimeFormat: - return "DateTimeFormat"; - default: - $ERROR("test internal error: unknown Constructor"); - } + switch (Constructor) { + case Intl.Collator: + return "Collator"; + case Intl.NumberFormat: + return "NumberFormat"; + case Intl.DateTimeFormat: + return "DateTimeFormat"; + default: + $ERROR("test internal error: unknown Constructor"); + } } @@ -61,13 +61,13 @@ function getConstructorName(Constructor) { * @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 - }); + Object.defineProperty(obj, property, { + set: function(value) { + $ERROR("Client code can adversely affect behavior: setter for " + property + "."); + }, + enumerable: false, + configurable: true + }); } @@ -78,14 +78,14 @@ function taintDataProperty(obj, property) { * @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 - }); + Object.defineProperty(obj, property, { + value: function() { + $ERROR("Client code can adversely affect behavior: method " + property + "."); + }, + writable: true, + enumerable: false, + configurable: true + }); } @@ -95,12 +95,12 @@ function taintMethod(obj, property) { * @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); - }); + properties.forEach(function (property) { + var adaptedProperties = [property, "__" + property, "_" + property, property + "_", property + "__"]; + adaptedProperties.forEach(function (property) { + taintDataProperty(Object.prototype, property); }); + }); } @@ -109,12 +109,12 @@ function taintProperties(properties) { * 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"); + taintDataProperty(Array.prototype, "0"); + taintMethod(Array.prototype, "indexOf"); + taintMethod(Array.prototype, "join"); + taintMethod(Array.prototype, "push"); + taintMethod(Array.prototype, "slice"); + taintMethod(Array.prototype, "sort"); } @@ -130,60 +130,60 @@ var localeSupportInfo = {}; * of Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat. * @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 + * 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 constructorName = getConstructorName(Constructor); - if (localeSupportInfo[constructorName] !== undefined) { - return localeSupportInfo[constructorName]; - } - - 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); - } - } - - localeSupportInfo[constructorName] = { - supported: supported, - byFallback: byFallback, - unsupported: unsupported - }; - + var constructorName = getConstructorName(Constructor); + if (localeSupportInfo[constructorName] !== undefined) { return localeSupportInfo[constructorName]; + } + + 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); + } + } + + localeSupportInfo[constructorName] = { + supported: supported, + byFallback: byFallback, + unsupported: unsupported + }; + + return localeSupportInfo[constructorName]; } - + /** * @description Tests whether locale is a String value representing a @@ -195,465 +195,465 @@ function getLocaleSupportInfo(Constructor) { */ function isCanonicalizedStructurallyValidLanguageTag(locale) { - /** - * Regular expression defining BCP 47 language tags. - * - * Spec: RFC 5646 section 2.1. - */ - var alpha = "[a-zA-Z]", - digit = "[0-9]", - alphanum = "(" + alpha + "|" + digit + ")", - regular = "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)", - irregular = "(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)", - grandfathered = "(" + irregular + "|" + regular + ")", - privateuse = "(x(-[a-z0-9]{1,8})+)", - singleton = "(" + digit + "|[A-WY-Za-wy-z])", - extension = "(" + singleton + "(-" + alphanum + "{2,8})+)", - variant = "(" + alphanum + "{5,8}|(" + digit + alphanum + "{3}))", - region = "(" + alpha + "{2}|" + digit + "{3})", - script = "(" + alpha + "{4})", - extlang = "(" + alpha + "{3}(-" + alpha + "{3}){0,2})", - language = "(" + alpha + "{2,3}(-" + extlang + ")?|" + alpha + "{4}|" + alpha + "{5,8})", - langtag = language + "(-" + script + ")?(-" + region + ")?(-" + variant + ")*(-" + extension + ")*(-" + privateuse + ")?", - languageTag = "^(" + langtag + "|" + privateuse + "|" + grandfathered + ")$", - languageTagRE = new RegExp(languageTag, "i"); - var duplicateSingleton = "-" + singleton + "-(.*-)?\\1(?!" + alphanum + ")", - duplicateSingletonRE = new RegExp(duplicateSingleton, "i"), - duplicateVariant = "(" + alphanum + "{2,8}-)+" + variant + "-(" + alphanum + "{2,8}-)*\\3(?!" + alphanum + ")", - duplicateVariantRE = new RegExp(duplicateVariant, "i"); + /** + * Regular expression defining BCP 47 language tags. + * + * Spec: RFC 5646 section 2.1. + */ + var alpha = "[a-zA-Z]", + digit = "[0-9]", + alphanum = "(" + alpha + "|" + digit + ")", + regular = "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)", + irregular = "(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)", + grandfathered = "(" + irregular + "|" + regular + ")", + privateuse = "(x(-[a-z0-9]{1,8})+)", + singleton = "(" + digit + "|[A-WY-Za-wy-z])", + extension = "(" + singleton + "(-" + alphanum + "{2,8})+)", + variant = "(" + alphanum + "{5,8}|(" + digit + alphanum + "{3}))", + region = "(" + alpha + "{2}|" + digit + "{3})", + script = "(" + alpha + "{4})", + extlang = "(" + alpha + "{3}(-" + alpha + "{3}){0,2})", + language = "(" + alpha + "{2,3}(-" + extlang + ")?|" + alpha + "{4}|" + alpha + "{5,8})", + langtag = language + "(-" + script + ")?(-" + region + ")?(-" + variant + ")*(-" + extension + ")*(-" + privateuse + ")?", + languageTag = "^(" + langtag + "|" + privateuse + "|" + grandfathered + ")$", + languageTagRE = new RegExp(languageTag, "i"); + var duplicateSingleton = "-" + singleton + "-(.*-)?\\1(?!" + alphanum + ")", + duplicateSingletonRE = new RegExp(duplicateSingleton, "i"), + duplicateVariant = "(" + alphanum + "{2,8}-)+" + variant + "-(" + alphanum + "{2,8}-)*\\3(?!" + alphanum + ")", + duplicateVariantRE = new RegExp(duplicateVariant, "i"); - /** - * Verifies that the given string is a well-formed BCP 47 language tag - * 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); + /** + * Verifies that the given string is a well-formed BCP 47 language tag + * 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: IANA Language Subtag Registry. + */ + var __tagMappings = { + // property names must be in lower case; values in canonical form + + // grandfathered tags from IANA language subtag registry, file date 2011-08-25 + "art-lojban": "jbo", + "cel-gaulish": "cel-gaulish", + "en-gb-oed": "en-GB-oed", + "i-ami": "ami", + "i-bnn": "bnn", + "i-default": "i-default", + "i-enochian": "i-enochian", + "i-hak": "hak", + "i-klingon": "tlh", + "i-lux": "lb", + "i-mingo": "i-mingo", + "i-navajo": "nv", + "i-pwn": "pwn", + "i-tao": "tao", + "i-tay": "tay", + "i-tsu": "tsu", + "no-bok": "nb", + "no-nyn": "nn", + "sgn-be-fr": "sfb", + "sgn-be-nl": "vgt", + "sgn-ch-de": "sgg", + "zh-guoyu": "cmn", + "zh-hakka": "hak", + "zh-min": "zh-min", + "zh-min-nan": "nan", + "zh-xiang": "hsn", + // deprecated redundant tags from IANA language subtag registry, file date 2011-08-25 + "sgn-br": "bzs", + "sgn-co": "csn", + "sgn-de": "gsg", + "sgn-dk": "dsl", + "sgn-es": "ssp", + "sgn-fr": "fsl", + "sgn-gb": "bfi", + "sgn-gr": "gss", + "sgn-ie": "isg", + "sgn-it": "ise", + "sgn-jp": "jsl", + "sgn-mx": "mfs", + "sgn-ni": "ncs", + "sgn-nl": "dse", + "sgn-no": "nsl", + "sgn-pt": "psr", + "sgn-se": "swl", + "sgn-us": "ase", + "sgn-za": "sfs", + "zh-cmn": "cmn", + "zh-cmn-hans": "cmn-Hans", + "zh-cmn-hant": "cmn-Hant", + "zh-gan": "gan", + "zh-wuu": "wuu", + "zh-yue": "yue", + // deprecated variant with prefix from IANA language subtag registry, file date 2011-08-25 + "ja-latn-hepburn-heploc": "ja-Latn-alalc97" + }; + + + /** + * Mappings from non-extlang subtags to preferred values. + * + * Spec: IANA Language Subtag Registry. + */ + var __subtagMappings = { + // property names and values must be in canonical case + // language subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25 + "in": "id", + "iw": "he", + "ji": "yi", + "jw": "jv", + "mo": "ro", + "ayx": "nun", + "cjr": "mom", + "cmk": "xch", + "drh": "khk", + "drw": "prs", + "gav": "dev", + "mst": "mry", + "myt": "mry", + "tie": "ras", + "tkk": "twm", + "tnf": "prs", + // region subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25 + "BU": "MM", + "DD": "DE", + "FX": "FR", + "TP": "TL", + "YD": "YE", + "ZR": "CD" + }; + + + /** + * Mappings from extlang subtags to preferred values. + * + * Spec: IANA Language Subtag Registry. + */ + var __extlangMappings = { + // extlang subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25 + // values are arrays with [0] the replacement value, [1] (if present) the prefix to be removed + "aao": ["aao", "ar"], + "abh": ["abh", "ar"], + "abv": ["abv", "ar"], + "acm": ["acm", "ar"], + "acq": ["acq", "ar"], + "acw": ["acw", "ar"], + "acx": ["acx", "ar"], + "acy": ["acy", "ar"], + "adf": ["adf", "ar"], + "ads": ["ads", "sgn"], + "aeb": ["aeb", "ar"], + "aec": ["aec", "ar"], + "aed": ["aed", "sgn"], + "aen": ["aen", "sgn"], + "afb": ["afb", "ar"], + "afg": ["afg", "sgn"], + "ajp": ["ajp", "ar"], + "apc": ["apc", "ar"], + "apd": ["apd", "ar"], + "arb": ["arb", "ar"], + "arq": ["arq", "ar"], + "ars": ["ars", "ar"], + "ary": ["ary", "ar"], + "arz": ["arz", "ar"], + "ase": ["ase", "sgn"], + "asf": ["asf", "sgn"], + "asp": ["asp", "sgn"], + "asq": ["asq", "sgn"], + "asw": ["asw", "sgn"], + "auz": ["auz", "ar"], + "avl": ["avl", "ar"], + "ayh": ["ayh", "ar"], + "ayl": ["ayl", "ar"], + "ayn": ["ayn", "ar"], + "ayp": ["ayp", "ar"], + "bbz": ["bbz", "ar"], + "bfi": ["bfi", "sgn"], + "bfk": ["bfk", "sgn"], + "bjn": ["bjn", "ms"], + "bog": ["bog", "sgn"], + "bqn": ["bqn", "sgn"], + "bqy": ["bqy", "sgn"], + "btj": ["btj", "ms"], + "bve": ["bve", "ms"], + "bvl": ["bvl", "sgn"], + "bvu": ["bvu", "ms"], + "bzs": ["bzs", "sgn"], + "cdo": ["cdo", "zh"], + "cds": ["cds", "sgn"], + "cjy": ["cjy", "zh"], + "cmn": ["cmn", "zh"], + "coa": ["coa", "ms"], + "cpx": ["cpx", "zh"], + "csc": ["csc", "sgn"], + "csd": ["csd", "sgn"], + "cse": ["cse", "sgn"], + "csf": ["csf", "sgn"], + "csg": ["csg", "sgn"], + "csl": ["csl", "sgn"], + "csn": ["csn", "sgn"], + "csq": ["csq", "sgn"], + "csr": ["csr", "sgn"], + "czh": ["czh", "zh"], + "czo": ["czo", "zh"], + "doq": ["doq", "sgn"], + "dse": ["dse", "sgn"], + "dsl": ["dsl", "sgn"], + "dup": ["dup", "ms"], + "ecs": ["ecs", "sgn"], + "esl": ["esl", "sgn"], + "esn": ["esn", "sgn"], + "eso": ["eso", "sgn"], + "eth": ["eth", "sgn"], + "fcs": ["fcs", "sgn"], + "fse": ["fse", "sgn"], + "fsl": ["fsl", "sgn"], + "fss": ["fss", "sgn"], + "gan": ["gan", "zh"], + "gom": ["gom", "kok"], + "gse": ["gse", "sgn"], + "gsg": ["gsg", "sgn"], + "gsm": ["gsm", "sgn"], + "gss": ["gss", "sgn"], + "gus": ["gus", "sgn"], + "hab": ["hab", "sgn"], + "haf": ["haf", "sgn"], + "hak": ["hak", "zh"], + "hds": ["hds", "sgn"], + "hji": ["hji", "ms"], + "hks": ["hks", "sgn"], + "hos": ["hos", "sgn"], + "hps": ["hps", "sgn"], + "hsh": ["hsh", "sgn"], + "hsl": ["hsl", "sgn"], + "hsn": ["hsn", "zh"], + "icl": ["icl", "sgn"], + "ils": ["ils", "sgn"], + "inl": ["inl", "sgn"], + "ins": ["ins", "sgn"], + "ise": ["ise", "sgn"], + "isg": ["isg", "sgn"], + "isr": ["isr", "sgn"], + "jak": ["jak", "ms"], + "jax": ["jax", "ms"], + "jcs": ["jcs", "sgn"], + "jhs": ["jhs", "sgn"], + "jls": ["jls", "sgn"], + "jos": ["jos", "sgn"], + "jsl": ["jsl", "sgn"], + "jus": ["jus", "sgn"], + "kgi": ["kgi", "sgn"], + "knn": ["knn", "kok"], + "kvb": ["kvb", "ms"], + "kvk": ["kvk", "sgn"], + "kvr": ["kvr", "ms"], + "kxd": ["kxd", "ms"], + "lbs": ["lbs", "sgn"], + "lce": ["lce", "ms"], + "lcf": ["lcf", "ms"], + "liw": ["liw", "ms"], + "lls": ["lls", "sgn"], + "lsg": ["lsg", "sgn"], + "lsl": ["lsl", "sgn"], + "lso": ["lso", "sgn"], + "lsp": ["lsp", "sgn"], + "lst": ["lst", "sgn"], + "lsy": ["lsy", "sgn"], + "ltg": ["ltg", "lv"], + "lvs": ["lvs", "lv"], + "lzh": ["lzh", "zh"], + "max": ["max", "ms"], + "mdl": ["mdl", "sgn"], + "meo": ["meo", "ms"], + "mfa": ["mfa", "ms"], + "mfb": ["mfb", "ms"], + "mfs": ["mfs", "sgn"], + "min": ["min", "ms"], + "mnp": ["mnp", "zh"], + "mqg": ["mqg", "ms"], + "mre": ["mre", "sgn"], + "msd": ["msd", "sgn"], + "msi": ["msi", "ms"], + "msr": ["msr", "sgn"], + "mui": ["mui", "ms"], + "mzc": ["mzc", "sgn"], + "mzg": ["mzg", "sgn"], + "mzy": ["mzy", "sgn"], + "nan": ["nan", "zh"], + "nbs": ["nbs", "sgn"], + "ncs": ["ncs", "sgn"], + "nsi": ["nsi", "sgn"], + "nsl": ["nsl", "sgn"], + "nsp": ["nsp", "sgn"], + "nsr": ["nsr", "sgn"], + "nzs": ["nzs", "sgn"], + "okl": ["okl", "sgn"], + "orn": ["orn", "ms"], + "ors": ["ors", "ms"], + "pel": ["pel", "ms"], + "pga": ["pga", "ar"], + "pks": ["pks", "sgn"], + "prl": ["prl", "sgn"], + "prz": ["prz", "sgn"], + "psc": ["psc", "sgn"], + "psd": ["psd", "sgn"], + "pse": ["pse", "ms"], + "psg": ["psg", "sgn"], + "psl": ["psl", "sgn"], + "pso": ["pso", "sgn"], + "psp": ["psp", "sgn"], + "psr": ["psr", "sgn"], + "pys": ["pys", "sgn"], + "rms": ["rms", "sgn"], + "rsi": ["rsi", "sgn"], + "rsl": ["rsl", "sgn"], + "sdl": ["sdl", "sgn"], + "sfb": ["sfb", "sgn"], + "sfs": ["sfs", "sgn"], + "sgg": ["sgg", "sgn"], + "sgx": ["sgx", "sgn"], + "shu": ["shu", "ar"], + "slf": ["slf", "sgn"], + "sls": ["sls", "sgn"], + "sqs": ["sqs", "sgn"], + "ssh": ["ssh", "ar"], + "ssp": ["ssp", "sgn"], + "ssr": ["ssr", "sgn"], + "svk": ["svk", "sgn"], + "swc": ["swc", "sw"], + "swh": ["swh", "sw"], + "swl": ["swl", "sgn"], + "syy": ["syy", "sgn"], + "tmw": ["tmw", "ms"], + "tse": ["tse", "sgn"], + "tsm": ["tsm", "sgn"], + "tsq": ["tsq", "sgn"], + "tss": ["tss", "sgn"], + "tsy": ["tsy", "sgn"], + "tza": ["tza", "sgn"], + "ugn": ["ugn", "sgn"], + "ugy": ["ugy", "sgn"], + "ukl": ["ukl", "sgn"], + "uks": ["uks", "sgn"], + "urk": ["urk", "ms"], + "uzn": ["uzn", "uz"], + "uzs": ["uzs", "uz"], + "vgt": ["vgt", "sgn"], + "vkk": ["vkk", "ms"], + "vkt": ["vkt", "ms"], + "vsi": ["vsi", "sgn"], + "vsl": ["vsl", "sgn"], + "vsv": ["vsv", "sgn"], + "wuu": ["wuu", "zh"], + "xki": ["xki", "sgn"], + "xml": ["xml", "sgn"], + "xmm": ["xmm", "ms"], + "xms": ["xms", "sgn"], + "yds": ["yds", "sgn"], + "ysl": ["ysl", "sgn"], + "yue": ["yue", "zh"], + "zib": ["zib", "sgn"], + "zlm": ["zlm", "ms"], + "zmi": ["zmi", "ms"], + "zsl": ["zsl", "sgn"], + "zsm": ["zsm", "ms"] + }; + + + /** + * 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; - /** - * Mappings from complete tags to preferred values. - * - * Spec: IANA Language Subtag Registry. - */ - var __tagMappings = { - // property names must be in lower case; values in canonical form - - // grandfathered tags from IANA language subtag registry, file date 2011-08-25 - "art-lojban": "jbo", - "cel-gaulish": "cel-gaulish", - "en-gb-oed": "en-GB-oed", - "i-ami": "ami", - "i-bnn": "bnn", - "i-default": "i-default", - "i-enochian": "i-enochian", - "i-hak": "hak", - "i-klingon": "tlh", - "i-lux": "lb", - "i-mingo": "i-mingo", - "i-navajo": "nv", - "i-pwn": "pwn", - "i-tao": "tao", - "i-tay": "tay", - "i-tsu": "tsu", - "no-bok": "nb", - "no-nyn": "nn", - "sgn-be-fr": "sfb", - "sgn-be-nl": "vgt", - "sgn-ch-de": "sgg", - "zh-guoyu": "cmn", - "zh-hakka": "hak", - "zh-min": "zh-min", - "zh-min-nan": "nan", - "zh-xiang": "hsn", - // deprecated redundant tags from IANA language subtag registry, file date 2011-08-25 - "sgn-br": "bzs", - "sgn-co": "csn", - "sgn-de": "gsg", - "sgn-dk": "dsl", - "sgn-es": "ssp", - "sgn-fr": "fsl", - "sgn-gb": "bfi", - "sgn-gr": "gss", - "sgn-ie": "isg", - "sgn-it": "ise", - "sgn-jp": "jsl", - "sgn-mx": "mfs", - "sgn-ni": "ncs", - "sgn-nl": "dse", - "sgn-no": "nsl", - "sgn-pt": "psr", - "sgn-se": "swl", - "sgn-us": "ase", - "sgn-za": "sfs", - "zh-cmn": "cmn", - "zh-cmn-hans": "cmn-Hans", - "zh-cmn-hant": "cmn-Hant", - "zh-gan": "gan", - "zh-wuu": "wuu", - "zh-yue": "yue", - // deprecated variant with prefix from IANA language subtag registry, file date 2011-08-25 - "ja-latn-hepburn-heploc": "ja-Latn-alalc97" - }; - - - /** - * Mappings from non-extlang subtags to preferred values. - * - * Spec: IANA Language Subtag Registry. - */ - var __subtagMappings = { - // property names and values must be in canonical case - // language subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25 - "in": "id", - "iw": "he", - "ji": "yi", - "jw": "jv", - "mo": "ro", - "ayx": "nun", - "cjr": "mom", - "cmk": "xch", - "drh": "khk", - "drw": "prs", - "gav": "dev", - "mst": "mry", - "myt": "mry", - "tie": "ras", - "tkk": "twm", - "tnf": "prs", - // region subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25 - "BU": "MM", - "DD": "DE", - "FX": "FR", - "TP": "TL", - "YD": "YE", - "ZR": "CD" - }; - - - /** - * Mappings from extlang subtags to preferred values. - * - * Spec: IANA Language Subtag Registry. - */ - var __extlangMappings = { - // extlang subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25 - // values are arrays with [0] the replacement value, [1] (if present) the prefix to be removed - "aao": ["aao", "ar"], - "abh": ["abh", "ar"], - "abv": ["abv", "ar"], - "acm": ["acm", "ar"], - "acq": ["acq", "ar"], - "acw": ["acw", "ar"], - "acx": ["acx", "ar"], - "acy": ["acy", "ar"], - "adf": ["adf", "ar"], - "ads": ["ads", "sgn"], - "aeb": ["aeb", "ar"], - "aec": ["aec", "ar"], - "aed": ["aed", "sgn"], - "aen": ["aen", "sgn"], - "afb": ["afb", "ar"], - "afg": ["afg", "sgn"], - "ajp": ["ajp", "ar"], - "apc": ["apc", "ar"], - "apd": ["apd", "ar"], - "arb": ["arb", "ar"], - "arq": ["arq", "ar"], - "ars": ["ars", "ar"], - "ary": ["ary", "ar"], - "arz": ["arz", "ar"], - "ase": ["ase", "sgn"], - "asf": ["asf", "sgn"], - "asp": ["asp", "sgn"], - "asq": ["asq", "sgn"], - "asw": ["asw", "sgn"], - "auz": ["auz", "ar"], - "avl": ["avl", "ar"], - "ayh": ["ayh", "ar"], - "ayl": ["ayl", "ar"], - "ayn": ["ayn", "ar"], - "ayp": ["ayp", "ar"], - "bbz": ["bbz", "ar"], - "bfi": ["bfi", "sgn"], - "bfk": ["bfk", "sgn"], - "bjn": ["bjn", "ms"], - "bog": ["bog", "sgn"], - "bqn": ["bqn", "sgn"], - "bqy": ["bqy", "sgn"], - "btj": ["btj", "ms"], - "bve": ["bve", "ms"], - "bvl": ["bvl", "sgn"], - "bvu": ["bvu", "ms"], - "bzs": ["bzs", "sgn"], - "cdo": ["cdo", "zh"], - "cds": ["cds", "sgn"], - "cjy": ["cjy", "zh"], - "cmn": ["cmn", "zh"], - "coa": ["coa", "ms"], - "cpx": ["cpx", "zh"], - "csc": ["csc", "sgn"], - "csd": ["csd", "sgn"], - "cse": ["cse", "sgn"], - "csf": ["csf", "sgn"], - "csg": ["csg", "sgn"], - "csl": ["csl", "sgn"], - "csn": ["csn", "sgn"], - "csq": ["csq", "sgn"], - "csr": ["csr", "sgn"], - "czh": ["czh", "zh"], - "czo": ["czo", "zh"], - "doq": ["doq", "sgn"], - "dse": ["dse", "sgn"], - "dsl": ["dsl", "sgn"], - "dup": ["dup", "ms"], - "ecs": ["ecs", "sgn"], - "esl": ["esl", "sgn"], - "esn": ["esn", "sgn"], - "eso": ["eso", "sgn"], - "eth": ["eth", "sgn"], - "fcs": ["fcs", "sgn"], - "fse": ["fse", "sgn"], - "fsl": ["fsl", "sgn"], - "fss": ["fss", "sgn"], - "gan": ["gan", "zh"], - "gom": ["gom", "kok"], - "gse": ["gse", "sgn"], - "gsg": ["gsg", "sgn"], - "gsm": ["gsm", "sgn"], - "gss": ["gss", "sgn"], - "gus": ["gus", "sgn"], - "hab": ["hab", "sgn"], - "haf": ["haf", "sgn"], - "hak": ["hak", "zh"], - "hds": ["hds", "sgn"], - "hji": ["hji", "ms"], - "hks": ["hks", "sgn"], - "hos": ["hos", "sgn"], - "hps": ["hps", "sgn"], - "hsh": ["hsh", "sgn"], - "hsl": ["hsl", "sgn"], - "hsn": ["hsn", "zh"], - "icl": ["icl", "sgn"], - "ils": ["ils", "sgn"], - "inl": ["inl", "sgn"], - "ins": ["ins", "sgn"], - "ise": ["ise", "sgn"], - "isg": ["isg", "sgn"], - "isr": ["isr", "sgn"], - "jak": ["jak", "ms"], - "jax": ["jax", "ms"], - "jcs": ["jcs", "sgn"], - "jhs": ["jhs", "sgn"], - "jls": ["jls", "sgn"], - "jos": ["jos", "sgn"], - "jsl": ["jsl", "sgn"], - "jus": ["jus", "sgn"], - "kgi": ["kgi", "sgn"], - "knn": ["knn", "kok"], - "kvb": ["kvb", "ms"], - "kvk": ["kvk", "sgn"], - "kvr": ["kvr", "ms"], - "kxd": ["kxd", "ms"], - "lbs": ["lbs", "sgn"], - "lce": ["lce", "ms"], - "lcf": ["lcf", "ms"], - "liw": ["liw", "ms"], - "lls": ["lls", "sgn"], - "lsg": ["lsg", "sgn"], - "lsl": ["lsl", "sgn"], - "lso": ["lso", "sgn"], - "lsp": ["lsp", "sgn"], - "lst": ["lst", "sgn"], - "lsy": ["lsy", "sgn"], - "ltg": ["ltg", "lv"], - "lvs": ["lvs", "lv"], - "lzh": ["lzh", "zh"], - "max": ["max", "ms"], - "mdl": ["mdl", "sgn"], - "meo": ["meo", "ms"], - "mfa": ["mfa", "ms"], - "mfb": ["mfb", "ms"], - "mfs": ["mfs", "sgn"], - "min": ["min", "ms"], - "mnp": ["mnp", "zh"], - "mqg": ["mqg", "ms"], - "mre": ["mre", "sgn"], - "msd": ["msd", "sgn"], - "msi": ["msi", "ms"], - "msr": ["msr", "sgn"], - "mui": ["mui", "ms"], - "mzc": ["mzc", "sgn"], - "mzg": ["mzg", "sgn"], - "mzy": ["mzy", "sgn"], - "nan": ["nan", "zh"], - "nbs": ["nbs", "sgn"], - "ncs": ["ncs", "sgn"], - "nsi": ["nsi", "sgn"], - "nsl": ["nsl", "sgn"], - "nsp": ["nsp", "sgn"], - "nsr": ["nsr", "sgn"], - "nzs": ["nzs", "sgn"], - "okl": ["okl", "sgn"], - "orn": ["orn", "ms"], - "ors": ["ors", "ms"], - "pel": ["pel", "ms"], - "pga": ["pga", "ar"], - "pks": ["pks", "sgn"], - "prl": ["prl", "sgn"], - "prz": ["prz", "sgn"], - "psc": ["psc", "sgn"], - "psd": ["psd", "sgn"], - "pse": ["pse", "ms"], - "psg": ["psg", "sgn"], - "psl": ["psl", "sgn"], - "pso": ["pso", "sgn"], - "psp": ["psp", "sgn"], - "psr": ["psr", "sgn"], - "pys": ["pys", "sgn"], - "rms": ["rms", "sgn"], - "rsi": ["rsi", "sgn"], - "rsl": ["rsl", "sgn"], - "sdl": ["sdl", "sgn"], - "sfb": ["sfb", "sgn"], - "sfs": ["sfs", "sgn"], - "sgg": ["sgg", "sgn"], - "sgx": ["sgx", "sgn"], - "shu": ["shu", "ar"], - "slf": ["slf", "sgn"], - "sls": ["sls", "sgn"], - "sqs": ["sqs", "sgn"], - "ssh": ["ssh", "ar"], - "ssp": ["ssp", "sgn"], - "ssr": ["ssr", "sgn"], - "svk": ["svk", "sgn"], - "swc": ["swc", "sw"], - "swh": ["swh", "sw"], - "swl": ["swl", "sgn"], - "syy": ["syy", "sgn"], - "tmw": ["tmw", "ms"], - "tse": ["tse", "sgn"], - "tsm": ["tsm", "sgn"], - "tsq": ["tsq", "sgn"], - "tss": ["tss", "sgn"], - "tsy": ["tsy", "sgn"], - "tza": ["tza", "sgn"], - "ugn": ["ugn", "sgn"], - "ugy": ["ugy", "sgn"], - "ukl": ["ukl", "sgn"], - "uks": ["uks", "sgn"], - "urk": ["urk", "ms"], - "uzn": ["uzn", "uz"], - "uzs": ["uzs", "uz"], - "vgt": ["vgt", "sgn"], - "vkk": ["vkk", "ms"], - "vkt": ["vkt", "ms"], - "vsi": ["vsi", "sgn"], - "vsl": ["vsl", "sgn"], - "vsv": ["vsv", "sgn"], - "wuu": ["wuu", "zh"], - "xki": ["xki", "sgn"], - "xml": ["xml", "sgn"], - "xmm": ["xmm", "ms"], - "xms": ["xms", "sgn"], - "yds": ["yds", "sgn"], - "ysl": ["ysl", "sgn"], - "yue": ["yue", "zh"], - "zib": ["zib", "sgn"], - "zlm": ["zlm", "ms"], - "zmi": ["zmi", "ms"], - "zsl": ["zsl", "sgn"], - "zsm": ["zsm", "ms"] - }; - - - /** - * 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]; + // handle standard part: all subtags before first singleton or "x" + while (i < subtags.length) { + var subtag = subtags[i]; + if (subtag.length === 1 && (i > 0 || subtag === "x")) { + break; + } else if (i !== 0 && subtag.length === 2) { + subtag = subtag.toUpperCase(); + } else if (subtag.length === 4) { + subtag = subtag[0].toUpperCase() + subtag.substring(1).toLowerCase(); + } + if (__subtagMappings.hasOwnProperty(subtag)) { + subtag = __subtagMappings[subtag]; + } else if (__extlangMappings.hasOwnProperty(subtag)) { + subtag = __extlangMappings[subtag][0]; + if (i === 1 && __extlangMappings[subtag][1] === subtags[0]) { + subtags.shift(); + i--; } + } + subtags[i] = subtag; + i++; + } + var normal = subtags.slice(0, i).join("-"); - var subtags = locale.split("-"); - var i = 0; + // 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 = subtags.slice(extensionStart, i).join("-"); + extensions.push(extension); + } + extensions.sort(); - // handle standard part: all subtags before first singleton or "x" - while (i < subtags.length) { - var subtag = subtags[i]; - if (subtag.length === 1 && (i > 0 || subtag === "x")) { - break; - } else if (i !== 0 && subtag.length === 2) { - subtag = subtag.toUpperCase(); - } else if (subtag.length === 4) { - subtag = subtag[0].toUpperCase() + subtag.substring(1).toLowerCase(); - } - if (__subtagMappings.hasOwnProperty(subtag)) { - subtag = __subtagMappings[subtag]; - } else if (__extlangMappings.hasOwnProperty(subtag)) { - subtag = __extlangMappings[subtag][0]; - if (i === 1 && __extlangMappings[subtag][1] === subtags[0]) { - subtags.shift(); - i--; - } - } - subtags[i] = subtag; - i++; - } - var normal = subtags.slice(0, i).join("-"); - - // 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 = 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 = normal; - if (extensions.length > 0) { - canonical += "-" + extensions.join("-"); - } - if (privateUse !== undefined) { - if (canonical.length > 0) { - canonical += "-" + privateUse; - } else { - canonical = privateUse; - } - } - - return canonical; + // handle private use + var privateUse; + if (i < subtags.length) { + privateUse = subtags.slice(i).join("-"); } - return typeof locale === "string" && isStructurallyValidLanguageTag(locale) && - canonicalizeLanguageTag(locale) === locale; + // put everything back together + var canonical = normal; + 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; } @@ -665,124 +665,124 @@ function isCanonicalizedStructurallyValidLanguageTag(locale) { * @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}. + * @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}. * @return {boolean} whether the test succeeded. */ 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 isOptional = testOptions !== undefined && testOptions.isOptional === true; + var noReturn = testOptions !== undefined && testOptions.noReturn === true; + var isILD = testOptions !== undefined && testOptions.isILD === true; - 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 + "."); - } + 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]; }); + } } + } - // 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 + "."); - } - } + 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."); + } + } } + }); - return true; + // 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 + "."); + } + } + } + } + + return true; } @@ -792,25 +792,25 @@ function testOption(Constructor, property, type, values, fallback, testOptions) * @param {Object} obj the object to be tested. * @param {string} property the name of the property * @param {Function|Array} valid either a function that tests value for validity and returns a boolean, - * an array of valid values. + * an array of valid values. * @exception if the property has an invalid value. */ function testProperty(obj, property, valid) { - var desc = Object.getOwnPropertyDescriptor(obj, property); - if (!desc.writable) { - $ERROR("Property " + property + " must be writable."); - } - if (!desc.enumerable) { - $ERROR("Property " + property + " must be enumerable."); - } - if (!desc.configurable) { - $ERROR("Property " + property + " must be configurable."); - } - var value = desc.value; - var isValid = (typeof valid === "function") ? valid(value) : (valid.indexOf(value) !== -1); - if (!isValid) { - $ERROR("Property value " + value + " is not allowed for property " + property + "."); - } + var desc = Object.getOwnPropertyDescriptor(obj, property); + if (!desc.writable) { + $ERROR("Property " + property + " must be writable."); + } + if (!desc.enumerable) { + $ERROR("Property " + property + " must be enumerable."); + } + if (!desc.configurable) { + $ERROR("Property " + property + " must be configurable."); + } + var value = desc.value; + var isValid = (typeof valid === "function") ? valid(value) : (valid.indexOf(value) !== -1); + if (!isValid) { + $ERROR("Property value " + value + " is not allowed for property " + property + "."); + } } @@ -820,13 +820,13 @@ function testProperty(obj, property, valid) { * @param {Object} obj the object to be tested. * @param {string} property the name of the property * @param {Function|Array} valid either a function that tests value for validity and returns a boolean, - * an array of valid values. + * an array of valid values. * @exception if the property is present and has an invalid value. */ function mayHaveProperty(obj, property, valid) { - if (obj.hasOwnProperty(property)) { - testProperty(obj, property, valid); - } + if (obj.hasOwnProperty(property)) { + testProperty(obj, property, valid); + } } @@ -836,14 +836,14 @@ function mayHaveProperty(obj, property, valid) { * @param {Object} obj the object to be tested. * @param {string} property the name of the property * @param {Function|Array} valid either a function that tests value for validity and returns a boolean, - * an array of valid values. + * an array of valid values. * @exception if the property is missing or has an invalid value. */ function mustHaveProperty(obj, property, valid) { - if (!obj.hasOwnProperty(property)) { - $ERROR("Object is missing property " + property + "."); - } - testProperty(obj, property, valid); + if (!obj.hasOwnProperty(property)) { + $ERROR("Object is missing property " + property + "."); + } + testProperty(obj, property, valid); } @@ -854,9 +854,9 @@ function mustHaveProperty(obj, property, valid) { * @exception if the property is present. */ function mustNotHaveProperty(obj, property) { - if (obj.hasOwnProperty(property)) { - $ERROR("Object has property it mustn't have: " + property + "."); - } + if (obj.hasOwnProperty(property)) { + $ERROR("Object has property it mustn't have: " + property + "."); + } } @@ -866,16 +866,16 @@ function mustNotHaveProperty(obj, property) { * 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" + "$_", "$*", "$&", "$+", "$`", "$'", + "input", "lastMatch", "lastParen", "leftContext", "rightContext" ]; var regExpPropertiesDefaultValues = (function () { - var values = Object.create(null); - regExpProperties.forEach(function (property) { - values[property] = RegExp[property]; - }); - return values; + var values = Object.create(null); + regExpProperties.forEach(function (property) { + values[property] = RegExp[property]; + }); + return values; }()); @@ -885,16 +885,16 @@ var regExpPropertiesDefaultValues = (function () { * RegExp constructor. */ function testForUnwantedRegExpChanges(testFunc) { - regExpProperties.forEach(function (property) { - RegExp[property] = regExpPropertiesDefaultValues[property]; - }); - testFunc(); - regExpProperties.forEach(function (property) { - if (RegExp[property] !== regExpPropertiesDefaultValues[property]) { - $ERROR("RegExp has unexpected property " + property + " with value " + - RegExp[property] + "."); - } - }); + regExpProperties.forEach(function (property) { + RegExp[property] = regExpPropertiesDefaultValues[property]; + }); + testFunc(); + regExpProperties.forEach(function (property) { + if (RegExp[property] !== regExpPropertiesDefaultValues[property]) { + $ERROR("RegExp has unexpected property " + property + " with value " + + RegExp[property] + "."); + } + }); } @@ -903,84 +903,84 @@ function testForUnwantedRegExpChanges(testFunc) { * 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. + * allowed for use in the ECMAScript Internationalization API. */ function isValidNumberingSystem(name) { - - // source: CLDR file common/bcp47/number.xml; version CLDR 21. - var numberingSystems = [ - "arab", - "arabext", - "armn", - "armnlow", - "bali", - "beng", - "brah", - "cakm", - "cham", - "deva", - "ethi", - "finance", - "fullwide", - "geor", - "grek", - "greklow", - "gujr", - "guru", - "hanidec", - "hans", - "hansfin", - "hant", - "hantfin", - "hebr", - "java", - "jpan", - "jpanfin", - "kali", - "khmr", - "knda", - "osma", - "lana", - "lanatham", - "laoo", - "latn", - "lepc", - "limb", - "mlym", - "mong", - "mtei", - "mymr", - "mymrshan", - "native", - "nkoo", - "olck", - "orya", - "roman", - "romanlow", - "saur", - "shrd", - "sora", - "sund", - "talu", - "takr", - "taml", - "tamldec", - "telu", - "thai", - "tibt", - "traditio", - "vaii" - ]; - - var excluded = [ - "finance", - "native", - "traditio" - ]; - - - return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1; + + // source: CLDR file common/bcp47/number.xml; version CLDR 21. + var numberingSystems = [ + "arab", + "arabext", + "armn", + "armnlow", + "bali", + "beng", + "brah", + "cakm", + "cham", + "deva", + "ethi", + "finance", + "fullwide", + "geor", + "grek", + "greklow", + "gujr", + "guru", + "hanidec", + "hans", + "hansfin", + "hant", + "hantfin", + "hebr", + "java", + "jpan", + "jpanfin", + "kali", + "khmr", + "knda", + "osma", + "lana", + "lanatham", + "laoo", + "latn", + "lepc", + "limb", + "mlym", + "mong", + "mtei", + "mymr", + "mymrshan", + "native", + "nkoo", + "olck", + "orya", + "roman", + "romanlow", + "saur", + "shrd", + "sora", + "sund", + "talu", + "takr", + "taml", + "tamldec", + "telu", + "thai", + "tibt", + "traditio", + "vaii" + ]; + + var excluded = [ + "finance", + "native", + "traditio" + ]; + + + return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1; } @@ -990,26 +990,26 @@ function isValidNumberingSystem(name) { */ var numberingSystemDigits = { - arab: "٠١٢٣٤٥٦٧٨٩", - arabext: "۰۱۲۳۴۵۶۷۸۹", - beng: "০১২৩৪৫৬৭৮৯", - deva: "०१२३४५६७८९", - fullwide: "0123456789", - gujr: "૦૧૨૩૪૫૬૭૮૯", - guru: "੦੧੨੩੪੫੬੭੮੯", - hanidec: "〇一二三四五六七八九", - khmr: "០១២៣៤៥៦៧៨៩", - knda: "೦೧೨೩೪೫೬೭೮೯", - laoo: "໐໑໒໓໔໕໖໗໘໙", - latn: "0123456789", - mlym: "൦൧൨൩൪൫൬൭൮൯", - mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙", - mymr: "၀၁၂၃၄၅၆၇၈၉", - orya: "୦୧୨୩୪୫୬୭୮୯", - tamldec: "௦௧௨௩௪௫௬௭௮௯", - telu: "౦౧౨౩౪౫౬౭౮౯", - thai: "๐๑๒๓๔๕๖๗๘๙", - tibt: "༠༡༢༣༤༥༦༧༨༩" + arab: "٠١٢٣٤٥٦٧٨٩", + arabext: "۰۱۲۳۴۵۶۷۸۹", + beng: "০১২৩৪৫৬৭৮৯", + deva: "०१२३४५६७८९", + fullwide: "0123456789", + gujr: "૦૧૨૩૪૫૬૭૮૯", + guru: "੦੧੨੩੪੫੬੭੮੯", + hanidec: "〇一二三四五六七八九", + khmr: "០១២៣៤៥៦៧៨៩", + knda: "೦೧೨೩೪೫೬೭೮೯", + laoo: "໐໑໒໓໔໕໖໗໘໙", + latn: "0123456789", + mlym: "൦൧൨൩൪൫൬൭൮൯", + mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙", + mymr: "၀၁၂၃၄၅၆၇၈၉", + orya: "୦୧୨୩୪୫୬୭୮୯", + tamldec: "௦௧௨௩௪௫௬௭௮௯", + telu: "౦౧౨౩౪౫౬౭౮౯", + thai: "๐๑๒๓๔๕๖๗๘๙", + tibt: "༠༡༢༣༤༥༦༧༨༩" }; @@ -1020,75 +1020,75 @@ var numberingSystemDigits = { * @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. + * 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. + * 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 + "."); - } - }); - } + 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 + "."); + } + }); + } }); + }); } @@ -1098,7 +1098,7 @@ function testNumberFormat(locales, numberingSystems, options, testData) { */ function getDateTimeComponents() { - return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"]; + return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"]; } @@ -1110,24 +1110,24 @@ function getDateTimeComponents() { */ 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; + + 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; } @@ -1140,10 +1140,10 @@ function getDateTimeComponentValues(component) { */ function testValidDateTimeComponentValue(component, value) { - if (getDateTimeComponentValues(component).indexOf(value) === -1) { - $ERROR("Invalid value " + value + " for date-time component " + component + "."); - } - return true; + if (getDateTimeComponentValues(component).indexOf(value) === -1) { + $ERROR("Invalid value " + value + " for date-time component " + component + "."); + } + return true; } @@ -1157,30 +1157,30 @@ function testValidDateTimeComponentValue(component, value) { */ 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|Canada/East-Saskatchewan"; - var zoneNamePattern = new RegExp("^(?:" + fileName + "|" + legacyName + ")$"); + /** + * 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|Canada/East-Saskatchewan"; + 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); + 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); } @@ -1193,13 +1193,12 @@ function isCanonicalizedStructurallyValidTimeZoneName(timeZone) { * @exception if the test fails. */ function testArraysAreSame(expected, actual) { - var i; - for (i = 0; i < Math.max(actual.length, expected.length); i++) { - if (actual[i] !== expected[i]) { - $ERROR("Result array element at index " + i + " should be \"" + - expected[i] + "\" but is \"" + actual[i] + "\"."); - } + var i; + for (i = 0; i < Math.max(actual.length, expected.length); i++) { + if (actual[i] !== expected[i]) { + $ERROR("Result array element at index " + i + " should be \"" + + expected[i] + "\" but is \"" + actual[i] + "\"."); } - return true; + } + return true; } - diff --git a/harness/timer.js b/harness/timer.js index 4dddbb3a1b..f1089108be 100644 --- a/harness/timer.js +++ b/harness/timer.js @@ -1,22 +1,23 @@ //setTimeout is not available, hence this script was loaded -if(Promise === undefined && this.setTimeout === undefined){ - if(/\$DONE()/.test(code)) - $ERROR("Async test capability is not supported in your test environment"); +if (Promise === undefined && this.setTimeout === undefined) { + if(/\$DONE()/.test(code)) + $ERROR("Async test capability is not supported in your test environment"); } -if(Promise !== undefined && this.setTimeout === undefined) - (function(that){ - that.setTimeout = function(callback, delay) { - var p = Promise.resolve(); - var start = Date.now(); - var end = start + delay; - function check(){ - var timeLeft = end - Date.now(); - if(timeLeft > 0) - p.then(check); - else - callback(); - } - p.then(check); - } - })(this); \ No newline at end of file +if (Promise !== undefined && this.setTimeout === undefined) { + (function(that) { + that.setTimeout = function(callback, delay) { + var p = Promise.resolve(); + var start = Date.now(); + var end = start + delay; + function check(){ + var timeLeft = end - Date.now(); + if(timeLeft > 0) + p.then(check); + else + callback(); + } + p.then(check); + } + })(this); +} diff --git a/tools/CoverageAnalyzer.py b/tools/CoverageAnalyzer.py index e79ab7f38d..e1a8413db6 100644 --- a/tools/CoverageAnalyzer.py +++ b/tools/CoverageAnalyzer.py @@ -1,61 +1,61 @@ -# Copyright (c) 2012 Ecma International. All rights reserved. -# This code is governed by the BSD license found in the LICENSE file. - - -#--IMPORTS--------------------------------------------------------------------- -import os -import sys - -#--GLOBALS--------------------------------------------------------------------- -CVG_DICT = {} - -#--HELPERS--------------------------------------------------------------------- -def getCoverageData(directory): - tempList = os.listdir(directory) - #Build up a list of directories under directory - dirList = [x for x in tempList if os.path.isdir(os.path.join(directory, x))] - #Build up a list of JavaScript files under the current directory - jsList = [x for xin in tempList if x.endswith(".js")] - - #If the directory contains JavaScript files we'll assume they're all test - #cases - if len(jsList)!=0: - CVG_DICT[os.path.split(directory)[1]] = len(jsList) - - #This might have just been a directory containing other dirs. Call ourself on - #it as well - for x in dirList: - getCoverageData(os.path.join(directory, x)) - - -def emitCoverageData(cvgDict): - totalTests = 0 - totalSections = 0 - keyList = cvgDict.keys() - keyList.sort(chapterCompare) - for cvgKey in keyList: - print cvgKey, ",", cvgDict[cvgKey] - totalSections+=1 - totalTests+=cvgDict[cvgKey] - print - print "Total number of tests is:", totalTests, "." - print "These tests cover", totalSections, "ECMAScript 5 sections." - - -def chapterCompare(x, y): - if ("." in x) and ("." in y): - try: - x1 = int(x[0:x.index(".")]) - y1 = int(y[0:y.index(".")]) - if x1==y1: - return chapterCompare(x[x.index(".")+1:], y[y.index(".")+1:]) - return cmp(x1, y1) - except ValueError: - pass - return cmp(x, y) - -#--MAIN------------------------------------------------------------------------ -startDir = sys.argv[1] -getCoverageData(startDir) -print "Emitting ECMAScript 5 coverage data for", startDir, "..." -emitCoverageData(CVG_DICT) +# Copyright (c) 2012 Ecma International. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + + +#--IMPORTS--------------------------------------------------------------------- +import os +import sys + +#--GLOBALS--------------------------------------------------------------------- +CVG_DICT = {} + +#--HELPERS--------------------------------------------------------------------- +def getCoverageData(directory): + tempList = os.listdir(directory) + #Build up a list of directories under directory + dirList = [x for x in tempList if os.path.isdir(os.path.join(directory, x))] + #Build up a list of JavaScript files under the current directory + jsList = [x for xin in tempList if x.endswith(".js")] + + #If the directory contains JavaScript files we'll assume they're all test + #cases + if len(jsList)!=0: + CVG_DICT[os.path.split(directory)[1]] = len(jsList) + + #This might have just been a directory containing other dirs. Call ourself on + #it as well + for x in dirList: + getCoverageData(os.path.join(directory, x)) + + +def emitCoverageData(cvgDict): + totalTests = 0 + totalSections = 0 + keyList = cvgDict.keys() + keyList.sort(chapterCompare) + for cvgKey in keyList: + print cvgKey, ",", cvgDict[cvgKey] + totalSections+=1 + totalTests+=cvgDict[cvgKey] + print + print "Total number of tests is:", totalTests, "." + print "These tests cover", totalSections, "ECMAScript 5 sections." + + +def chapterCompare(x, y): + if ("." in x) and ("." in y): + try: + x1 = int(x[0:x.index(".")]) + y1 = int(y[0:y.index(".")]) + if x1==y1: + return chapterCompare(x[x.index(".")+1:], y[y.index(".")+1:]) + return cmp(x1, y1) + except ValueError: + pass + return cmp(x, y) + +#--MAIN------------------------------------------------------------------------ +startDir = sys.argv[1] +getCoverageData(startDir) +print "Emitting ECMAScript 5 coverage data for", startDir, "..." +emitCoverageData(CVG_DICT)