Last active
January 15, 2016 10:14
-
-
Save avdg/3359a388aedaf55df7fe to your computer and use it in GitHub Desktop.
UglifyJS codegen fail example with getters and setters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var UglifyJS = require("uglify-js"); // Or wherever UglifyJS is | |
var test = "var strict_mode = false;\nfunction testRun(id, path, description, codeString, result, error) {\n if (result!==\"pass\") {\n throw new Error(\"Test \'\" + path + \"\'failed: \" + error);\n }\n}\n\nfunction testFinished() {\n \/\/no-op\n}\nfunction compareArray(aExpected, aActual) {\n if (aActual.length != aExpected.length) {\n return false;\n }\n\n aExpected.sort();\n aActual.sort();\n\n var s;\n for (var i = 0; i < aExpected.length; i++) {\n if (aActual[i] !== aExpected[i]) {\n return false;\n }\n }\n return true;\n}\n\n\/\/-----------------------------------------------------------------------------\nfunction arrayContains(arr, expected) {\n var found;\n for (var i = 0; i < expected.length; i++) {\n found = false;\n for (var j = 0; j < arr.length; j++) {\n if (expected[i] === arr[j]) {\n found = true;\n break;\n }\n }\n if (!found) {\n return false;\n }\n }\n return true;\n}\n\n\/\/-----------------------------------------------------------------------------\nvar supportsArrayIndexGettersOnArrays = undefined;\nfunction fnSupportsArrayIndexGettersOnArrays() {\n if (typeof supportsArrayIndexGettersOnArrays !== \"undefined\") {\n return supportsArrayIndexGettersOnArrays;\n }\n\n supportsArrayIndexGettersOnArrays = false;\n\n if (fnExists(Object.defineProperty)) {\n var arr = [];\n Object.defineProperty(arr, \"0\", {\n get: function() {\n supportsArrayIndexGettersOnArrays = true;\n return 0;\n }\n });\n var res = arr[0];\n }\n\n return supportsArrayIndexGettersOnArrays;\n}\n\n\/\/-----------------------------------------------------------------------------\nvar supportsArrayIndexGettersOnObjects = undefined;\nfunction fnSupportsArrayIndexGettersOnObjects() {\n if (typeof supportsArrayIndexGettersOnObjects !== \"undefined\")\n return supportsArrayIndexGettersOnObjects;\n\n supportsArrayIndexGettersOnObjects = false;\n\n if (fnExists(Object.defineProperty)) {\n var obj = {};\n Object.defineProperty(obj, \"0\", {\n get: function() {\n supportsArrayIndexGettersOnObjects = true;\n return 0;\n }\n });\n var res = obj[0];\n }\n\n return supportsArrayIndexGettersOnObjects;\n}\n\n\/\/-----------------------------------------------------------------------------\nfunction ConvertToFileUrl(pathStr) {\n return \"file:\" + pathStr.replace(\/\\\\\/g, \"\/\");\n}\n\n\/\/-----------------------------------------------------------------------------\nfunction fnExists(\/*arguments*\/) {\n for (var i = 0; i < arguments.length; i++) {\n if (typeof (arguments[i]) !== \"function\") return false;\n }\n return true;\n}\n\n\/\/-----------------------------------------------------------------------------\nvar __globalObject = Function(\"return this;\")();\nfunction fnGlobalObject() {\n return __globalObject;\n}\n\n\/\/-----------------------------------------------------------------------------\nfunction fnSupportsStrict() {\n \"use strict\";\n try {\n eval(\'with ({}) {}\');\n return false;\n } catch (e) {\n return true;\n }\n}\n\n\/\/-----------------------------------------------------------------------------\n\/\/Verify all attributes specified data property of given object:\n\/\/value, writable, enumerable, configurable\n\/\/If all attribute values are expected, return true, otherwise, return false\nfunction dataPropertyAttributesAreCorrect(obj,\n name,\n value,\n writable,\n enumerable,\n configurable) {\n var attributesCorrect = true;\n\n if (obj[name] !== value) {\n if (typeof obj[name] === \"number\" &&\n isNaN(obj[name]) &&\n typeof value === \"number\" &&\n isNaN(value)) {\n \/\/ keep empty\n } else {\n attributesCorrect = false;\n }\n }\n\n try {\n if (obj[name] === \"oldValue\") {\n obj[name] = \"newValue\";\n } else {\n obj[name] = \"OldValue\";\n }\n } catch (we) {\n }\n\n var overwrited = false;\n if (obj[name] !== value) {\n if (typeof obj[name] === \"number\" &&\n isNaN(obj[name]) &&\n typeof value === \"number\" &&\n isNaN(value)) {\n \/\/ keep empty\n } else {\n overwrited = true;\n }\n }\n if (overwrited !== writable) {\n attributesCorrect = false;\n }\n\n var enumerated = false;\n for (var prop in obj) {\n if (obj.hasOwnProperty(prop) && prop === name) {\n enumerated = true;\n }\n }\n\n if (enumerated !== enumerable) {\n attributesCorrect = false;\n }\n\n\n var deleted = false;\n\n try {\n delete obj[name];\n } catch (de) {\n }\n if (!obj.hasOwnProperty(name)) {\n deleted = true;\n }\n if (deleted !== configurable) {\n attributesCorrect = false;\n }\n\n return attributesCorrect;\n}\n\n\/\/-----------------------------------------------------------------------------\n\/\/Verify all attributes specified accessor property of given object:\n\/\/get, set, enumerable, configurable\n\/\/If all attribute values are expected, return true, otherwise, return false\nfunction accessorPropertyAttributesAreCorrect(obj,\n name,\n get,\n set,\n setVerifyHelpProp,\n enumerable,\n configurable) {\n var attributesCorrect = true;\n\n if (get !== undefined) {\n if (obj[name] !== get()) {\n if (typeof obj[name] === \"number\" &&\n isNaN(obj[name]) &&\n typeof get() === \"number\" &&\n isNaN(get())) {\n \/\/ keep empty\n } else {\n attributesCorrect = false;\n }\n }\n } else {\n if (obj[name] !== undefined) {\n attributesCorrect = false;\n }\n }\n\n try {\n var desc = Object.getOwnPropertyDescriptor(obj, name);\n if (typeof desc.set === \"undefined\") {\n if (typeof set !== \"undefined\") {\n attributesCorrect = false;\n }\n } else {\n obj[name] = \"toBeSetValue\";\n if (obj[setVerifyHelpProp] !== \"toBeSetValue\") {\n attributesCorrect = false;\n }\n }\n } catch (se) {\n throw se;\n }\n\n\n var enumerated = false;\n for (var prop in obj) {\n if (obj.hasOwnProperty(prop) && prop === name) {\n enumerated = true;\n }\n }\n\n if (enumerated !== enumerable) {\n attributesCorrect = false;\n }\n\n\n var deleted = false;\n try {\n delete obj[name];\n } catch (de) {\n throw de;\n }\n if (!obj.hasOwnProperty(name)) {\n deleted = true;\n }\n if (deleted !== configurable) {\n attributesCorrect = false;\n }\n\n return attributesCorrect;\n}\n\n\/\/-----------------------------------------------------------------------------\nvar NotEarlyErrorString = \"NotEarlyError\";\nvar EarlyErrorRePat = \"^((?!\" + NotEarlyErrorString + \").)*$\";\nvar NotEarlyError = new Error(NotEarlyErrorString);\n\n\/\/-----------------------------------------------------------------------------\n\/\/ Copyright 2009 the Sputnik authors. All rights reserved.\n\/\/ This code is governed by the BSD license found in the LICENSE file.\n\nfunction Test262Error(message) {\n if (message) this.message = message;\n}\n\nTest262Error.prototype.toString = function () {\n return \"Test262 Error: \" + this.message;\n};\n\nfunction testFailed(message) {\n throw new Test262Error(message);\n}\n\n\nfunction testPrint(message) {\n\n}\n\n\n\/\/adaptors for Test262 framework\nfunction $PRINT(message) {\n\n}\n\nfunction $INCLUDE(message) { }\nfunction $ERROR(message) {\n testFailed(message);\n}\n\nfunction $FAIL(message) {\n testFailed(message);\n}\n\n\n\n\/\/Sputnik library definitions\n\/\/Ultimately these should be namespaced some how and only made\n\/\/available to tests that explicitly include them.\n\/\/For now, we just define the globally\n\n\/\/math_precision.js\n\/\/ Copyright 2009 the Sputnik authors. All rights reserved.\n\/\/ This code is governed by the BSD license found in the LICENSE file.\n\nfunction getPrecision(num) {\n \/\/TODO: Create a table of prec\'s,\n \/\/ because using Math for testing Math isn\'t that correct.\n\n var log2num = Math.log(Math.abs(num)) \/ Math.LN2;\n var pernum = Math.ceil(log2num);\n return (2 * Math.pow(2, -52 + pernum));\n \/\/return(0);\n}\n\n\n\/\/math_isequal.js\n\/\/ Copyright 2009 the Sputnik authors. All rights reserved.\n\/\/ This code is governed by the BSD license found in the LICENSE file.\n\nvar prec;\nfunction isEqual(num1, num2) {\n if ((num1 === Infinity) && (num2 === Infinity)) {\n return (true);\n }\n if ((num1 === -Infinity) && (num2 === -Infinity)) {\n return (true);\n }\n prec = getPrecision(Math.min(Math.abs(num1), Math.abs(num2)));\n return (Math.abs(num1 - num2) <= prec);\n \/\/return(num1 === num2);\n}\n\n\/\/numeric_conversion.js\n\/\/ Copyright 2009 the Sputnik authors. All rights reserved.\n\/\/ This code is governed by the BSD license found in the LICENSE file.\n\nfunction ToInteger(p) {\n var x = Number(p);\n\n if (isNaN(x)) {\n return +0;\n }\n\n if ((x === +0)\n || (x === -0)\n || (x === Number.POSITIVE_INFINITY)\n || (x === Number.NEGATIVE_INFINITY)) {\n return x;\n }\n\n var sign = (x < 0) ? -1 : 1;\n\n return (sign * Math.floor(Math.abs(x)));\n}\n\n\/\/Date_constants.js\n\/\/ Copyright 2009 the Sputnik authors. All rights reserved.\n\/\/ This code is governed by the BSD license found in the LICENSE file.\n\nvar HoursPerDay = 24;\nvar MinutesPerHour = 60;\nvar SecondsPerMinute = 60;\n\nvar msPerDay = 86400000;\nvar msPerSecond = 1000;\nvar msPerMinute = 60000;\nvar msPerHour = 3600000;\n\nvar date_1899_end = -2208988800001;\nvar date_1900_start = -2208988800000;\nvar date_1969_end = -1;\nvar date_1970_start = 0;\nvar date_1999_end = 946684799999;\nvar date_2000_start = 946684800000;\nvar date_2099_end = 4102444799999;\nvar date_2100_start = 4102444800000;\n\n\/\/ Copyright 2009 the Sputnik authors. All rights reserved.\n\/\/ This code is governed by the BSD license found in the LICENSE file.\n\n\/\/the following values are normally generated by the sputnik.py driver\nvar $LocalTZ,\n $DST_start_month,\n $DST_start_sunday,\n $DST_start_hour,\n $DST_start_minutes,\n $DST_end_month,\n $DST_end_sunday,\n $DST_end_hour,\n $DST_end_minutes;\n\n(function () {\n \/**\n * Finds the first date, starting from |start|, where |predicate|\n * holds.\n *\/\n var findNearestDateBefore = function(start, predicate) {\n var current = start;\n var month = 1000 * 60 * 60 * 24 * 30;\n for (var step = month; step > 0; step = Math.floor(step \/ 3)) {\n if (!predicate(current)) {\n while (!predicate(current))\n current = new Date(current.getTime() + step);\n current = new Date(current.getTime() - step);\n }\n }\n while (!predicate(current)) {\n current = new Date(current.getTime() + 1);\n }\n return current;\n };\n\n var juneDate = new Date(2000, 5, 20, 0, 0, 0, 0);\n var decemberDate = new Date(2000, 11, 20, 0, 0, 0, 0);\n var juneOffset = juneDate.getTimezoneOffset();\n var decemberOffset = decemberDate.getTimezoneOffset();\n var isSouthernHemisphere = (juneOffset > decemberOffset);\n var winterTime = isSouthernHemisphere ? juneDate : decemberDate;\n var summerTime = isSouthernHemisphere ? decemberDate : juneDate;\n\n var dstStart = findNearestDateBefore(winterTime, function (date) {\n return date.getTimezoneOffset() == summerTime.getTimezoneOffset();\n });\n $DST_start_month = dstStart.getMonth();\n $DST_start_sunday = dstStart.getDate() > 15 ? \'\"last\"\' : \'\"first\"\';\n $DST_start_hour = dstStart.getHours();\n $DST_start_minutes = dstStart.getMinutes();\n\n var dstEnd = findNearestDateBefore(summerTime, function (date) {\n return date.getTimezoneOffset() == winterTime.getTimezoneOffset();\n });\n $DST_end_month = dstEnd.getMonth();\n $DST_end_sunday = dstEnd.getDate() > 15 ? \'\"last\"\' : \'\"first\"\';\n $DST_end_hour = dstEnd.getHours();\n $DST_end_minutes = dstEnd.getMinutes();\n\n return;\n})();\n\n\n\/\/Date.library.js\n\/\/ Copyright 2009 the Sputnik authors. All rights reserved.\n\/\/ This code is governed by the BSD license found in the LICENSE file.\n\n\/\/15.9.1.2 Day Number and Time within Day\nfunction Day(t) {\n return Math.floor(t\/msPerDay);\n}\n\nfunction TimeWithinDay(t) {\n return t%msPerDay;\n}\n\n\/\/15.9.1.3 Year Number\nfunction DaysInYear(y){\n if(y%4 != 0) return 365;\n if(y%4 == 0 && y%100 != 0) return 366;\n if(y%100 == 0 && y%400 != 0) return 365;\n if(y%400 == 0) return 366;\n}\n\nfunction DayFromYear(y) {\n return (365*(y-1970)\n + Math.floor((y-1969)\/4)\n - Math.floor((y-1901)\/100)\n + Math.floor((y-1601)\/400));\n}\n\nfunction TimeFromYear(y){\n return msPerDay*DayFromYear(y);\n}\n\nfunction YearFromTime(t) {\n t = Number(t);\n var sign = ( t < 0 ) ? -1 : 1;\n var year = ( sign < 0 ) ? 1969 : 1970;\n\n for(var time = 0;;year += sign){\n time = TimeFromYear(year);\n\n if(sign > 0 && time > t){\n year -= sign;\n break;\n }\n else if(sign < 0 && time <= t){\n break;\n }\n };\n return year;\n}\n\nfunction InLeapYear(t){\n if(DaysInYear(YearFromTime(t)) == 365)\n return 0;\n\n if(DaysInYear(YearFromTime(t)) == 366)\n return 1;\n}\n\nfunction DayWithinYear(t) {\n return Day(t)-DayFromYear(YearFromTime(t));\n}\n\n\/\/15.9.1.4 Month Number\nfunction MonthFromTime(t){\n var day = DayWithinYear(t);\n var leap = InLeapYear(t);\n\n if((0 <= day) && (day < 31)) return 0;\n if((31 <= day) && (day < (59+leap))) return 1;\n if(((59+leap) <= day) && (day < (90+leap))) return 2;\n if(((90+leap) <= day) && (day < (120+leap))) return 3;\n if(((120+leap) <= day) && (day < (151+leap))) return 4;\n if(((151+leap) <= day) && (day < (181+leap))) return 5;\n if(((181+leap) <= day) && (day < (212+leap))) return 6;\n if(((212+leap) <= day) && (day < (243+leap))) return 7;\n if(((243+leap) <= day) && (day < (273+leap))) return 8;\n if(((273+leap) <= day) && (day < (304+leap))) return 9;\n if(((304+leap) <= day) && (day < (334+leap))) return 10;\n if(((334+leap) <= day) && (day < (365+leap))) return 11;\n}\n\n\/\/15.9.1.5 Date Number\nfunction DateFromTime(t) {\n var day = DayWithinYear(t);\n var month = MonthFromTime(t);\n var leap = InLeapYear(t);\n\n if(month == 0) return day+1;\n if(month == 1) return day-30;\n if(month == 2) return day-58-leap;\n if(month == 3) return day-89-leap;\n if(month == 4) return day-119-leap;\n if(month == 5) return day-150-leap;\n if(month == 6) return day-180-leap;\n if(month == 7) return day-211-leap;\n if(month == 8) return day-242-leap;\n if(month == 9) return day-272-leap;\n if(month == 10) return day-303-leap;\n if(month == 11) return day-333-leap;\n}\n\n\/\/15.9.1.6 Week Day\nfunction WeekDay(t) {\n var weekday = (Day(t)+4)%7;\n return (weekday < 0 ? 7+weekday : weekday);\n}\n\n\/\/15.9.1.9 Daylight Saving Time Adjustment\n$LocalTZ = (new Date()).getTimezoneOffset() \/ -60;\nif (DaylightSavingTA((new Date()).valueOf()) !== 0) {\n $LocalTZ -= 1;\n}\nvar LocalTZA = $LocalTZ*msPerHour;\n\nfunction DaysInMonth(m, leap) {\n m = m%12;\n\n \/\/April, June, Sept, Nov\n if(m == 3 || m == 5 || m == 8 || m == 10 ) {\n return 30;\n }\n\n \/\/Jan, March, May, July, Aug, Oct, Dec\n if(m == 0 || m == 2 || m == 4 || m == 6 || m == 7 || m == 9 || m == 11){\n return 31;\n }\n\n \/\/Feb\n return 28+leap;\n}\n\nfunction GetSundayInMonth(t, m, count){\n var year = YearFromTime(t);\n var tempDate;\n\n if (count===\'\"first\"\') {\n for (var d=1; d <= DaysInMonth(m, InLeapYear(t)); d++) {\n tempDate = new Date(year, m, d);\n if (tempDate.getDay()===0) {\n return tempDate.valueOf();\n }\n }\n } else if(count===\'\"last\"\') {\n for (var d=DaysInMonth(m, InLeapYear(t)); d>0; d--) {\n tempDate = new Date(year, m, d);\n if (tempDate.getDay()===0) {\n return tempDate.valueOf();\n }\n }\n }\n throw new Error(\"Unsupported \'count\' arg:\" + count);\n}\n\/*\nfunction GetSundayInMonth(t, m, count){\n var year = YearFromTime(t);\n var leap = InLeapYear(t);\n var day = 0;\n\n if(m >= 1) day += DaysInMonth(0, leap);\n if(m >= 2) day += DaysInMonth(1, leap);\n if(m >= 3) day += DaysInMonth(2, leap);\n if(m >= 4) day += DaysInMonth(3, leap);\n if(m >= 5) day += DaysInMonth(4, leap);\n if(m >= 6) day += DaysInMonth(5, leap);\n if(m >= 7) day += DaysInMonth(6, leap);\n if(m >= 8) day += DaysInMonth(7, leap);\n if(m >= 9) day += DaysInMonth(8, leap);\n if(m >= 10) day += DaysInMonth(9, leap);\n if(m >= 11) day += DaysInMonth(10, leap);\n\n var month_start = TimeFromYear(year)+day*msPerDay;\n var sunday = 0;\n\n if(count === \"last\"){\n for(var last_sunday = month_start+DaysInMonth(m, leap)*msPerDay;\n WeekDay(last_sunday)>0;\n last_sunday -= msPerDay\n ){};\n sunday = last_sunday;\n }\n else {\n for(var first_sunday = month_start;\n WeekDay(first_sunday)>0;\n first_sunday += msPerDay\n ){};\n sunday = first_sunday+7*msPerDay*(count-1);\n }\n\n return sunday;\n}*\/\n\nfunction DaylightSavingTA(t) {\n\/\/ t = t-LocalTZA;\n\n var DST_start = GetSundayInMonth(t, $DST_start_month, $DST_start_sunday) +\n $DST_start_hour*msPerHour +\n $DST_start_minutes*msPerMinute;\n\n var k = new Date(DST_start);\n\n var DST_end = GetSundayInMonth(t, $DST_end_month, $DST_end_sunday) +\n $DST_end_hour*msPerHour +\n $DST_end_minutes*msPerMinute;\n\n if ( t >= DST_start && t < DST_end ) {\n return msPerHour;\n } else {\n return 0;\n }\n}\n\n\/\/15.9.1.9 Local Time\nfunction LocalTime(t){\n return t+LocalTZA+DaylightSavingTA(t);\n}\n\nfunction UTC(t) {\n return t-LocalTZA-DaylightSavingTA(t-LocalTZA);\n}\n\n\/\/15.9.1.10 Hours, Minutes, Second, and Milliseconds\nfunction HourFromTime(t){\n return Math.floor(t\/msPerHour)%HoursPerDay;\n}\n\nfunction MinFromTime(t){\n return Math.floor(t\/msPerMinute)%MinutesPerHour;\n}\n\nfunction SecFromTime(t){\n return Math.floor(t\/msPerSecond)%SecondsPerMinute;\n}\n\nfunction msFromTime(t){\n return t%msPerSecond;\n}\n\n\/\/15.9.1.11 MakeTime (hour, min, sec, ms)\nfunction MakeTime(hour, min, sec, ms){\n if ( !isFinite(hour) || !isFinite(min) || !isFinite(sec) || !isFinite(ms)) {\n return Number.NaN;\n }\n\n hour = ToInteger(hour);\n min = ToInteger(min);\n sec = ToInteger(sec);\n ms = ToInteger(ms);\n\n return ((hour*msPerHour) + (min*msPerMinute) + (sec*msPerSecond) + ms);\n}\n\n\/\/15.9.1.12 MakeDay (year, month, date)\nfunction MakeDay(year, month, date) {\n if ( !isFinite(year) || !isFinite(month) || !isFinite(date)) {\n return Number.NaN;\n }\n\n year = ToInteger(year);\n month = ToInteger(month);\n date = ToInteger(date );\n\n var result5 = year + Math.floor(month\/12);\n var result6 = month%12;\n\n var sign = ( year < 1970 ) ? -1 : 1;\n var t = ( year < 1970 ) ? 1 : 0;\n var y = ( year < 1970 ) ? 1969 : 1970;\n\n if( sign == -1 ){\n for ( y = 1969; y >= year; y += sign ) {\n t += sign * DaysInYear(y)*msPerDay;\n }\n } else {\n for ( y = 1970 ; y < year; y += sign ) {\n t += sign * DaysInYear(y)*msPerDay;\n }\n }\n\n var leap = 0;\n for ( var m = 0; m < month; m++ ) {\n \/\/if year is changed, than we need to recalculate leep\n leap = InLeapYear(t);\n t += DaysInMonth(m, leap)*msPerDay;\n }\n\n if ( YearFromTime(t) != result5 ) {\n return Number.NaN;\n }\n if ( MonthFromTime(t) != result6 ) {\n return Number.NaN;\n }\n if ( DateFromTime(t) != 1 ) {\n return Number.NaN;\n }\n\n return Day(t)+date-1;\n}\n\n\/\/15.9.1.13 MakeDate (day, time)\nfunction MakeDate( day, time ) {\n if(!isFinite(day) || !isFinite(time)) {\n return Number.NaN;\n }\n\n return day*msPerDay+time;\n}\n\n\/\/15.9.1.14 TimeClip (time)\nfunction TimeClip(time) {\n if(!isFinite(time) || Math.abs(time) > 8.64e15){\n return Number.NaN;\n }\n\n return ToInteger(time);\n}\n\n\/\/Test Functions\n\/\/ConstructDate is considered deprecated, and should not be used directly from\n\/\/test262 tests as it\'s incredibly sensitive to DST start\/end dates that\n\/\/vary with geographic location.\nfunction ConstructDate(year, month, date, hours, minutes, seconds, ms){\n \/*\n * 1. Call ToNumber(year)\n * 2. Call ToNumber(month)\n * 3. If date is supplied use ToNumber(date); else use 1\n * 4. If hours is supplied use ToNumber(hours); else use 0\n * 5. If minutes is supplied use ToNumber(minutes); else use 0\n * 6. If seconds is supplied use ToNumber(seconds); else use 0\n * 7. If ms is supplied use ToNumber(ms); else use 0\n * 8. If Result(1) is not NaN and 0 <= ToInteger(Result(1)) <= 99, Result(8) is\n * 1900+ToInteger(Result(1)); otherwise, Result(8) is Result(1)\n * 9. Compute MakeDay(Result(8), Result(2), Result(3))\n * 10. Compute MakeTime(Result(4), Result(5), Result(6), Result(7))\n * 11. Compute MakeDate(Result(9), Result(10))\n * 12. Set the [[Value]] property of the newly constructed object to TimeClip(UTC(Result(11)))\n *\/\n var r1 = Number(year);\n var r2 = Number(month);\n var r3 = ((date && arguments.length > 2) ? Number(date) : 1);\n var r4 = ((hours && arguments.length > 3) ? Number(hours) : 0);\n var r5 = ((minutes && arguments.length > 4) ? Number(minutes) : 0);\n var r6 = ((seconds && arguments.length > 5) ? Number(seconds) : 0);\n var r7 = ((ms && arguments.length > 6) ? Number(ms) : 0);\n\n var r8 = r1;\n\n if(!isNaN(r1) && (0 <= ToInteger(r1)) && (ToInteger(r1) <= 99))\n r8 = 1900+r1;\n\n var r9 = MakeDay(r8, r2, r3);\n var r10 = MakeTime(r4, r5, r6, r7);\n var r11 = MakeDate(r9, r10);\n\n var retVal = TimeClip(UTC(r11));\n return retVal;\n}\n\n\n\n\/**** Python code for initialize the above constants\n\/\/ We may want to replicate the following in JavaScript.\n\/\/ However, using JS date operations to generate parameters that are then used to\n\/\/ test those some date operations seems unsound. However, it isn\'t clear if there\n\/\/is a good interoperable alternative.\n\n# Copyright 2009 the Sputnik authors. All rights reserved.\n# This code is governed by the BSD license found in the LICENSE file.\n\ndef GetDaylightSavingsTimes():\n# Is the given floating-point time in DST?\ndef IsDst(t):\nreturn time.localtime(t)[-1]\n# Binary search to find an interval between the two times no greater than\n# delta where DST switches, returning the midpoint.\ndef FindBetween(start, end, delta):\nwhile end - start > delta:\nmiddle = (end + start) \/ 2\nif IsDst(middle) == IsDst(start):\nstart = middle\nelse:\nend = middle\nreturn (start + end) \/ 2\nnow = time.time()\none_month = (30 * 24 * 60 * 60)\n# First find a date with different daylight savings. To avoid corner cases\n# we try four months before and after today.\nafter = now + 4 * one_month\nbefore = now - 4 * one_month\nif IsDst(now) == IsDst(before) and IsDst(now) == IsDst(after):\nlogger.warning(\"Was unable to determine DST info.\")\nreturn None\n# Determine when the change occurs between now and the date we just found\n# in a different DST.\nif IsDst(now) != IsDst(before):\nfirst = FindBetween(before, now, 1)\nelse:\nfirst = FindBetween(now, after, 1)\n# Determine when the change occurs between three and nine months from the\n# first.\nsecond = FindBetween(first + 3 * one_month, first + 9 * one_month, 1)\n# Find out which switch is into and which if out of DST\nif IsDst(first - 1) and not IsDst(first + 1):\nstart = second\nend = first\nelse:\nstart = first\nend = second\nreturn (start, end)\n\n\ndef GetDaylightSavingsAttribs():\ntimes = GetDaylightSavingsTimes()\nif not times:\nreturn None\n(start, end) = times\ndef DstMonth(t):\nreturn time.localtime(t)[1] - 1\ndef DstHour(t):\nreturn time.localtime(t - 1)[3] + 1\ndef DstSunday(t):\nif time.localtime(t)[2] > 15:\nreturn \"\'last\'\"\nelse:\nreturn \"\'first\'\"\ndef DstMinutes(t):\nreturn (time.localtime(t - 1)[4] + 1) % 60\nattribs = { }\nattribs[\'start_month\'] = DstMonth(start)\nattribs[\'end_month\'] = DstMonth(end)\nattribs[\'start_sunday\'] = DstSunday(start)\nattribs[\'end_sunday\'] = DstSunday(end)\nattribs[\'start_hour\'] = DstHour(start)\nattribs[\'end_hour\'] = DstHour(end)\nattribs[\'start_minutes\'] = DstMinutes(start)\nattribs[\'end_minutes\'] = DstMinutes(end)\nreturn attribs\n\n*********\/\n\n\/\/--Test case registration-----------------------------------------------------\nfunction runTestCase(testcase) {\n if (testcase() !== true) {\n $ERROR(\"Test case returned non-true value!\");\n }\n}\n\nif (this.window!==undefined) { \/\/for console support\n this.window.onerror = function(errorMsg, url, lineNumber) {\n this.window.iframeError = errorMsg;\n };\n}\n\n\/\/This doesn\'t work with early errors in current versions of Opera\n\/*\nif (\/opera\/i.test(navigator.userAgent)) {\n (function() {\n var origError = window.Error;\n window.Error = function() {\n if (arguments.length>0) {\n try {\n window.onerror(arguments[0]);\n } catch(e) {\n alert(\"Failed to invoke window.onerror (from ed.js)\");\n }\n }\n return origError.apply(this, arguments);\n }\n })();\n}*\/\n\/**\n * @description Tests that obj meets the requirements for built-in objects\n * defined by the introduction of chapter 15 of the ECMAScript Language Specification.\n * @param {Object} obj the object to be tested.\n * @param {boolean} isFunction whether the specification describes obj as a function.\n * @param {boolean} isConstructor whether the specification describes obj as a constructor.\n * @param {String[]} properties an array with the names of the built-in properties of obj,\n * excluding length, prototype, or properties with non-default attributes.\n * @param {number} length for functions only: the length specified for the function\n * or derived from the argument list.\n * @author Norbert Lindenberg\n *\/\n\nfunction testBuiltInObject(obj, isFunction, isConstructor, properties, length) {\n\n if (obj === undefined) {\n $ERROR(\"Object being tested is undefined.\");\n }\n\n var objString = Object.prototype.toString.call(obj);\n if (isFunction) {\n if (objString !== \"[object Function]\") {\n $ERROR(\"The [[Class]] internal property of a built-in function must be \" +\n \"\\\"Function\\\", but toString() returns \" + objString);\n }\n } else {\n if (objString !== \"[object Object]\") {\n $ERROR(\"The [[Class]] internal property of a built-in non-function object must be \" +\n \"\\\"Object\\\", but toString() returns \" + objString);\n }\n }\n\n if (!Object.isExtensible(obj)) {\n $ERROR(\"Built-in objects must be extensible.\");\n }\n\n if (isFunction && Object.getPrototypeOf(obj) !== Function.prototype) {\n $ERROR(\"Built-in functions must have Function.prototype as their prototype.\");\n }\n\n if (isConstructor && Object.getPrototypeOf(obj.prototype) !== Object.prototype) {\n $ERROR(\"Built-in prototype objects must have Object.prototype as their prototype.\");\n }\n\n \/\/ verification of the absence of the [[Construct]] internal property has\n \/\/ been moved to the end of the test\n\n \/\/ verification of the absence of the prototype property has\n \/\/ been moved to the end of the test\n\n if (isFunction) {\n\n if (typeof obj.length !== \"number\" || obj.length !== Math.floor(obj.length)) {\n $ERROR(\"Built-in functions must have a length property with an integer value.\");\n }\n\n if (obj.length !== length) {\n $ERROR(\"Function\'s length property doesn\'t have specified value; expected \" +\n length + \", got \" + obj.length + \".\");\n }\n\n var desc = Object.getOwnPropertyDescriptor(obj, \"length\");\n if (desc.writable) {\n $ERROR(\"The length property of a built-in function must not be writable.\");\n }\n if (desc.enumerable) {\n $ERROR(\"The length property of a built-in function must not be enumerable.\");\n }\n if (desc.configurable) {\n $ERROR(\"The length property of a built-in function must not be configurable.\");\n }\n }\n\n properties.forEach(function(prop) {\n var desc = Object.getOwnPropertyDescriptor(obj, prop);\n if (desc === undefined) {\n $ERROR(\"Missing property \" + prop + \".\");\n }\n \/\/ accessor properties don\'t have writable attribute\n if (desc.hasOwnProperty(\"writable\") && !desc.writable) {\n $ERROR(\"The \" + prop + \" property of this built-in function must be writable.\");\n }\n if (desc.enumerable) {\n $ERROR(\"The \" + prop + \" property of this built-in function must not be enumerable.\");\n }\n if (!desc.configurable) {\n $ERROR(\"The \" + prop + \" property of this built-in function must be configurable.\");\n }\n });\n\n \/\/ The remaining sections have been moved to the end of the test because\n \/\/ unbound non-constructor functions written in JavaScript cannot possibly\n \/\/ pass them, and we still want to test JavaScript implementations as much\n \/\/ as possible.\n\n var exception;\n if (isFunction && !isConstructor) {\n \/\/ this is not a complete test for the presence of [[Construct]]:\n \/\/ if it\'s absent, the exception must be thrown, but it may also\n \/\/ be thrown if it\'s present and just has preconditions related to\n \/\/ arguments or the this value that this statement doesn\'t meet.\n try {\n \/*jshint newcap:false*\/\n var instance = new obj();\n } catch (e) {\n exception = e;\n }\n if (exception === undefined || exception.name !== \"TypeError\") {\n $ERROR(\"Built-in functions that aren\'t constructors must throw TypeError when \" +\n \"used in a \\\"new\\\" statement.\");\n }\n }\n\n if (isFunction && !isConstructor && obj.hasOwnProperty(\"prototype\")) {\n $ERROR(\"Built-in functions that aren\'t constructors must not have a prototype property.\");\n }\n\n \/\/ passed the complete test!\n return true;\n}\n\n\n\/**\n * This file contains shared functions for the tests in the conformance test\n * suite for the ECMAScript Internationalization API.\n * @author Norbert Lindenberg\n *\/\n\n\n\/**\n * @description Calls the provided function for every service constructor in\n * the Intl object, until f returns a falsy value. It returns the result of the\n * last call to f, mapped to a boolean.\n * @param {Function} f the function to call for each service constructor in\n * the Intl object.\n * @param {Function} Constructor the constructor object to test with.\n * @result {Boolean} whether the test succeeded.\n *\/\nfunction testWithIntlConstructors(f) {\n var constructors = [\"Collator\", \"NumberFormat\", \"DateTimeFormat\"];\n return constructors.every(function (constructor) {\n var Constructor = Intl[constructor];\n var result;\n try {\n result = f(Constructor);\n } catch (e) {\n e.message += \" (Testing with \" + constructor + \".)\";\n throw e;\n }\n return result;\n });\n}\n\n\n\/**\n * Returns the name of the given constructor object, which must be one of\n * Intl.Collator, Intl.NumberFormat, or Intl.DateTimeFormat.\n * @param {object} Constructor a constructor\n * @return {string} the name of the constructor\n *\/\nfunction getConstructorName(Constructor) {\n switch (Constructor) {\n case Intl.Collator:\n return \"Collator\";\n case Intl.NumberFormat:\n return \"NumberFormat\";\n case Intl.DateTimeFormat:\n return \"DateTimeFormat\";\n default:\n $ERROR(\"test internal error: unknown Constructor\");\n }\n}\n\n\n\/**\n * Taints a named data property of the given object by installing\n * a setter that throws an exception.\n * @param {object} obj the object whose data property to taint\n * @param {string} property the property to taint\n *\/\nfunction taintDataProperty(obj, property) {\n Object.defineProperty(obj, property, {\n set: function(value) {\n $ERROR(\"Client code can adversely affect behavior: setter for \" + property + \".\");\n },\n enumerable: false,\n configurable: true\n });\n}\n\n\n\/**\n * Taints a named method of the given object by replacing it with a function\n * that throws an exception.\n * @param {object} obj the object whose method to taint\n * @param {string} property the name of the method to taint\n *\/\nfunction taintMethod(obj, property) {\n Object.defineProperty(obj, property, {\n value: function() {\n $ERROR(\"Client code can adversely affect behavior: method \" + property + \".\");\n },\n writable: true,\n enumerable: false,\n configurable: true\n });\n}\n\n\n\/**\n * Taints the given properties (and similarly named properties) by installing\n * setters on Object.prototype that throw exceptions.\n * @param {Array} properties an array of property names to taint\n *\/\nfunction taintProperties(properties) {\n properties.forEach(function (property) {\n var adaptedProperties = [property, \"__\" + property, \"_\" + property, property + \"_\", property + \"__\"];\n adaptedProperties.forEach(function (property) {\n taintDataProperty(Object.prototype, property);\n });\n });\n}\n\n\n\/**\n * Taints the Array object by creating a setter for the property \"0\" and\n * replacing some key methods with functions that throw exceptions.\n *\/\nfunction taintArray() {\n taintDataProperty(Array.prototype, \"0\");\n taintMethod(Array.prototype, \"indexOf\");\n taintMethod(Array.prototype, \"join\");\n taintMethod(Array.prototype, \"push\");\n taintMethod(Array.prototype, \"slice\");\n taintMethod(Array.prototype, \"sort\");\n}\n\n\n\/\/ auxiliary data for getLocaleSupportInfo\nvar languages = [\"zh\", \"es\", \"en\", \"hi\", \"ur\", \"ar\", \"ja\", \"pa\"];\nvar scripts = [\"Latn\", \"Hans\", \"Deva\", \"Arab\", \"Jpan\", \"Hant\"];\nvar countries = [\"CN\", \"IN\", \"US\", \"PK\", \"JP\", \"TW\", \"HK\", \"SG\"];\nvar localeSupportInfo = {};\n\n\n\/**\n * Gets locale support info for the given constructor object, which must be one\n * of Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat.\n * @param {object} Constructor the constructor for which to get locale support info\n * @return {object} locale support info with the following properties:\n * supported: array of fully supported language tags\n * byFallback: array of language tags that are supported through fallbacks\n * unsupported: array of unsupported language tags\n *\/\nfunction getLocaleSupportInfo(Constructor) {\n var constructorName = getConstructorName(Constructor);\n if (localeSupportInfo[constructorName] !== undefined) {\n return localeSupportInfo[constructorName];\n }\n\n var allTags = [];\n var i, j, k;\n var language, script, country;\n for (i = 0; i < languages.length; i++) {\n language = languages[i];\n allTags.push(language);\n for (j = 0; j < scripts.length; j++) {\n script = scripts[j];\n allTags.push(language + \"-\" + script);\n for (k = 0; k < countries.length; k++) {\n country = countries[k];\n allTags.push(language + \"-\" + script + \"-\" + country);\n }\n }\n for (k = 0; k < countries.length; k++) {\n country = countries[k];\n allTags.push(language + \"-\" + country);\n }\n }\n\n var supported = [];\n var byFallback = [];\n var unsupported = [];\n for (i = 0; i < allTags.length; i++) {\n var request = allTags[i];\n var result = new Constructor([request], {localeMatcher: \"lookup\"}).resolvedOptions().locale;\n if (request === result) {\n supported.push(request);\n } else if (request.indexOf(result) === 0) {\n byFallback.push(request);\n } else {\n unsupported.push(request);\n }\n }\n\n localeSupportInfo[constructorName] = {\n supported: supported,\n byFallback: byFallback,\n unsupported: unsupported\n };\n\n return localeSupportInfo[constructorName];\n}\n\n\n\/**\n * @description Tests whether locale is a String value representing a\n * structurally valid and canonicalized BCP 47 language tag, as defined in\n * sections 6.2.2 and 6.2.3 of the ECMAScript Internationalization API\n * Specification.\n * @param {String} locale the string to be tested.\n * @result {Boolean} whether the test succeeded.\n *\/\nfunction isCanonicalizedStructurallyValidLanguageTag(locale) {\n\n \/**\n * Regular expression defining BCP 47 language tags.\n *\n * Spec: RFC 5646 section 2.1.\n *\/\n var alpha = \"[a-zA-Z]\",\n digit = \"[0-9]\",\n alphanum = \"(\" + alpha + \"|\" + digit + \")\",\n regular = \"(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)\",\n 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)\",\n grandfathered = \"(\" + irregular + \"|\" + regular + \")\",\n privateuse = \"(x(-[a-z0-9]{1,8})+)\",\n singleton = \"(\" + digit + \"|[A-WY-Za-wy-z])\",\n extension = \"(\" + singleton + \"(-\" + alphanum + \"{2,8})+)\",\n variant = \"(\" + alphanum + \"{5,8}|(\" + digit + alphanum + \"{3}))\",\n region = \"(\" + alpha + \"{2}|\" + digit + \"{3})\",\n script = \"(\" + alpha + \"{4})\",\n extlang = \"(\" + alpha + \"{3}(-\" + alpha + \"{3}){0,2})\",\n language = \"(\" + alpha + \"{2,3}(-\" + extlang + \")?|\" + alpha + \"{4}|\" + alpha + \"{5,8})\",\n langtag = language + \"(-\" + script + \")?(-\" + region + \")?(-\" + variant + \")*(-\" + extension + \")*(-\" + privateuse + \")?\",\n languageTag = \"^(\" + langtag + \"|\" + privateuse + \"|\" + grandfathered + \")$\",\n languageTagRE = new RegExp(languageTag, \"i\");\n var duplicateSingleton = \"-\" + singleton + \"-(.*-)?\\\\1(?!\" + alphanum + \")\",\n duplicateSingletonRE = new RegExp(duplicateSingleton, \"i\"),\n duplicateVariant = \"(\" + alphanum + \"{2,8}-)+\" + variant + \"-(\" + alphanum + \"{2,8}-)*\\\\3(?!\" + alphanum + \")\",\n duplicateVariantRE = new RegExp(duplicateVariant, \"i\");\n\n\n \/**\n * Verifies that the given string is a well-formed BCP 47 language tag\n * with no duplicate variant or singleton subtags.\n *\n * Spec: ECMAScript Internationalization API Specification, draft, 6.2.2.\n *\/\n function isStructurallyValidLanguageTag(locale) {\n if (!languageTagRE.test(locale)) {\n return false;\n }\n locale = locale.split(\/-x-\/)[0];\n return !duplicateSingletonRE.test(locale) && !duplicateVariantRE.test(locale);\n }\n\n\n \/**\n * Mappings from complete tags to preferred values.\n *\n * Spec: IANA Language Subtag Registry.\n *\/\n var __tagMappings = {\n \/\/ property names must be in lower case; values in canonical form\n\n \/\/ grandfathered tags from IANA language subtag registry, file date 2011-08-25\n \"art-lojban\": \"jbo\",\n \"cel-gaulish\": \"cel-gaulish\",\n \"en-gb-oed\": \"en-GB-oed\",\n \"i-ami\": \"ami\",\n \"i-bnn\": \"bnn\",\n \"i-default\": \"i-default\",\n \"i-enochian\": \"i-enochian\",\n \"i-hak\": \"hak\",\n \"i-klingon\": \"tlh\",\n \"i-lux\": \"lb\",\n \"i-mingo\": \"i-mingo\",\n \"i-navajo\": \"nv\",\n \"i-pwn\": \"pwn\",\n \"i-tao\": \"tao\",\n \"i-tay\": \"tay\",\n \"i-tsu\": \"tsu\",\n \"no-bok\": \"nb\",\n \"no-nyn\": \"nn\",\n \"sgn-be-fr\": \"sfb\",\n \"sgn-be-nl\": \"vgt\",\n \"sgn-ch-de\": \"sgg\",\n \"zh-guoyu\": \"cmn\",\n \"zh-hakka\": \"hak\",\n \"zh-min\": \"zh-min\",\n \"zh-min-nan\": \"nan\",\n \"zh-xiang\": \"hsn\",\n \/\/ deprecated redundant tags from IANA language subtag registry, file date 2011-08-25\n \"sgn-br\": \"bzs\",\n \"sgn-co\": \"csn\",\n \"sgn-de\": \"gsg\",\n \"sgn-dk\": \"dsl\",\n \"sgn-es\": \"ssp\",\n \"sgn-fr\": \"fsl\",\n \"sgn-gb\": \"bfi\",\n \"sgn-gr\": \"gss\",\n \"sgn-ie\": \"isg\",\n \"sgn-it\": \"ise\",\n \"sgn-jp\": \"jsl\",\n \"sgn-mx\": \"mfs\",\n \"sgn-ni\": \"ncs\",\n \"sgn-nl\": \"dse\",\n \"sgn-no\": \"nsl\",\n \"sgn-pt\": \"psr\",\n \"sgn-se\": \"swl\",\n \"sgn-us\": \"ase\",\n \"sgn-za\": \"sfs\",\n \"zh-cmn\": \"cmn\",\n \"zh-cmn-hans\": \"cmn-Hans\",\n \"zh-cmn-hant\": \"cmn-Hant\",\n \"zh-gan\": \"gan\",\n \"zh-wuu\": \"wuu\",\n \"zh-yue\": \"yue\",\n \/\/ deprecated variant with prefix from IANA language subtag registry, file date 2011-08-25\n \"ja-latn-hepburn-heploc\": \"ja-Latn-alalc97\"\n };\n\n\n \/**\n * Mappings from non-extlang subtags to preferred values.\n *\n * Spec: IANA Language Subtag Registry.\n *\/\n var __subtagMappings = {\n \/\/ property names and values must be in canonical case\n \/\/ language subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25\n \"in\": \"id\",\n \"iw\": \"he\",\n \"ji\": \"yi\",\n \"jw\": \"jv\",\n \"mo\": \"ro\",\n \"ayx\": \"nun\",\n \"cjr\": \"mom\",\n \"cmk\": \"xch\",\n \"drh\": \"khk\",\n \"drw\": \"prs\",\n \"gav\": \"dev\",\n \"mst\": \"mry\",\n \"myt\": \"mry\",\n \"tie\": \"ras\",\n \"tkk\": \"twm\",\n \"tnf\": \"prs\",\n \/\/ region subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25\n \"BU\": \"MM\",\n \"DD\": \"DE\",\n \"FX\": \"FR\",\n \"TP\": \"TL\",\n \"YD\": \"YE\",\n \"ZR\": \"CD\"\n };\n\n\n \/**\n * Mappings from extlang subtags to preferred values.\n *\n * Spec: IANA Language Subtag Registry.\n *\/\n var __extlangMappings = {\n \/\/ extlang subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25\n \/\/ values are arrays with [0] the replacement value, [1] (if present) the prefix to be removed\n \"aao\": [\"aao\", \"ar\"],\n \"abh\": [\"abh\", \"ar\"],\n \"abv\": [\"abv\", \"ar\"],\n \"acm\": [\"acm\", \"ar\"],\n \"acq\": [\"acq\", \"ar\"],\n \"acw\": [\"acw\", \"ar\"],\n \"acx\": [\"acx\", \"ar\"],\n \"acy\": [\"acy\", \"ar\"],\n \"adf\": [\"adf\", \"ar\"],\n \"ads\": [\"ads\", \"sgn\"],\n \"aeb\": [\"aeb\", \"ar\"],\n \"aec\": [\"aec\", \"ar\"],\n \"aed\": [\"aed\", \"sgn\"],\n \"aen\": [\"aen\", \"sgn\"],\n \"afb\": [\"afb\", \"ar\"],\n \"afg\": [\"afg\", \"sgn\"],\n \"ajp\": [\"ajp\", \"ar\"],\n \"apc\": [\"apc\", \"ar\"],\n \"apd\": [\"apd\", \"ar\"],\n \"arb\": [\"arb\", \"ar\"],\n \"arq\": [\"arq\", \"ar\"],\n \"ars\": [\"ars\", \"ar\"],\n \"ary\": [\"ary\", \"ar\"],\n \"arz\": [\"arz\", \"ar\"],\n \"ase\": [\"ase\", \"sgn\"],\n \"asf\": [\"asf\", \"sgn\"],\n \"asp\": [\"asp\", \"sgn\"],\n \"asq\": [\"asq\", \"sgn\"],\n \"asw\": [\"asw\", \"sgn\"],\n \"auz\": [\"auz\", \"ar\"],\n \"avl\": [\"avl\", \"ar\"],\n \"ayh\": [\"ayh\", \"ar\"],\n \"ayl\": [\"ayl\", \"ar\"],\n \"ayn\": [\"ayn\", \"ar\"],\n \"ayp\": [\"ayp\", \"ar\"],\n \"bbz\": [\"bbz\", \"ar\"],\n \"bfi\": [\"bfi\", \"sgn\"],\n \"bfk\": [\"bfk\", \"sgn\"],\n \"bjn\": [\"bjn\", \"ms\"],\n \"bog\": [\"bog\", \"sgn\"],\n \"bqn\": [\"bqn\", \"sgn\"],\n \"bqy\": [\"bqy\", \"sgn\"],\n \"btj\": [\"btj\", \"ms\"],\n \"bve\": [\"bve\", \"ms\"],\n \"bvl\": [\"bvl\", \"sgn\"],\n \"bvu\": [\"bvu\", \"ms\"],\n \"bzs\": [\"bzs\", \"sgn\"],\n \"cdo\": [\"cdo\", \"zh\"],\n \"cds\": [\"cds\", \"sgn\"],\n \"cjy\": [\"cjy\", \"zh\"],\n \"cmn\": [\"cmn\", \"zh\"],\n \"coa\": [\"coa\", \"ms\"],\n \"cpx\": [\"cpx\", \"zh\"],\n \"csc\": [\"csc\", \"sgn\"],\n \"csd\": [\"csd\", \"sgn\"],\n \"cse\": [\"cse\", \"sgn\"],\n \"csf\": [\"csf\", \"sgn\"],\n \"csg\": [\"csg\", \"sgn\"],\n \"csl\": [\"csl\", \"sgn\"],\n \"csn\": [\"csn\", \"sgn\"],\n \"csq\": [\"csq\", \"sgn\"],\n \"csr\": [\"csr\", \"sgn\"],\n \"czh\": [\"czh\", \"zh\"],\n \"czo\": [\"czo\", \"zh\"],\n \"doq\": [\"doq\", \"sgn\"],\n \"dse\": [\"dse\", \"sgn\"],\n \"dsl\": [\"dsl\", \"sgn\"],\n \"dup\": [\"dup\", \"ms\"],\n \"ecs\": [\"ecs\", \"sgn\"],\n \"esl\": [\"esl\", \"sgn\"],\n \"esn\": [\"esn\", \"sgn\"],\n \"eso\": [\"eso\", \"sgn\"],\n \"eth\": [\"eth\", \"sgn\"],\n \"fcs\": [\"fcs\", \"sgn\"],\n \"fse\": [\"fse\", \"sgn\"],\n \"fsl\": [\"fsl\", \"sgn\"],\n \"fss\": [\"fss\", \"sgn\"],\n \"gan\": [\"gan\", \"zh\"],\n \"gom\": [\"gom\", \"kok\"],\n \"gse\": [\"gse\", \"sgn\"],\n \"gsg\": [\"gsg\", \"sgn\"],\n \"gsm\": [\"gsm\", \"sgn\"],\n \"gss\": [\"gss\", \"sgn\"],\n \"gus\": [\"gus\", \"sgn\"],\n \"hab\": [\"hab\", \"sgn\"],\n \"haf\": [\"haf\", \"sgn\"],\n \"hak\": [\"hak\", \"zh\"],\n \"hds\": [\"hds\", \"sgn\"],\n \"hji\": [\"hji\", \"ms\"],\n \"hks\": [\"hks\", \"sgn\"],\n \"hos\": [\"hos\", \"sgn\"],\n \"hps\": [\"hps\", \"sgn\"],\n \"hsh\": [\"hsh\", \"sgn\"],\n \"hsl\": [\"hsl\", \"sgn\"],\n \"hsn\": [\"hsn\", \"zh\"],\n \"icl\": [\"icl\", \"sgn\"],\n \"ils\": [\"ils\", \"sgn\"],\n \"inl\": [\"inl\", \"sgn\"],\n \"ins\": [\"ins\", \"sgn\"],\n \"ise\": [\"ise\", \"sgn\"],\n \"isg\": [\"isg\", \"sgn\"],\n \"isr\": [\"isr\", \"sgn\"],\n \"jak\": [\"jak\", \"ms\"],\n \"jax\": [\"jax\", \"ms\"],\n \"jcs\": [\"jcs\", \"sgn\"],\n \"jhs\": [\"jhs\", \"sgn\"],\n \"jls\": [\"jls\", \"sgn\"],\n \"jos\": [\"jos\", \"sgn\"],\n \"jsl\": [\"jsl\", \"sgn\"],\n \"jus\": [\"jus\", \"sgn\"],\n \"kgi\": [\"kgi\", \"sgn\"],\n \"knn\": [\"knn\", \"kok\"],\n \"kvb\": [\"kvb\", \"ms\"],\n \"kvk\": [\"kvk\", \"sgn\"],\n \"kvr\": [\"kvr\", \"ms\"],\n \"kxd\": [\"kxd\", \"ms\"],\n \"lbs\": [\"lbs\", \"sgn\"],\n \"lce\": [\"lce\", \"ms\"],\n \"lcf\": [\"lcf\", \"ms\"],\n \"liw\": [\"liw\", \"ms\"],\n \"lls\": [\"lls\", \"sgn\"],\n \"lsg\": [\"lsg\", \"sgn\"],\n \"lsl\": [\"lsl\", \"sgn\"],\n \"lso\": [\"lso\", \"sgn\"],\n \"lsp\": [\"lsp\", \"sgn\"],\n \"lst\": [\"lst\", \"sgn\"],\n \"lsy\": [\"lsy\", \"sgn\"],\n \"ltg\": [\"ltg\", \"lv\"],\n \"lvs\": [\"lvs\", \"lv\"],\n \"lzh\": [\"lzh\", \"zh\"],\n \"max\": [\"max\", \"ms\"],\n \"mdl\": [\"mdl\", \"sgn\"],\n \"meo\": [\"meo\", \"ms\"],\n \"mfa\": [\"mfa\", \"ms\"],\n \"mfb\": [\"mfb\", \"ms\"],\n \"mfs\": [\"mfs\", \"sgn\"],\n \"min\": [\"min\", \"ms\"],\n \"mnp\": [\"mnp\", \"zh\"],\n \"mqg\": [\"mqg\", \"ms\"],\n \"mre\": [\"mre\", \"sgn\"],\n \"msd\": [\"msd\", \"sgn\"],\n \"msi\": [\"msi\", \"ms\"],\n \"msr\": [\"msr\", \"sgn\"],\n \"mui\": [\"mui\", \"ms\"],\n \"mzc\": [\"mzc\", \"sgn\"],\n \"mzg\": [\"mzg\", \"sgn\"],\n \"mzy\": [\"mzy\", \"sgn\"],\n \"nan\": [\"nan\", \"zh\"],\n \"nbs\": [\"nbs\", \"sgn\"],\n \"ncs\": [\"ncs\", \"sgn\"],\n \"nsi\": [\"nsi\", \"sgn\"],\n \"nsl\": [\"nsl\", \"sgn\"],\n \"nsp\": [\"nsp\", \"sgn\"],\n \"nsr\": [\"nsr\", \"sgn\"],\n \"nzs\": [\"nzs\", \"sgn\"],\n \"okl\": [\"okl\", \"sgn\"],\n \"orn\": [\"orn\", \"ms\"],\n \"ors\": [\"ors\", \"ms\"],\n \"pel\": [\"pel\", \"ms\"],\n \"pga\": [\"pga\", \"ar\"],\n \"pks\": [\"pks\", \"sgn\"],\n \"prl\": [\"prl\", \"sgn\"],\n \"prz\": [\"prz\", \"sgn\"],\n \"psc\": [\"psc\", \"sgn\"],\n \"psd\": [\"psd\", \"sgn\"],\n \"pse\": [\"pse\", \"ms\"],\n \"psg\": [\"psg\", \"sgn\"],\n \"psl\": [\"psl\", \"sgn\"],\n \"pso\": [\"pso\", \"sgn\"],\n \"psp\": [\"psp\", \"sgn\"],\n \"psr\": [\"psr\", \"sgn\"],\n \"pys\": [\"pys\", \"sgn\"],\n \"rms\": [\"rms\", \"sgn\"],\n \"rsi\": [\"rsi\", \"sgn\"],\n \"rsl\": [\"rsl\", \"sgn\"],\n \"sdl\": [\"sdl\", \"sgn\"],\n \"sfb\": [\"sfb\", \"sgn\"],\n \"sfs\": [\"sfs\", \"sgn\"],\n \"sgg\": [\"sgg\", \"sgn\"],\n \"sgx\": [\"sgx\", \"sgn\"],\n \"shu\": [\"shu\", \"ar\"],\n \"slf\": [\"slf\", \"sgn\"],\n \"sls\": [\"sls\", \"sgn\"],\n \"sqs\": [\"sqs\", \"sgn\"],\n \"ssh\": [\"ssh\", \"ar\"],\n \"ssp\": [\"ssp\", \"sgn\"],\n \"ssr\": [\"ssr\", \"sgn\"],\n \"svk\": [\"svk\", \"sgn\"],\n \"swc\": [\"swc\", \"sw\"],\n \"swh\": [\"swh\", \"sw\"],\n \"swl\": [\"swl\", \"sgn\"],\n \"syy\": [\"syy\", \"sgn\"],\n \"tmw\": [\"tmw\", \"ms\"],\n \"tse\": [\"tse\", \"sgn\"],\n \"tsm\": [\"tsm\", \"sgn\"],\n \"tsq\": [\"tsq\", \"sgn\"],\n \"tss\": [\"tss\", \"sgn\"],\n \"tsy\": [\"tsy\", \"sgn\"],\n \"tza\": [\"tza\", \"sgn\"],\n \"ugn\": [\"ugn\", \"sgn\"],\n \"ugy\": [\"ugy\", \"sgn\"],\n \"ukl\": [\"ukl\", \"sgn\"],\n \"uks\": [\"uks\", \"sgn\"],\n \"urk\": [\"urk\", \"ms\"],\n \"uzn\": [\"uzn\", \"uz\"],\n \"uzs\": [\"uzs\", \"uz\"],\n \"vgt\": [\"vgt\", \"sgn\"],\n \"vkk\": [\"vkk\", \"ms\"],\n \"vkt\": [\"vkt\", \"ms\"],\n \"vsi\": [\"vsi\", \"sgn\"],\n \"vsl\": [\"vsl\", \"sgn\"],\n \"vsv\": [\"vsv\", \"sgn\"],\n \"wuu\": [\"wuu\", \"zh\"],\n \"xki\": [\"xki\", \"sgn\"],\n \"xml\": [\"xml\", \"sgn\"],\n \"xmm\": [\"xmm\", \"ms\"],\n \"xms\": [\"xms\", \"sgn\"],\n \"yds\": [\"yds\", \"sgn\"],\n \"ysl\": [\"ysl\", \"sgn\"],\n \"yue\": [\"yue\", \"zh\"],\n \"zib\": [\"zib\", \"sgn\"],\n \"zlm\": [\"zlm\", \"ms\"],\n \"zmi\": [\"zmi\", \"ms\"],\n \"zsl\": [\"zsl\", \"sgn\"],\n \"zsm\": [\"zsm\", \"ms\"]\n };\n\n\n \/**\n * Canonicalizes the given well-formed BCP 47 language tag, including regularized case of subtags.\n *\n * Spec: ECMAScript Internationalization API Specification, draft, 6.2.3.\n * Spec: RFC 5646, section 4.5.\n *\/\n function canonicalizeLanguageTag(locale) {\n\n \/\/ start with lower case for easier processing, and because most subtags will need to be lower case anyway\n locale = locale.toLowerCase();\n\n \/\/ handle mappings for complete tags\n if (__tagMappings.hasOwnProperty(locale)) {\n return __tagMappings[locale];\n }\n\n var subtags = locale.split(\"-\");\n var i = 0;\n\n \/\/ handle standard part: all subtags before first singleton or \"x\"\n while (i < subtags.length) {\n var subtag = subtags[i];\n if (subtag.length === 1 && (i > 0 || subtag === \"x\")) {\n break;\n } else if (i !== 0 && subtag.length === 2) {\n subtag = subtag.toUpperCase();\n } else if (subtag.length === 4) {\n subtag = subtag[0].toUpperCase() + subtag.substring(1).toLowerCase();\n }\n if (__subtagMappings.hasOwnProperty(subtag)) {\n subtag = __subtagMappings[subtag];\n } else if (__extlangMappings.hasOwnProperty(subtag)) {\n subtag = __extlangMappings[subtag][0];\n if (i === 1 && __extlangMappings[subtag][1] === subtags[0]) {\n subtags.shift();\n i--;\n }\n }\n subtags[i] = subtag;\n i++;\n }\n var normal = subtags.slice(0, i).join(\"-\");\n\n \/\/ handle extensions\n var extensions = [];\n while (i < subtags.length && subtags[i] !== \"x\") {\n var extensionStart = i;\n i++;\n while (i < subtags.length && subtags[i].length > 1) {\n i++;\n }\n var extension = subtags.slice(extensionStart, i).join(\"-\");\n extensions.push(extension);\n }\n extensions.sort();\n\n \/\/ handle private use\n var privateUse;\n if (i < subtags.length) {\n privateUse = subtags.slice(i).join(\"-\");\n }\n\n \/\/ put everything back together\n var canonical = normal;\n if (extensions.length > 0) {\n canonical += \"-\" + extensions.join(\"-\");\n }\n if (privateUse !== undefined) {\n if (canonical.length > 0) {\n canonical += \"-\" + privateUse;\n } else {\n canonical = privateUse;\n }\n }\n\n return canonical;\n }\n\n return typeof locale === \"string\" && isStructurallyValidLanguageTag(locale) &&\n canonicalizeLanguageTag(locale) === locale;\n}\n\n\n\/**\n * Tests whether the named options property is correctly handled by the given constructor.\n * @param {object} Constructor the constructor to test.\n * @param {string} property the name of the options property to test.\n * @param {string} type the type that values of the property are expected to have\n * @param {Array} [values] an array of allowed values for the property. Not needed for boolean.\n * @param {any} fallback the fallback value that the property assumes if not provided.\n * @param {object} testOptions additional options:\n * @param {boolean} isOptional whether support for this property is optional for implementations.\n * @param {boolean} noReturn whether the resulting value of the property is not returned.\n * @param {boolean} isILD whether the resulting value of the property is implementation and locale dependent.\n * @param {object} extra additional option to pass along, properties are value -> {option: value}.\n * @return {boolean} whether the test succeeded.\n *\/\nfunction testOption(Constructor, property, type, values, fallback, testOptions) {\n var isOptional = testOptions !== undefined && testOptions.isOptional === true;\n var noReturn = testOptions !== undefined && testOptions.noReturn === true;\n var isILD = testOptions !== undefined && testOptions.isILD === true;\n\n function addExtraOptions(options, value, testOptions) {\n if (testOptions !== undefined && testOptions.extra !== undefined) {\n var extra;\n if (value !== undefined && testOptions.extra[value] !== undefined) {\n extra = testOptions.extra[value];\n } else if (testOptions.extra.any !== undefined) {\n extra = testOptions.extra.any;\n }\n if (extra !== undefined) {\n Object.getOwnPropertyNames(extra).forEach(function (prop) {\n options[prop] = extra[prop];\n });\n }\n }\n }\n\n var testValues, options, obj, expected, actual, error;\n\n \/\/ test that the specified values are accepted. Also add values that convert to specified values.\n if (type === \"boolean\") {\n if (values === undefined) {\n values = [true, false];\n }\n testValues = values.slice(0);\n testValues.push(888);\n testValues.push(0);\n } else if (type === \"string\") {\n testValues = values.slice(0);\n testValues.push({toString: function () { return values[0]; }});\n }\n testValues.forEach(function (value) {\n options = {};\n options[property] = value;\n addExtraOptions(options, value, testOptions);\n obj = new Constructor(undefined, options);\n if (noReturn) {\n if (obj.resolvedOptions().hasOwnProperty(property)) {\n $ERROR(\"Option property \" + property + \" is returned, but shouldn\'t be.\");\n }\n } else {\n actual = obj.resolvedOptions()[property];\n if (isILD) {\n if (actual !== undefined && values.indexOf(actual) === -1) {\n $ERROR(\"Invalid value \" + actual + \" returned for property \" + property + \".\");\n }\n } else {\n if (type === \"boolean\") {\n expected = Boolean(value);\n } else if (type === \"string\") {\n expected = String(value);\n }\n if (actual !== expected && !(isOptional && actual === undefined)) {\n $ERROR(\"Option value \" + value + \" for property \" + property +\n \" was not accepted; got \" + actual + \" instead.\");\n }\n }\n }\n });\n\n \/\/ test that invalid values are rejected\n if (type === \"string\") {\n var invalidValues = [\"invalidValue\", -1, null];\n \/\/ assume that we won\'t have values in caseless scripts\n if (values[0].toUpperCase() !== values[0]) {\n invalidValues.push(values[0].toUpperCase());\n } else {\n invalidValues.push(values[0].toLowerCase());\n }\n invalidValues.forEach(function (value) {\n options = {};\n options[property] = value;\n addExtraOptions(options, value, testOptions);\n error = undefined;\n try {\n obj = new Constructor(undefined, options);\n } catch (e) {\n error = e;\n }\n if (error === undefined) {\n $ERROR(\"Invalid option value \" + value + \" for property \" + property + \" was not rejected.\");\n } else if (error.name !== \"RangeError\") {\n $ERROR(\"Invalid option value \" + value + \" for property \" + property + \" was rejected with wrong error \" + error.name + \".\");\n }\n });\n }\n\n \/\/ test that fallback value or another valid value is used if no options value is provided\n if (!noReturn) {\n options = {};\n addExtraOptions(options, undefined, testOptions);\n obj = new Constructor(undefined, options);\n actual = obj.resolvedOptions()[property];\n if (!(isOptional && actual === undefined)) {\n if (fallback !== undefined) {\n if (actual !== fallback) {\n $ERROR(\"Option fallback value \" + fallback + \" for property \" + property +\n \" was not used; got \" + actual + \" instead.\");\n }\n } else {\n if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) {\n $ERROR(\"Invalid value \" + actual + \" returned for property \" + property + \".\");\n }\n }\n }\n }\n\n return true;\n}\n\n\n\/**\n * Tests whether the named property of the given object has a valid value\n * and the default attributes of the properties of an object literal.\n * @param {Object} obj the object to be tested.\n * @param {string} property the name of the property\n * @param {Function|Array} valid either a function that tests value for validity and returns a boolean,\n * an array of valid values.\n * @exception if the property has an invalid value.\n *\/\nfunction testProperty(obj, property, valid) {\n var desc = Object.getOwnPropertyDescriptor(obj, property);\n if (!desc.writable) {\n $ERROR(\"Property \" + property + \" must be writable.\");\n }\n if (!desc.enumerable) {\n $ERROR(\"Property \" + property + \" must be enumerable.\");\n }\n if (!desc.configurable) {\n $ERROR(\"Property \" + property + \" must be configurable.\");\n }\n var value = desc.value;\n var isValid = (typeof valid === \"function\") ? valid(value) : (valid.indexOf(value) !== -1);\n if (!isValid) {\n $ERROR(\"Property value \" + value + \" is not allowed for property \" + property + \".\");\n }\n}\n\n\n\/**\n * Tests whether the named property of the given object, if present at all, has a valid value\n * and the default attributes of the properties of an object literal.\n * @param {Object} obj the object to be tested.\n * @param {string} property the name of the property\n * @param {Function|Array} valid either a function that tests value for validity and returns a boolean,\n * an array of valid values.\n * @exception if the property is present and has an invalid value.\n *\/\nfunction mayHaveProperty(obj, property, valid) {\n if (obj.hasOwnProperty(property)) {\n testProperty(obj, property, valid);\n }\n}\n\n\n\/**\n * Tests whether the given object has the named property with a valid value\n * and the default attributes of the properties of an object literal.\n * @param {Object} obj the object to be tested.\n * @param {string} property the name of the property\n * @param {Function|Array} valid either a function that tests value for validity and returns a boolean,\n * an array of valid values.\n * @exception if the property is missing or has an invalid value.\n *\/\nfunction mustHaveProperty(obj, property, valid) {\n if (!obj.hasOwnProperty(property)) {\n $ERROR(\"Object is missing property \" + property + \".\");\n }\n testProperty(obj, property, valid);\n}\n\n\n\/**\n * Tests whether the given object does not have the named property.\n * @param {Object} obj the object to be tested.\n * @param {string} property the name of the property\n * @exception if the property is present.\n *\/\nfunction mustNotHaveProperty(obj, property) {\n if (obj.hasOwnProperty(property)) {\n $ERROR(\"Object has property it mustn\'t have: \" + property + \".\");\n }\n}\n\n\n\/**\n * Properties of the RegExp constructor that may be affected by use of regular\n * expressions, and the default values of these properties. Properties are from\n * https:\/\/developer.mozilla.org\/en-US\/docs\/JavaScript\/Reference\/Deprecated_and_obsolete_features#RegExp_Properties\n *\/\nvar regExpProperties = [\"$1\", \"$2\", \"$3\", \"$4\", \"$5\", \"$6\", \"$7\", \"$8\", \"$9\",\n \"$_\", \"$*\", \"$&\", \"$+\", \"$`\", \"$\'\",\n \"input\", \"lastMatch\", \"lastParen\", \"leftContext\", \"rightContext\"\n];\n\nvar regExpPropertiesDefaultValues = (function () {\n var values = Object.create(null);\n regExpProperties.forEach(function (property) {\n values[property] = RegExp[property];\n });\n return values;\n}());\n\n\n\/**\n * Tests that executing the provided function (which may use regular expressions\n * in its implementation) does not create or modify unwanted properties on the\n * RegExp constructor.\n *\/\nfunction testForUnwantedRegExpChanges(testFunc) {\n regExpProperties.forEach(function (property) {\n RegExp[property] = regExpPropertiesDefaultValues[property];\n });\n testFunc();\n regExpProperties.forEach(function (property) {\n if (RegExp[property] !== regExpPropertiesDefaultValues[property]) {\n $ERROR(\"RegExp has unexpected property \" + property + \" with value \" +\n RegExp[property] + \".\");\n }\n });\n}\n\n\n\/**\n * Tests whether name is a valid BCP 47 numbering system name\n * and not excluded from use in the ECMAScript Internationalization API.\n * @param {string} name the name to be tested.\n * @return {boolean} whether name is a valid BCP 47 numbering system name and\n * allowed for use in the ECMAScript Internationalization API.\n *\/\n\nfunction isValidNumberingSystem(name) {\n\n \/\/ source: CLDR file common\/bcp47\/number.xml; version CLDR 21.\n var numberingSystems = [\n \"arab\",\n \"arabext\",\n \"armn\",\n \"armnlow\",\n \"bali\",\n \"beng\",\n \"brah\",\n \"cakm\",\n \"cham\",\n \"deva\",\n \"ethi\",\n \"finance\",\n \"fullwide\",\n \"geor\",\n \"grek\",\n \"greklow\",\n \"gujr\",\n \"guru\",\n \"hanidec\",\n \"hans\",\n \"hansfin\",\n \"hant\",\n \"hantfin\",\n \"hebr\",\n \"java\",\n \"jpan\",\n \"jpanfin\",\n \"kali\",\n \"khmr\",\n \"knda\",\n \"osma\",\n \"lana\",\n \"lanatham\",\n \"laoo\",\n \"latn\",\n \"lepc\",\n \"limb\",\n \"mlym\",\n \"mong\",\n \"mtei\",\n \"mymr\",\n \"mymrshan\",\n \"native\",\n \"nkoo\",\n \"olck\",\n \"orya\",\n \"roman\",\n \"romanlow\",\n \"saur\",\n \"shrd\",\n \"sora\",\n \"sund\",\n \"talu\",\n \"takr\",\n \"taml\",\n \"tamldec\",\n \"telu\",\n \"thai\",\n \"tibt\",\n \"traditio\",\n \"vaii\"\n ];\n\n var excluded = [\n \"finance\",\n \"native\",\n \"traditio\"\n ];\n\n\n return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1;\n}\n\n\n\/**\n * Provides the digits of numbering systems with simple digit mappings,\n * as specified in 11.3.2.\n *\/\n\nvar numberingSystemDigits = {\n arab: \"┘á┘í┘ó┘ú┘ñ┘Ñ┘ª┘º┘¿┘®\",\n arabext: \"█░█▒█▓█│█┤█Á█Â█À█©█╣\",\n beng: \"ÓºªÓººÓº¿Óº®Óº¬Óº½Óº¼Óº¡Óº«Óº»\",\n deva: \"ÓѪÓѺÓÑ¿ÓÑ®ÓѬÓѽÓѼÓÑ¡ÓÑ«ÓÑ»\",\n fullwide: \"´╝É´╝æ´╝Æ´╝ô´╝ö´╝ò´╝û´╝ù´╝ÿ´╝Ö\",\n gujr: \"Ó½ªÓ½ºÓ½¿Ó½®Ó½¬Ó½½Ó½¼Ó½¡Ó½«Ó½»\",\n guru: \"Ó®ªÓ®ºÓ®¿Ó®®Ó®¬Ó®½Ó®¼Ó®¡Ó®«Ó®»\",\n hanidec: \"ÒÇçõ©Çõ║îõ©ëÕøøõ║öÕà¡õ©âÕà½õ╣Ø\",\n khmr: \"߃á߃í߃ó߃ú߃ñ߃Ñ߃ªßƒºßƒ¿ßƒ®\",\n knda: \"Ó│ªÓ│ºÓ│¿Ó│®Ó│¬Ó│½Ó│¼Ó│¡Ó│«Ó│»\",\n laoo: \"Ó╗ÉÓ╗æÓ╗ÆÓ╗ôÓ╗öÓ╗òÓ╗ûÓ╗ùÓ╗ÿÓ╗Ö\",\n latn: \"0123456789\",\n mlym: \"ÓÁªÓÁºÓÁ¿ÓÁ®ÓÁ¬ÓÁ½ÓÁ¼ÓÁ¡ÓÁ«ÓÁ»\",\n mong: \"ßáÉßáæßáÆßáôßáößáòßáûßáùßáÿßáÖ\",\n mymr: \"ßüÇßüüßüéßüâßüäßüàßüåßüçßüêßüë\",\n orya: \"Ó¡ªÓ¡ºÓ¡¿Ó¡®Ó¡¬Ó¡½Ó¡¼Ó¡¡Ó¡«Ó¡»\",\n tamldec: \"Ó»ªÓ»ºÓ»¿Ó»®Ó»¬Ó»½Ó»¼Ó»¡Ó»«Ó»»\",\n telu: \"Ó▒ªÓ▒ºÓ▒¿Ó▒®Ó▒¬Ó▒½Ó▒¼Ó▒¡Ó▒«Ó▒»\",\n thai: \"Ó╣ÉÓ╣æÓ╣ÆÓ╣ôÓ╣öÓ╣òÓ╣ûÓ╣ùÓ╣ÿÓ╣Ö\",\n tibt: \"Ó╝áÓ╝íÓ╝óÓ╝úÓ╝ñÓ╝ÑÓ╝ªÓ╝ºÓ╝¿Ó╝®\"\n};\n\n\n\/**\n * Tests that number formatting is handled correctly. The function checks that the\n * digit sequences in formatted output are as specified, converted to the\n * selected numbering system, and embedded in consistent localized patterns.\n * @param {Array} locales the locales to be tested.\n * @param {Array} numberingSystems the numbering systems to be tested.\n * @param {Object} options the options to pass to Intl.NumberFormat. Options\n * must include {useGrouping: false}, and must cause 1.1 to be formatted\n * pre- and post-decimal digits.\n * @param {Object} testData maps input data (in ES5 9.3.1 format) to expected output strings\n * in unlocalized format with Western digits.\n *\/\n\nfunction testNumberFormat(locales, numberingSystems, options, testData) {\n locales.forEach(function (locale) {\n numberingSystems.forEach(function (numbering) {\n var digits = numberingSystemDigits[numbering];\n var format = new Intl.NumberFormat([locale + \"-u-nu-\" + numbering], options);\n\n function getPatternParts(positive) {\n var n = positive ? 1.1 : -1.1;\n var formatted = format.format(n);\n var oneoneRE = \"([^\" + digits + \"]*)[\" + digits + \"]+([^\" + digits + \"]+)[\" + digits + \"]+([^\" + digits + \"]*)\";\n var match = formatted.match(new RegExp(oneoneRE));\n if (match === null) {\n $ERROR(\"Unexpected formatted \" + n + \" for \" +\n format.resolvedOptions().locale + \" and options \" +\n JSON.stringify(options) + \": \" + formatted);\n }\n return match;\n }\n\n function toNumbering(raw) {\n return raw.replace(\/[0-9]\/g, function (digit) {\n return digits[digit.charCodeAt(0) - \"0\".charCodeAt(0)];\n });\n }\n\n function buildExpected(raw, patternParts) {\n var period = raw.indexOf(\".\");\n if (period === -1) {\n return patternParts[1] + toNumbering(raw) + patternParts[3];\n } else {\n return patternParts[1] +\n toNumbering(raw.substring(0, period)) +\n patternParts[2] +\n toNumbering(raw.substring(period + 1)) +\n patternParts[3];\n }\n }\n\n if (format.resolvedOptions().numberingSystem === numbering) {\n \/\/ figure out prefixes, infixes, suffixes for positive and negative values\n var posPatternParts = getPatternParts(true);\n var negPatternParts = getPatternParts(false);\n\n Object.getOwnPropertyNames(testData).forEach(function (input) {\n var rawExpected = testData[input];\n var patternParts;\n if (rawExpected[0] === \"-\") {\n patternParts = negPatternParts;\n rawExpected = rawExpected.substring(1);\n } else {\n patternParts = posPatternParts;\n }\n var expected = buildExpected(rawExpected, patternParts);\n var actual = format.format(input);\n if (actual !== expected) {\n $ERROR(\"Formatted value for \" + input + \", \" +\n format.resolvedOptions().locale + \" and options \" +\n JSON.stringify(options) + \" is \" + actual + \"; expected \" + expected + \".\");\n }\n });\n }\n });\n });\n}\n\n\n\/**\n * Return the components of date-time formats.\n * @return {Array} an array with all date-time components.\n *\/\n\nfunction getDateTimeComponents() {\n return [\"weekday\", \"era\", \"year\", \"month\", \"day\", \"hour\", \"minute\", \"second\", \"timeZoneName\"];\n}\n\n\n\/**\n * Return the valid values for the given date-time component, as specified\n * by the table in section 12.1.1.\n * @param {string} component a date-time component.\n * @return {Array} an array with the valid values for the component.\n *\/\n\nfunction getDateTimeComponentValues(component) {\n\n var components = {\n weekday: [\"narrow\", \"short\", \"long\"],\n era: [\"narrow\", \"short\", \"long\"],\n year: [\"2-digit\", \"numeric\"],\n month: [\"2-digit\", \"numeric\", \"narrow\", \"short\", \"long\"],\n day: [\"2-digit\", \"numeric\"],\n hour: [\"2-digit\", \"numeric\"],\n minute: [\"2-digit\", \"numeric\"],\n second: [\"2-digit\", \"numeric\"],\n timeZoneName: [\"short\", \"long\"]\n };\n\n var result = components[component];\n if (result === undefined) {\n $ERROR(\"Internal error: No values defined for date-time component \" + component + \".\");\n }\n return result;\n}\n\n\n\/**\n * Tests that the given value is valid for the given date-time component.\n * @param {string} component a date-time component.\n * @param {string} value the value to be tested.\n * @return {boolean} true if the test succeeds.\n * @exception if the test fails.\n *\/\n\nfunction testValidDateTimeComponentValue(component, value) {\n if (getDateTimeComponentValues(component).indexOf(value) === -1) {\n $ERROR(\"Invalid value \" + value + \" for date-time component \" + component + \".\");\n }\n return true;\n}\n\n\n\/**\n * Verifies that the actual array matches the expected one in length, elements,\n * and element order.\n * @param {Array} expected the expected array.\n * @param {Array} actual the actual array.\n * @return {boolean} true if the test succeeds.\n * @exception if the test fails.\n *\/\nfunction testArraysAreSame(expected, actual) {\n for (i = 0; i < Math.max(actual.length, expected.length); i++) {\n if (actual[i] !== expected[i]) {\n $ERROR(\"Result array element at index \" + i + \" should be \\\"\" +\n expected[i] + \"\\\" but is \\\"\" + actual[i] + \"\\\".\");\n }\n }\n return true;\n}\n\n\nfunction testcase() {\n var test0 = 0, test1 = 1, test2 = 2;\n var tokenCodes = {\n set in(value){\n test0 = value;\n },\n get in(){\n return test0;\n },\n set try(value){\n test1 = value;\n },\n get try(){\n return test1\n },\n set class(value){\n test2 = value;\n },\n get class(){\n return test2;\n }\n };\n var arr = [\n \'in\',\n \'try\',\n \'class\'\n ];\n for(var p in tokenCodes) {\n for(var p1 in arr) {\n if(arr[p1] === p) {\n if(!tokenCodes.hasOwnProperty(arr[p1])) {\n return false;\n };\n }\n }\n }\n return true;\n }\nrunTestCase(testcase);"; | |
var ast = UglifyJS.parse(test); | |
var result = ast.print_to_string(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var strict_mode = false; | |
function testRun(id, path, description, codeString, result, error) { | |
if (result!=="pass") { | |
throw new Error("Test '" + path + "'failed: " + error); | |
} | |
} | |
function testFinished() { | |
//no-op | |
} | |
function compareArray(aExpected, aActual) { | |
if (aActual.length != aExpected.length) { | |
return false; | |
} | |
aExpected.sort(); | |
aActual.sort(); | |
var s; | |
for (var i = 0; i < aExpected.length; i++) { | |
if (aActual[i] !== aExpected[i]) { | |
return false; | |
} | |
} | |
return true; | |
} | |
//----------------------------------------------------------------------------- | |
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; | |
} | |
} | |
return true; | |
} | |
//----------------------------------------------------------------------------- | |
var supportsArrayIndexGettersOnArrays = undefined; | |
function fnSupportsArrayIndexGettersOnArrays() { | |
if (typeof supportsArrayIndexGettersOnArrays !== "undefined") { | |
return supportsArrayIndexGettersOnArrays; | |
} | |
supportsArrayIndexGettersOnArrays = false; | |
if (fnExists(Object.defineProperty)) { | |
var arr = []; | |
Object.defineProperty(arr, "0", { | |
get: function() { | |
supportsArrayIndexGettersOnArrays = true; | |
return 0; | |
} | |
}); | |
var res = arr[0]; | |
} | |
return supportsArrayIndexGettersOnArrays; | |
} | |
//----------------------------------------------------------------------------- | |
var supportsArrayIndexGettersOnObjects = undefined; | |
function fnSupportsArrayIndexGettersOnObjects() { | |
if (typeof supportsArrayIndexGettersOnObjects !== "undefined") | |
return supportsArrayIndexGettersOnObjects; | |
supportsArrayIndexGettersOnObjects = false; | |
if (fnExists(Object.defineProperty)) { | |
var obj = {}; | |
Object.defineProperty(obj, "0", { | |
get: function() { | |
supportsArrayIndexGettersOnObjects = true; | |
return 0; | |
} | |
}); | |
var res = obj[0]; | |
} | |
return supportsArrayIndexGettersOnObjects; | |
} | |
//----------------------------------------------------------------------------- | |
function ConvertToFileUrl(pathStr) { | |
return "file:" + pathStr.replace(/\\/g, "/"); | |
} | |
//----------------------------------------------------------------------------- | |
function fnExists(/*arguments*/) { | |
for (var i = 0; i < arguments.length; i++) { | |
if (typeof (arguments[i]) !== "function") return false; | |
} | |
return true; | |
} | |
//----------------------------------------------------------------------------- | |
var __globalObject = Function("return this;")(); | |
function fnGlobalObject() { | |
return __globalObject; | |
} | |
//----------------------------------------------------------------------------- | |
function fnSupportsStrict() { | |
"use strict"; | |
try { | |
eval('with ({}) {}'); | |
return false; | |
} catch (e) { | |
return true; | |
} | |
} | |
//----------------------------------------------------------------------------- | |
//Verify all attributes specified data property of given object: | |
//value, writable, enumerable, configurable | |
//If all attribute values are expected, return true, otherwise, return false | |
function dataPropertyAttributesAreCorrect(obj, | |
name, | |
value, | |
writable, | |
enumerable, | |
configurable) { | |
var attributesCorrect = true; | |
if (obj[name] !== value) { | |
if (typeof obj[name] === "number" && | |
isNaN(obj[name]) && | |
typeof value === "number" && | |
isNaN(value)) { | |
// keep empty | |
} else { | |
attributesCorrect = false; | |
} | |
} | |
try { | |
if (obj[name] === "oldValue") { | |
obj[name] = "newValue"; | |
} else { | |
obj[name] = "OldValue"; | |
} | |
} catch (we) { | |
} | |
var overwrited = false; | |
if (obj[name] !== value) { | |
if (typeof obj[name] === "number" && | |
isNaN(obj[name]) && | |
typeof value === "number" && | |
isNaN(value)) { | |
// keep empty | |
} else { | |
overwrited = true; | |
} | |
} | |
if (overwrited !== writable) { | |
attributesCorrect = false; | |
} | |
var enumerated = false; | |
for (var prop in obj) { | |
if (obj.hasOwnProperty(prop) && prop === name) { | |
enumerated = true; | |
} | |
} | |
if (enumerated !== enumerable) { | |
attributesCorrect = false; | |
} | |
var deleted = false; | |
try { | |
delete obj[name]; | |
} catch (de) { | |
} | |
if (!obj.hasOwnProperty(name)) { | |
deleted = true; | |
} | |
if (deleted !== configurable) { | |
attributesCorrect = false; | |
} | |
return attributesCorrect; | |
} | |
//----------------------------------------------------------------------------- | |
//Verify all attributes specified accessor property of given object: | |
//get, set, enumerable, configurable | |
//If all attribute values are expected, return true, otherwise, return false | |
function accessorPropertyAttributesAreCorrect(obj, | |
name, | |
get, | |
set, | |
setVerifyHelpProp, | |
enumerable, | |
configurable) { | |
var attributesCorrect = true; | |
if (get !== undefined) { | |
if (obj[name] !== get()) { | |
if (typeof obj[name] === "number" && | |
isNaN(obj[name]) && | |
typeof get() === "number" && | |
isNaN(get())) { | |
// keep empty | |
} else { | |
attributesCorrect = false; | |
} | |
} | |
} else { | |
if (obj[name] !== undefined) { | |
attributesCorrect = false; | |
} | |
} | |
try { | |
var desc = Object.getOwnPropertyDescriptor(obj, name); | |
if (typeof desc.set === "undefined") { | |
if (typeof set !== "undefined") { | |
attributesCorrect = false; | |
} | |
} else { | |
obj[name] = "toBeSetValue"; | |
if (obj[setVerifyHelpProp] !== "toBeSetValue") { | |
attributesCorrect = false; | |
} | |
} | |
} catch (se) { | |
throw se; | |
} | |
var enumerated = false; | |
for (var prop in obj) { | |
if (obj.hasOwnProperty(prop) && prop === name) { | |
enumerated = true; | |
} | |
} | |
if (enumerated !== enumerable) { | |
attributesCorrect = false; | |
} | |
var deleted = false; | |
try { | |
delete obj[name]; | |
} catch (de) { | |
throw de; | |
} | |
if (!obj.hasOwnProperty(name)) { | |
deleted = true; | |
} | |
if (deleted !== configurable) { | |
attributesCorrect = false; | |
} | |
return attributesCorrect; | |
} | |
//----------------------------------------------------------------------------- | |
var NotEarlyErrorString = "NotEarlyError"; | |
var EarlyErrorRePat = "^((?!" + NotEarlyErrorString + ").)*$"; | |
var NotEarlyError = new Error(NotEarlyErrorString); | |
//----------------------------------------------------------------------------- | |
// Copyright 2009 the Sputnik authors. All rights reserved. | |
// This code is governed by the BSD license found in the LICENSE file. | |
function Test262Error(message) { | |
if (message) this.message = message; | |
} | |
Test262Error.prototype.toString = function () { | |
return "Test262 Error: " + this.message; | |
}; | |
function testFailed(message) { | |
throw new Test262Error(message); | |
} | |
function testPrint(message) { | |
} | |
//adaptors for Test262 framework | |
function $PRINT(message) { | |
} | |
function $INCLUDE(message) { } | |
function $ERROR(message) { | |
testFailed(message); | |
} | |
function $FAIL(message) { | |
testFailed(message); | |
} | |
//Sputnik library definitions | |
//Ultimately these should be namespaced some how and only made | |
//available to tests that explicitly include them. | |
//For now, we just define the globally | |
//math_precision.js | |
// Copyright 2009 the Sputnik authors. All rights reserved. | |
// This code is governed by the BSD license found in the LICENSE file. | |
function getPrecision(num) { | |
//TODO: Create a table of prec's, | |
// because using Math for testing Math isn't that correct. | |
var log2num = Math.log(Math.abs(num)) / Math.LN2; | |
var pernum = Math.ceil(log2num); | |
return (2 * Math.pow(2, -52 + pernum)); | |
//return(0); | |
} | |
//math_isequal.js | |
// Copyright 2009 the Sputnik authors. All rights reserved. | |
// This code is governed by the BSD license found in the LICENSE file. | |
var prec; | |
function isEqual(num1, num2) { | |
if ((num1 === Infinity) && (num2 === Infinity)) { | |
return (true); | |
} | |
if ((num1 === -Infinity) && (num2 === -Infinity)) { | |
return (true); | |
} | |
prec = getPrecision(Math.min(Math.abs(num1), Math.abs(num2))); | |
return (Math.abs(num1 - num2) <= prec); | |
//return(num1 === num2); | |
} | |
//numeric_conversion.js | |
// Copyright 2009 the Sputnik authors. All rights reserved. | |
// This code is governed by the BSD license found in the LICENSE file. | |
function ToInteger(p) { | |
var x = Number(p); | |
if (isNaN(x)) { | |
return +0; | |
} | |
if ((x === +0) | |
|| (x === -0) | |
|| (x === Number.POSITIVE_INFINITY) | |
|| (x === Number.NEGATIVE_INFINITY)) { | |
return x; | |
} | |
var sign = (x < 0) ? -1 : 1; | |
return (sign * Math.floor(Math.abs(x))); | |
} | |
//Date_constants.js | |
// Copyright 2009 the Sputnik authors. All rights reserved. | |
// This code is governed by the BSD license found in the LICENSE file. | |
var HoursPerDay = 24; | |
var MinutesPerHour = 60; | |
var SecondsPerMinute = 60; | |
var msPerDay = 86400000; | |
var msPerSecond = 1000; | |
var msPerMinute = 60000; | |
var msPerHour = 3600000; | |
var date_1899_end = -2208988800001; | |
var date_1900_start = -2208988800000; | |
var date_1969_end = -1; | |
var date_1970_start = 0; | |
var date_1999_end = 946684799999; | |
var date_2000_start = 946684800000; | |
var date_2099_end = 4102444799999; | |
var date_2100_start = 4102444800000; | |
// Copyright 2009 the Sputnik authors. All rights reserved. | |
// This code is governed by the BSD license found in the LICENSE file. | |
//the following values are normally generated by the sputnik.py driver | |
var $LocalTZ, | |
$DST_start_month, | |
$DST_start_sunday, | |
$DST_start_hour, | |
$DST_start_minutes, | |
$DST_end_month, | |
$DST_end_sunday, | |
$DST_end_hour, | |
$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); | |
} | |
} | |
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 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(); | |
return; | |
})(); | |
//Date.library.js | |
// Copyright 2009 the Sputnik authors. All rights reserved. | |
// This code is governed by the BSD license found in the LICENSE file. | |
//15.9.1.2 Day Number and Time within Day | |
function Day(t) { | |
return Math.floor(t/msPerDay); | |
} | |
function TimeWithinDay(t) { | |
return t%msPerDay; | |
} | |
//15.9.1.3 Year Number | |
function DaysInYear(y){ | |
if(y%4 != 0) return 365; | |
if(y%4 == 0 && y%100 != 0) return 366; | |
if(y%100 == 0 && y%400 != 0) return 365; | |
if(y%400 == 0) return 366; | |
} | |
function DayFromYear(y) { | |
return (365*(y-1970) | |
+ Math.floor((y-1969)/4) | |
- Math.floor((y-1901)/100) | |
+ Math.floor((y-1601)/400)); | |
} | |
function TimeFromYear(y){ | |
return msPerDay*DayFromYear(y); | |
} | |
function YearFromTime(t) { | |
t = Number(t); | |
var sign = ( t < 0 ) ? -1 : 1; | |
var year = ( sign < 0 ) ? 1969 : 1970; | |
for(var time = 0;;year += sign){ | |
time = TimeFromYear(year); | |
if(sign > 0 && time > t){ | |
year -= sign; | |
break; | |
} | |
else if(sign < 0 && time <= t){ | |
break; | |
} | |
}; | |
return year; | |
} | |
function InLeapYear(t){ | |
if(DaysInYear(YearFromTime(t)) == 365) | |
return 0; | |
if(DaysInYear(YearFromTime(t)) == 366) | |
return 1; | |
} | |
function DayWithinYear(t) { | |
return Day(t)-DayFromYear(YearFromTime(t)); | |
} | |
//15.9.1.4 Month Number | |
function MonthFromTime(t){ | |
var day = DayWithinYear(t); | |
var leap = InLeapYear(t); | |
if((0 <= day) && (day < 31)) return 0; | |
if((31 <= day) && (day < (59+leap))) return 1; | |
if(((59+leap) <= day) && (day < (90+leap))) return 2; | |
if(((90+leap) <= day) && (day < (120+leap))) return 3; | |
if(((120+leap) <= day) && (day < (151+leap))) return 4; | |
if(((151+leap) <= day) && (day < (181+leap))) return 5; | |
if(((181+leap) <= day) && (day < (212+leap))) return 6; | |
if(((212+leap) <= day) && (day < (243+leap))) return 7; | |
if(((243+leap) <= day) && (day < (273+leap))) return 8; | |
if(((273+leap) <= day) && (day < (304+leap))) return 9; | |
if(((304+leap) <= day) && (day < (334+leap))) return 10; | |
if(((334+leap) <= day) && (day < (365+leap))) return 11; | |
} | |
//15.9.1.5 Date Number | |
function DateFromTime(t) { | |
var day = DayWithinYear(t); | |
var month = MonthFromTime(t); | |
var leap = InLeapYear(t); | |
if(month == 0) return day+1; | |
if(month == 1) return day-30; | |
if(month == 2) return day-58-leap; | |
if(month == 3) return day-89-leap; | |
if(month == 4) return day-119-leap; | |
if(month == 5) return day-150-leap; | |
if(month == 6) return day-180-leap; | |
if(month == 7) return day-211-leap; | |
if(month == 8) return day-242-leap; | |
if(month == 9) return day-272-leap; | |
if(month == 10) return day-303-leap; | |
if(month == 11) return day-333-leap; | |
} | |
//15.9.1.6 Week Day | |
function WeekDay(t) { | |
var weekday = (Day(t)+4)%7; | |
return (weekday < 0 ? 7+weekday : weekday); | |
} | |
//15.9.1.9 Daylight Saving Time Adjustment | |
$LocalTZ = (new Date()).getTimezoneOffset() / -60; | |
if (DaylightSavingTA((new Date()).valueOf()) !== 0) { | |
$LocalTZ -= 1; | |
} | |
var LocalTZA = $LocalTZ*msPerHour; | |
function DaysInMonth(m, leap) { | |
m = m%12; | |
//April, June, Sept, Nov | |
if(m == 3 || m == 5 || m == 8 || m == 10 ) { | |
return 30; | |
} | |
//Jan, March, May, July, Aug, Oct, Dec | |
if(m == 0 || m == 2 || m == 4 || m == 6 || m == 7 || m == 9 || m == 11){ | |
return 31; | |
} | |
//Feb | |
return 28+leap; | |
} | |
function GetSundayInMonth(t, m, count){ | |
var year = YearFromTime(t); | |
var tempDate; | |
if (count==='"first"') { | |
for (var d=1; d <= DaysInMonth(m, InLeapYear(t)); d++) { | |
tempDate = new Date(year, m, d); | |
if (tempDate.getDay()===0) { | |
return tempDate.valueOf(); | |
} | |
} | |
} else if(count==='"last"') { | |
for (var d=DaysInMonth(m, InLeapYear(t)); d>0; d--) { | |
tempDate = new Date(year, m, d); | |
if (tempDate.getDay()===0) { | |
return tempDate.valueOf(); | |
} | |
} | |
} | |
throw new Error("Unsupported 'count' arg:" + count); | |
} | |
/* | |
function GetSundayInMonth(t, m, count){ | |
var year = YearFromTime(t); | |
var leap = InLeapYear(t); | |
var day = 0; | |
if(m >= 1) day += DaysInMonth(0, leap); | |
if(m >= 2) day += DaysInMonth(1, leap); | |
if(m >= 3) day += DaysInMonth(2, leap); | |
if(m >= 4) day += DaysInMonth(3, leap); | |
if(m >= 5) day += DaysInMonth(4, leap); | |
if(m >= 6) day += DaysInMonth(5, leap); | |
if(m >= 7) day += DaysInMonth(6, leap); | |
if(m >= 8) day += DaysInMonth(7, leap); | |
if(m >= 9) day += DaysInMonth(8, leap); | |
if(m >= 10) day += DaysInMonth(9, leap); | |
if(m >= 11) day += DaysInMonth(10, leap); | |
var month_start = TimeFromYear(year)+day*msPerDay; | |
var sunday = 0; | |
if(count === "last"){ | |
for(var last_sunday = month_start+DaysInMonth(m, leap)*msPerDay; | |
WeekDay(last_sunday)>0; | |
last_sunday -= msPerDay | |
){}; | |
sunday = last_sunday; | |
} | |
else { | |
for(var first_sunday = month_start; | |
WeekDay(first_sunday)>0; | |
first_sunday += msPerDay | |
){}; | |
sunday = first_sunday+7*msPerDay*(count-1); | |
} | |
return sunday; | |
}*/ | |
function DaylightSavingTA(t) { | |
// t = t-LocalTZA; | |
var DST_start = GetSundayInMonth(t, $DST_start_month, $DST_start_sunday) + | |
$DST_start_hour*msPerHour + | |
$DST_start_minutes*msPerMinute; | |
var k = new Date(DST_start); | |
var DST_end = GetSundayInMonth(t, $DST_end_month, $DST_end_sunday) + | |
$DST_end_hour*msPerHour + | |
$DST_end_minutes*msPerMinute; | |
if ( t >= DST_start && t < DST_end ) { | |
return msPerHour; | |
} else { | |
return 0; | |
} | |
} | |
//15.9.1.9 Local Time | |
function LocalTime(t){ | |
return t+LocalTZA+DaylightSavingTA(t); | |
} | |
function UTC(t) { | |
return t-LocalTZA-DaylightSavingTA(t-LocalTZA); | |
} | |
//15.9.1.10 Hours, Minutes, Second, and Milliseconds | |
function HourFromTime(t){ | |
return Math.floor(t/msPerHour)%HoursPerDay; | |
} | |
function MinFromTime(t){ | |
return Math.floor(t/msPerMinute)%MinutesPerHour; | |
} | |
function SecFromTime(t){ | |
return Math.floor(t/msPerSecond)%SecondsPerMinute; | |
} | |
function msFromTime(t){ | |
return t%msPerSecond; | |
} | |
//15.9.1.11 MakeTime (hour, min, sec, ms) | |
function MakeTime(hour, min, sec, ms){ | |
if ( !isFinite(hour) || !isFinite(min) || !isFinite(sec) || !isFinite(ms)) { | |
return Number.NaN; | |
} | |
hour = ToInteger(hour); | |
min = ToInteger(min); | |
sec = ToInteger(sec); | |
ms = ToInteger(ms); | |
return ((hour*msPerHour) + (min*msPerMinute) + (sec*msPerSecond) + ms); | |
} | |
//15.9.1.12 MakeDay (year, month, date) | |
function MakeDay(year, month, date) { | |
if ( !isFinite(year) || !isFinite(month) || !isFinite(date)) { | |
return Number.NaN; | |
} | |
year = ToInteger(year); | |
month = ToInteger(month); | |
date = ToInteger(date ); | |
var result5 = year + Math.floor(month/12); | |
var result6 = month%12; | |
var sign = ( year < 1970 ) ? -1 : 1; | |
var t = ( year < 1970 ) ? 1 : 0; | |
var y = ( year < 1970 ) ? 1969 : 1970; | |
if( sign == -1 ){ | |
for ( y = 1969; y >= year; y += sign ) { | |
t += sign * DaysInYear(y)*msPerDay; | |
} | |
} else { | |
for ( y = 1970 ; y < year; y += sign ) { | |
t += sign * DaysInYear(y)*msPerDay; | |
} | |
} | |
var leap = 0; | |
for ( var m = 0; m < month; m++ ) { | |
//if year is changed, than we need to recalculate leep | |
leap = InLeapYear(t); | |
t += DaysInMonth(m, leap)*msPerDay; | |
} | |
if ( YearFromTime(t) != result5 ) { | |
return Number.NaN; | |
} | |
if ( MonthFromTime(t) != result6 ) { | |
return Number.NaN; | |
} | |
if ( DateFromTime(t) != 1 ) { | |
return Number.NaN; | |
} | |
return Day(t)+date-1; | |
} | |
//15.9.1.13 MakeDate (day, time) | |
function MakeDate( day, time ) { | |
if(!isFinite(day) || !isFinite(time)) { | |
return Number.NaN; | |
} | |
return day*msPerDay+time; | |
} | |
//15.9.1.14 TimeClip (time) | |
function TimeClip(time) { | |
if(!isFinite(time) || Math.abs(time) > 8.64e15){ | |
return Number.NaN; | |
} | |
return ToInteger(time); | |
} | |
//Test Functions | |
//ConstructDate is considered deprecated, and should not be used directly from | |
//test262 tests as it's incredibly sensitive to DST start/end dates that | |
//vary with geographic location. | |
function ConstructDate(year, month, date, hours, minutes, seconds, ms){ | |
/* | |
* 1. Call ToNumber(year) | |
* 2. Call ToNumber(month) | |
* 3. If date is supplied use ToNumber(date); else use 1 | |
* 4. If hours is supplied use ToNumber(hours); else use 0 | |
* 5. If minutes is supplied use ToNumber(minutes); else use 0 | |
* 6. If seconds is supplied use ToNumber(seconds); else use 0 | |
* 7. If ms is supplied use ToNumber(ms); else use 0 | |
* 8. If Result(1) is not NaN and 0 <= ToInteger(Result(1)) <= 99, Result(8) is | |
* 1900+ToInteger(Result(1)); otherwise, Result(8) is Result(1) | |
* 9. Compute MakeDay(Result(8), Result(2), Result(3)) | |
* 10. Compute MakeTime(Result(4), Result(5), Result(6), Result(7)) | |
* 11. Compute MakeDate(Result(9), Result(10)) | |
* 12. Set the [[Value]] property of the newly constructed object to TimeClip(UTC(Result(11))) | |
*/ | |
var r1 = Number(year); | |
var r2 = Number(month); | |
var r3 = ((date && arguments.length > 2) ? Number(date) : 1); | |
var r4 = ((hours && arguments.length > 3) ? Number(hours) : 0); | |
var r5 = ((minutes && arguments.length > 4) ? Number(minutes) : 0); | |
var r6 = ((seconds && arguments.length > 5) ? Number(seconds) : 0); | |
var r7 = ((ms && arguments.length > 6) ? Number(ms) : 0); | |
var r8 = r1; | |
if(!isNaN(r1) && (0 <= ToInteger(r1)) && (ToInteger(r1) <= 99)) | |
r8 = 1900+r1; | |
var r9 = MakeDay(r8, r2, r3); | |
var r10 = MakeTime(r4, r5, r6, r7); | |
var r11 = MakeDate(r9, r10); | |
var retVal = TimeClip(UTC(r11)); | |
return retVal; | |
} | |
/**** Python code for initialize the above constants | |
// We may want to replicate the following in JavaScript. | |
// However, using JS date operations to generate parameters that are then used to | |
// test those some date operations seems unsound. However, it isn't clear if there | |
//is a good interoperable alternative. | |
# Copyright 2009 the Sputnik authors. All rights reserved. | |
# This code is governed by the BSD license found in the LICENSE file. | |
def GetDaylightSavingsTimes(): | |
# Is the given floating-point time in DST? | |
def IsDst(t): | |
return time.localtime(t)[-1] | |
# Binary search to find an interval between the two times no greater than | |
# delta where DST switches, returning the midpoint. | |
def FindBetween(start, end, delta): | |
while end - start > delta: | |
middle = (end + start) / 2 | |
if IsDst(middle) == IsDst(start): | |
start = middle | |
else: | |
end = middle | |
return (start + end) / 2 | |
now = time.time() | |
one_month = (30 * 24 * 60 * 60) | |
# First find a date with different daylight savings. To avoid corner cases | |
# we try four months before and after today. | |
after = now + 4 * one_month | |
before = now - 4 * one_month | |
if IsDst(now) == IsDst(before) and IsDst(now) == IsDst(after): | |
logger.warning("Was unable to determine DST info.") | |
return None | |
# Determine when the change occurs between now and the date we just found | |
# in a different DST. | |
if IsDst(now) != IsDst(before): | |
first = FindBetween(before, now, 1) | |
else: | |
first = FindBetween(now, after, 1) | |
# Determine when the change occurs between three and nine months from the | |
# first. | |
second = FindBetween(first + 3 * one_month, first + 9 * one_month, 1) | |
# Find out which switch is into and which if out of DST | |
if IsDst(first - 1) and not IsDst(first + 1): | |
start = second | |
end = first | |
else: | |
start = first | |
end = second | |
return (start, end) | |
def GetDaylightSavingsAttribs(): | |
times = GetDaylightSavingsTimes() | |
if not times: | |
return None | |
(start, end) = times | |
def DstMonth(t): | |
return time.localtime(t)[1] - 1 | |
def DstHour(t): | |
return time.localtime(t - 1)[3] + 1 | |
def DstSunday(t): | |
if time.localtime(t)[2] > 15: | |
return "'last'" | |
else: | |
return "'first'" | |
def DstMinutes(t): | |
return (time.localtime(t - 1)[4] + 1) % 60 | |
attribs = { } | |
attribs['start_month'] = DstMonth(start) | |
attribs['end_month'] = DstMonth(end) | |
attribs['start_sunday'] = DstSunday(start) | |
attribs['end_sunday'] = DstSunday(end) | |
attribs['start_hour'] = DstHour(start) | |
attribs['end_hour'] = DstHour(end) | |
attribs['start_minutes'] = DstMinutes(start) | |
attribs['end_minutes'] = DstMinutes(end) | |
return attribs | |
*********/ | |
//--Test case registration----------------------------------------------------- | |
function runTestCase(testcase) { | |
if (testcase() !== true) { | |
$ERROR("Test case returned non-true value!"); | |
} | |
} | |
if (this.window!==undefined) { //for console support | |
this.window.onerror = function(errorMsg, url, lineNumber) { | |
this.window.iframeError = errorMsg; | |
}; | |
} | |
//This doesn't work with early errors in current versions of Opera | |
/* | |
if (/opera/i.test(navigator.userAgent)) { | |
(function() { | |
var origError = window.Error; | |
window.Error = function() { | |
if (arguments.length>0) { | |
try { | |
window.onerror(arguments[0]); | |
} catch(e) { | |
alert("Failed to invoke window.onerror (from ed.js)"); | |
} | |
} | |
return origError.apply(this, arguments); | |
} | |
})(); | |
}*/ | |
/** | |
* @description Tests that obj meets the requirements for built-in objects | |
* 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. | |
* @param {number} length for functions only: the length specified for the function | |
* 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."); | |
} | |
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."); | |
} | |
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 not be configurable."); | |
} | |
} | |
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 function must be writable."); | |
} | |
if (desc.enumerable) { | |
$ERROR("The " + prop + " property of this built-in function must not be enumerable."); | |
} | |
if (!desc.configurable) { | |
$ERROR("The " + prop + " property of this built-in function 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."); | |
} | |
} | |
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; | |
} | |
/** | |
* This file contains shared functions for the tests in the conformance test | |
* suite for the ECMAScript Internationalization API. | |
* @author Norbert Lindenberg | |
*/ | |
/** | |
* @description Calls the provided function for every service constructor in | |
* 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. | |
* @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; | |
}); | |
} | |
/** | |
* Returns the name of the given constructor object, which must be one of | |
* Intl.Collator, Intl.NumberFormat, or Intl.DateTimeFormat. | |
* @param {object} Constructor a constructor | |
* @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"); | |
} | |
} | |
/** | |
* Taints a named data property of the given object by installing | |
* a setter that throws an exception. | |
* @param {object} obj the object whose data property to taint | |
* @param {string} property the property to taint | |
*/ | |
function taintDataProperty(obj, property) { | |
Object.defineProperty(obj, property, { | |
set: function(value) { | |
$ERROR("Client code can adversely affect behavior: setter for " + property + "."); | |
}, | |
enumerable: false, | |
configurable: true | |
}); | |
} | |
/** | |
* Taints a named method of the given object by replacing it with a function | |
* that throws an exception. | |
* @param {object} obj the object whose method to taint | |
* @param {string} property the name of the method to taint | |
*/ | |
function taintMethod(obj, property) { | |
Object.defineProperty(obj, property, { | |
value: function() { | |
$ERROR("Client code can adversely affect behavior: method " + property + "."); | |
}, | |
writable: true, | |
enumerable: false, | |
configurable: true | |
}); | |
} | |
/** | |
* Taints the given properties (and similarly named properties) by installing | |
* setters on Object.prototype that throw exceptions. | |
* @param {Array} properties an array of property names to taint | |
*/ | |
function taintProperties(properties) { | |
properties.forEach(function (property) { | |
var adaptedProperties = [property, "__" + property, "_" + property, property + "_", property + "__"]; | |
adaptedProperties.forEach(function (property) { | |
taintDataProperty(Object.prototype, property); | |
}); | |
}); | |
} | |
/** | |
* Taints the Array object by creating a setter for the property "0" and | |
* replacing some key methods with functions that throw exceptions. | |
*/ | |
function taintArray() { | |
taintDataProperty(Array.prototype, "0"); | |
taintMethod(Array.prototype, "indexOf"); | |
taintMethod(Array.prototype, "join"); | |
taintMethod(Array.prototype, "push"); | |
taintMethod(Array.prototype, "slice"); | |
taintMethod(Array.prototype, "sort"); | |
} | |
// auxiliary data for getLocaleSupportInfo | |
var languages = ["zh", "es", "en", "hi", "ur", "ar", "ja", "pa"]; | |
var scripts = ["Latn", "Hans", "Deva", "Arab", "Jpan", "Hant"]; | |
var countries = ["CN", "IN", "US", "PK", "JP", "TW", "HK", "SG"]; | |
var localeSupportInfo = {}; | |
/** | |
* Gets locale support info for the given constructor object, which must be one | |
* 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 | |
*/ | |
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 | |
}; | |
return localeSupportInfo[constructorName]; | |
} | |
/** | |
* @description Tests whether locale is a String value representing a | |
* structurally valid and canonicalized BCP 47 language tag, as defined in | |
* sections 6.2.2 and 6.2.3 of the ECMAScript Internationalization API | |
* Specification. | |
* @param {String} locale the string to be tested. | |
* @result {Boolean} whether the test succeeded. | |
*/ | |
function isCanonicalizedStructurallyValidLanguageTag(locale) { | |
/** | |
* Regular expression defining 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); | |
} | |
/** | |
* 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; | |
// 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; | |
} | |
return typeof locale === "string" && isStructurallyValidLanguageTag(locale) && | |
canonicalizeLanguageTag(locale) === locale; | |
} | |
/** | |
* Tests whether the named options property is correctly handled by the given constructor. | |
* @param {object} Constructor the constructor to test. | |
* @param {string} property the name of the options property to test. | |
* @param {string} type the type that values of the property are expected to have | |
* @param {Array} [values] an array of allowed values for the property. Not needed for boolean. | |
* @param {any} fallback the fallback value that the property assumes if not provided. | |
* @param {object} testOptions additional options: | |
* @param {boolean} isOptional whether support for this property is optional for implementations. | |
* @param {boolean} noReturn whether the resulting value of the property is not returned. | |
* @param {boolean} isILD whether the resulting value of the property is implementation and locale dependent. | |
* @param {object} extra additional option to pass along, properties are value -> {option: value}. | |
* @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 testValues, options, obj, expected, actual, error; | |
// test that the specified values are accepted. Also add values that convert to specified values. | |
if (type === "boolean") { | |
if (values === undefined) { | |
values = [true, false]; | |
} | |
testValues = values.slice(0); | |
testValues.push(888); | |
testValues.push(0); | |
} else if (type === "string") { | |
testValues = values.slice(0); | |
testValues.push({toString: function () { return values[0]; }}); | |
} | |
testValues.forEach(function (value) { | |
options = {}; | |
options[property] = value; | |
addExtraOptions(options, value, testOptions); | |
obj = new Constructor(undefined, options); | |
if (noReturn) { | |
if (obj.resolvedOptions().hasOwnProperty(property)) { | |
$ERROR("Option property " + property + " is returned, but shouldn't be."); | |
} | |
} else { | |
actual = obj.resolvedOptions()[property]; | |
if (isILD) { | |
if (actual !== undefined && values.indexOf(actual) === -1) { | |
$ERROR("Invalid value " + actual + " returned for property " + property + "."); | |
} | |
} else { | |
if (type === "boolean") { | |
expected = Boolean(value); | |
} else if (type === "string") { | |
expected = String(value); | |
} | |
if (actual !== expected && !(isOptional && actual === undefined)) { | |
$ERROR("Option value " + value + " for property " + property + | |
" was not accepted; got " + actual + " instead."); | |
} | |
} | |
} | |
}); | |
// test that invalid values are rejected | |
if (type === "string") { | |
var invalidValues = ["invalidValue", -1, null]; | |
// assume that we won't have values in caseless scripts | |
if (values[0].toUpperCase() !== values[0]) { | |
invalidValues.push(values[0].toUpperCase()); | |
} else { | |
invalidValues.push(values[0].toLowerCase()); | |
} | |
invalidValues.forEach(function (value) { | |
options = {}; | |
options[property] = value; | |
addExtraOptions(options, value, testOptions); | |
error = undefined; | |
try { | |
obj = new Constructor(undefined, options); | |
} catch (e) { | |
error = e; | |
} | |
if (error === undefined) { | |
$ERROR("Invalid option value " + value + " for property " + property + " was not rejected."); | |
} else if (error.name !== "RangeError") { | |
$ERROR("Invalid option value " + value + " for property " + property + " was rejected with wrong error " + error.name + "."); | |
} | |
}); | |
} | |
// test that fallback value or another valid value is used if no options value is provided | |
if (!noReturn) { | |
options = {}; | |
addExtraOptions(options, undefined, testOptions); | |
obj = new Constructor(undefined, options); | |
actual = obj.resolvedOptions()[property]; | |
if (!(isOptional && actual === undefined)) { | |
if (fallback !== undefined) { | |
if (actual !== fallback) { | |
$ERROR("Option fallback value " + fallback + " for property " + property + | |
" was not used; got " + actual + " instead."); | |
} | |
} else { | |
if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) { | |
$ERROR("Invalid value " + actual + " returned for property " + property + "."); | |
} | |
} | |
} | |
} | |
return true; | |
} | |
/** | |
* Tests whether the named property of the given object has a valid value | |
* and the default attributes of the properties of an object literal. | |
* @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. | |
* @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 + "."); | |
} | |
} | |
/** | |
* Tests whether the named property of the given object, if present at all, has a valid value | |
* and the default attributes of the properties of an object literal. | |
* @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. | |
* @exception if the property is present and has an invalid value. | |
*/ | |
function mayHaveProperty(obj, property, valid) { | |
if (obj.hasOwnProperty(property)) { | |
testProperty(obj, property, valid); | |
} | |
} | |
/** | |
* Tests whether the given object has the named property with a valid value | |
* and the default attributes of the properties of an object literal. | |
* @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. | |
* @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); | |
} | |
/** | |
* Tests whether the given object does not have the named property. | |
* @param {Object} obj the object to be tested. | |
* @param {string} property the name of the property | |
* @exception if the property is present. | |
*/ | |
function mustNotHaveProperty(obj, property) { | |
if (obj.hasOwnProperty(property)) { | |
$ERROR("Object has property it mustn't have: " + property + "."); | |
} | |
} | |
/** | |
* Properties of the RegExp constructor that may be affected by use of regular | |
* expressions, and the default values of these properties. Properties are from | |
* https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Deprecated_and_obsolete_features#RegExp_Properties | |
*/ | |
var regExpProperties = ["$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", | |
"$_", "$*", "$&", "$+", "$`", "$'", | |
"input", "lastMatch", "lastParen", "leftContext", "rightContext" | |
]; | |
var regExpPropertiesDefaultValues = (function () { | |
var values = Object.create(null); | |
regExpProperties.forEach(function (property) { | |
values[property] = RegExp[property]; | |
}); | |
return values; | |
}()); | |
/** | |
* Tests that executing the provided function (which may use regular expressions | |
* in its implementation) does not create or modify unwanted properties on the | |
* RegExp constructor. | |
*/ | |
function testForUnwantedRegExpChanges(testFunc) { | |
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] + "."); | |
} | |
}); | |
} | |
/** | |
* Tests whether name is a valid BCP 47 numbering system name | |
* and not excluded from use in the ECMAScript Internationalization API. | |
* @param {string} name the name to be tested. | |
* @return {boolean} whether name is a valid BCP 47 numbering system name and | |
* allowed for use in the ECMAScript Internationalization API. | |
*/ | |
function isValidNumberingSystem(name) { | |
// source: CLDR file common/bcp47/number.xml; version CLDR 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; | |
} | |
/** | |
* Provides the digits of numbering systems with simple digit mappings, | |
* as specified in 11.3.2. | |
*/ | |
var numberingSystemDigits = { | |
arab: "┘á┘í┘ó┘ú┘ñ┘Ñ┘ª┘º┘¿┘®", | |
arabext: "█░█▒█▓█│█┤█Á█Â█À█©█╣", | |
beng: "ÓºªÓººÓº¿Óº®Óº¬Óº½Óº¼Óº¡Óº«Óº»", | |
deva: "ÓѪÓѺÓÑ¿ÓÑ®ÓѬÓѽÓѼÓÑ¡ÓÑ«ÓÑ»", | |
fullwide: "´╝É´╝æ´╝Æ´╝ô´╝ö´╝ò´╝û´╝ù´╝ÿ´╝Ö", | |
gujr: "Ó½ªÓ½ºÓ½¿Ó½®Ó½¬Ó½½Ó½¼Ó½¡Ó½«Ó½»", | |
guru: "Ó®ªÓ®ºÓ®¿Ó®®Ó®¬Ó®½Ó®¼Ó®¡Ó®«Ó®»", | |
hanidec: "ÒÇçõ©Çõ║îõ©ëÕøøõ║öÕà¡õ©âÕà½õ╣Ø", | |
khmr: "߃á߃í߃ó߃ú߃ñ߃Ñ߃ªßƒºßƒ¿ßƒ®", | |
knda: "Ó│ªÓ│ºÓ│¿Ó│®Ó│¬Ó│½Ó│¼Ó│¡Ó│«Ó│»", | |
laoo: "Ó╗ÉÓ╗æÓ╗ÆÓ╗ôÓ╗öÓ╗òÓ╗ûÓ╗ùÓ╗ÿÓ╗Ö", | |
latn: "0123456789", | |
mlym: "ÓÁªÓÁºÓÁ¿ÓÁ®ÓÁ¬ÓÁ½ÓÁ¼ÓÁ¡ÓÁ«ÓÁ»", | |
mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙", | |
mymr: "၀၁၂၃၄၅၆၇၈၉", | |
orya: "Ó¡ªÓ¡ºÓ¡¿Ó¡®Ó¡¬Ó¡½Ó¡¼Ó¡¡Ó¡«Ó¡»", | |
tamldec: "Ó»ªÓ»ºÓ»¿Ó»®Ó»¬Ó»½Ó»¼Ó»¡Ó»«Ó»»", | |
telu: "Ó▒ªÓ▒ºÓ▒¿Ó▒®Ó▒¬Ó▒½Ó▒¼Ó▒¡Ó▒«Ó▒»", | |
thai: "Ó╣ÉÓ╣æÓ╣ÆÓ╣ôÓ╣öÓ╣òÓ╣ûÓ╣ùÓ╣ÿÓ╣Ö", | |
tibt: "Ó╝áÓ╝íÓ╝óÓ╝úÓ╝ñÓ╝ÑÓ╝ªÓ╝ºÓ╝¿Ó╝®" | |
}; | |
/** | |
* Tests that number formatting is handled correctly. The function checks that the | |
* digit sequences in formatted output are as specified, converted to the | |
* selected numbering system, and embedded in consistent localized patterns. | |
* @param {Array} locales the locales to be tested. | |
* @param {Array} numberingSystems the numbering systems to be tested. | |
* @param {Object} options the options to pass to Intl.NumberFormat. Options | |
* must include {useGrouping: false}, and must cause 1.1 to be formatted | |
* pre- and post-decimal digits. | |
* @param {Object} testData maps input data (in ES5 9.3.1 format) to expected output strings | |
* in unlocalized format with Western digits. | |
*/ | |
function testNumberFormat(locales, numberingSystems, options, testData) { | |
locales.forEach(function (locale) { | |
numberingSystems.forEach(function (numbering) { | |
var digits = numberingSystemDigits[numbering]; | |
var format = new Intl.NumberFormat([locale + "-u-nu-" + numbering], options); | |
function getPatternParts(positive) { | |
var n = positive ? 1.1 : -1.1; | |
var formatted = format.format(n); | |
var oneoneRE = "([^" + digits + "]*)[" + digits + "]+([^" + digits + "]+)[" + digits + "]+([^" + digits + "]*)"; | |
var match = formatted.match(new RegExp(oneoneRE)); | |
if (match === null) { | |
$ERROR("Unexpected formatted " + n + " for " + | |
format.resolvedOptions().locale + " and options " + | |
JSON.stringify(options) + ": " + formatted); | |
} | |
return match; | |
} | |
function toNumbering(raw) { | |
return raw.replace(/[0-9]/g, function (digit) { | |
return digits[digit.charCodeAt(0) - "0".charCodeAt(0)]; | |
}); | |
} | |
function buildExpected(raw, patternParts) { | |
var period = raw.indexOf("."); | |
if (period === -1) { | |
return patternParts[1] + toNumbering(raw) + patternParts[3]; | |
} else { | |
return patternParts[1] + | |
toNumbering(raw.substring(0, period)) + | |
patternParts[2] + | |
toNumbering(raw.substring(period + 1)) + | |
patternParts[3]; | |
} | |
} | |
if (format.resolvedOptions().numberingSystem === numbering) { | |
// figure out prefixes, infixes, suffixes for positive and negative values | |
var posPatternParts = getPatternParts(true); | |
var negPatternParts = getPatternParts(false); | |
Object.getOwnPropertyNames(testData).forEach(function (input) { | |
var rawExpected = testData[input]; | |
var patternParts; | |
if (rawExpected[0] === "-") { | |
patternParts = negPatternParts; | |
rawExpected = rawExpected.substring(1); | |
} else { | |
patternParts = posPatternParts; | |
} | |
var expected = buildExpected(rawExpected, patternParts); | |
var actual = format.format(input); | |
if (actual !== expected) { | |
$ERROR("Formatted value for " + input + ", " + | |
format.resolvedOptions().locale + " and options " + | |
JSON.stringify(options) + " is " + actual + "; expected " + expected + "."); | |
} | |
}); | |
} | |
}); | |
}); | |
} | |
/** | |
* Return the components of date-time formats. | |
* @return {Array} an array with all date-time components. | |
*/ | |
function getDateTimeComponents() { | |
return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"]; | |
} | |
/** | |
* Return the valid values for the given date-time component, as specified | |
* by the table in section 12.1.1. | |
* @param {string} component a date-time component. | |
* @return {Array} an array with the valid values for the component. | |
*/ | |
function getDateTimeComponentValues(component) { | |
var components = { | |
weekday: ["narrow", "short", "long"], | |
era: ["narrow", "short", "long"], | |
year: ["2-digit", "numeric"], | |
month: ["2-digit", "numeric", "narrow", "short", "long"], | |
day: ["2-digit", "numeric"], | |
hour: ["2-digit", "numeric"], | |
minute: ["2-digit", "numeric"], | |
second: ["2-digit", "numeric"], | |
timeZoneName: ["short", "long"] | |
}; | |
var result = components[component]; | |
if (result === undefined) { | |
$ERROR("Internal error: No values defined for date-time component " + component + "."); | |
} | |
return result; | |
} | |
/** | |
* Tests that the given value is valid for the given date-time component. | |
* @param {string} component a date-time component. | |
* @param {string} value the value to be tested. | |
* @return {boolean} true if the test succeeds. | |
* @exception if the test fails. | |
*/ | |
function testValidDateTimeComponentValue(component, value) { | |
if (getDateTimeComponentValues(component).indexOf(value) === -1) { | |
$ERROR("Invalid value " + value + " for date-time component " + component + "."); | |
} | |
return true; | |
} | |
/** | |
* Verifies that the actual array matches the expected one in length, elements, | |
* and element order. | |
* @param {Array} expected the expected array. | |
* @param {Array} actual the actual array. | |
* @return {boolean} true if the test succeeds. | |
* @exception if the test fails. | |
*/ | |
function testArraysAreSame(expected, actual) { | |
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; | |
} | |
function testcase() { | |
var test0 = 0, test1 = 1, test2 = 2; | |
var tokenCodes = { | |
set in(value){ | |
test0 = value; | |
}, | |
get in(){ | |
return test0; | |
}, | |
set try(value){ | |
test1 = value; | |
}, | |
get try(){ | |
return test1 | |
}, | |
set class(value){ | |
test2 = value; | |
}, | |
get class(){ | |
return test2; | |
} | |
}; | |
var arr = [ | |
'in', | |
'try', | |
'class' | |
]; | |
for(var p in tokenCodes) { | |
for(var p1 in arr) { | |
if(arr[p1] === p) { | |
if(!tokenCodes.hasOwnProperty(arr[p1])) { | |
return false; | |
}; | |
} | |
} | |
} | |
return true; | |
} | |
runTestCase(testcase); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copy from https://github.com/tc39/test262/blob/7da91bceb9ce7613f87db47ddd1292a2dda58b42/test/suite/ch07/7.6/7.6.1/7.6.1-4-10.js | |
/// Copyright (c) 2012 Ecma International. All rights reserved. | |
/// Ecma International makes this code available under the terms and conditions set | |
/// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the | |
/// "Use Terms"). Any redistribution of this code must retain the above | |
/// copyright and this notice and otherwise comply with the Use Terms. | |
/** | |
* @path ch07/7.6/7.6.1/7.6.1-4-10.js | |
* @description Allow reserved words as property names by set function within an object, verified with hasOwnProperty: in, try, class | |
*/ | |
function testcase() { | |
var test0 = 0, test1 = 1, test2 = 2; | |
var tokenCodes = { | |
set in(value){ | |
test0 = value; | |
}, | |
get in(){ | |
return test0; | |
}, | |
set try(value){ | |
test1 = value; | |
}, | |
get try(){ | |
return test1 | |
}, | |
set class(value){ | |
test2 = value; | |
}, | |
get class(){ | |
return test2; | |
} | |
}; | |
var arr = [ | |
'in', | |
'try', | |
'class' | |
]; | |
for(var p in tokenCodes) { | |
for(var p1 in arr) { | |
if(arr[p1] === p) { | |
if(!tokenCodes.hasOwnProperty(arr[p1])) { | |
return false; | |
}; | |
} | |
} | |
} | |
return true; | |
} | |
runTestCase(testcase); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment