Bug 1407551 - Allow any printable ASCII characters in time zone names for Date.prototype.toString. r=Waldo
authorAndré Bargull <andre.bargull@gmail.com>
Thu, 12 Oct 2017 05:33:18 -0700
changeset 386001 7cf3c84c4d55993a2b89b0ea22047ddd1d2dc47e
parent 386000 85839dc9517240eba72ed8ba306d412facabf179
child 386002 10857abe539225fb09316d377f0f193d61dbf311
push id32673
push userarchaeopteryx@coole-files.de
push dateFri, 13 Oct 2017 09:13:17 +0000
treeherdermozilla-central@196dadb2fe50 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1407551
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1407551 - Allow any printable ASCII characters in time zone names for Date.prototype.toString. r=Waldo
js/src/jsdate.cpp
js/src/tests/ecma_6/Date/time-zones-pedantic.js
js/src/tests/ecma_6/Date/time-zones.js
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -2653,24 +2653,24 @@ FormatDate(JSContext* cx, double utcTime
 
             /* get a time zone string from the OS to include as a comment. */
             PRMJTime prtm = ToPRMJTime(localTime, utcTime);
             size_t tzlen = PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &prtm);
             if (tzlen != 0) {
                 /*
                  * Decide whether to use the resulting time zone string.
                  *
-                 * Reject it if it contains any non-ASCII, non-alphanumeric
+                 * Reject it if it contains any non-ASCII or non-printable
                  * characters.  It's then likely in some other character
                  * encoding, and we probably won't display it correctly.
                  */
                 usetz = true;
                 for (size_t i = 0; i < tzlen; i++) {
                     char16_t c = tzbuf[i];
-                    if (c > 127 || !(isalnum(c) || c == ' ' || c == '(' || c == ')' || c == '.')) {
+                    if (c > 127 || !isprint(c)) {
                         usetz = false;
                         break;
                     }
                 }
 
                 /* Also reject it if it's not parenthesized or if it's '()'. */
                 if (tzbuf[0] != '(' || tzbuf[1] == ')')
                     usetz = false;
--- a/js/src/tests/ecma_6/Date/time-zones-pedantic.js
+++ b/js/src/tests/ecma_6/Date/time-zones-pedantic.js
@@ -29,36 +29,40 @@ function inTimeZone(tzname, fn) {
 }
 
 const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].join("|");
 const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].join("|");
 const datePart = String.raw `(?:${weekdays}) (?:${months}) \d{2}`;
 const timePart = String.raw `\d{4,6} \d{2}:\d{2}:\d{2} GMT[+-]\d{4}`;
 const dateTimeRE = new RegExp(String.raw `^(${datePart} ${timePart})(?: \((.+)\))?$`);
 
-function assertDateTime(date, expected) {
+function assertDateTime(date, expected, alternativeTimeZone = undefined) {
     let actual = date.toString();
     assertEq(dateTimeRE.test(expected), true, `${expected}`);
     assertEq(dateTimeRE.test(actual), true, `${actual}`);
 
     let [, expectedDateTime, expectedTimeZone] = dateTimeRE.exec(expected);
     let [, actualDateTime, actualTimeZone] = dateTimeRE.exec(actual);
 
     assertEq(actualDateTime, expectedDateTime);
 
     // The time zone identifier is optional, so only compare its value if it's
     // present in |actual| and |expected|.
     if (expectedTimeZone !== undefined && actualTimeZone !== undefined) {
+        // Test against the alternative time zone identifier if necessary.
+        if (actualTimeZone !== expectedTimeZone && alternativeTimeZone !== undefined) {
+            expectedTimeZone = alternativeTimeZone;
+        }
         assertEq(actualTimeZone, expectedTimeZone);
     }
 }
 
 // bug 637244
 inTimeZone("Asia/Novosibirsk", () => {
     let dt1 = new Date(1984, Month.April, 1, -1);
-    assertDateTime(dt1, "Sat Mar 31 1984 23:00:00 GMT+0700 (NOVT)");
+    assertDateTime(dt1, "Sat Mar 31 1984 23:00:00 GMT+0700 (NOVT)", "+07");
 
     let dt2 = new Date(1984, Month.April, 1);
-    assertDateTime(dt2, "Sun Apr 01 1984 01:00:00 GMT+0800 (NOVST)");
+    assertDateTime(dt2, "Sun Apr 01 1984 01:00:00 GMT+0800 (NOVST)", "+08");
 });
 
 if (typeof reportCompare === "function")
     reportCompare(true, true);
--- a/js/src/tests/ecma_6/Date/time-zones.js
+++ b/js/src/tests/ecma_6/Date/time-zones.js
@@ -27,29 +27,33 @@ function inTimeZone(tzname, fn) {
 }
 
 const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].join("|");
 const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].join("|");
 const datePart = String.raw `(?:${weekdays}) (?:${months}) \d{2}`;
 const timePart = String.raw `\d{4,6} \d{2}:\d{2}:\d{2} GMT[+-]\d{4}`;
 const dateTimeRE = new RegExp(String.raw `^(${datePart} ${timePart})(?: \((.+)\))?$`);
 
-function assertDateTime(date, expected) {
+function assertDateTime(date, expected, alternativeTimeZone = undefined) {
     let actual = date.toString();
     assertEq(dateTimeRE.test(expected), true, `${expected}`);
     assertEq(dateTimeRE.test(actual), true, `${actual}`);
 
     let [, expectedDateTime, expectedTimeZone] = dateTimeRE.exec(expected);
     let [, actualDateTime, actualTimeZone] = dateTimeRE.exec(actual);
 
     assertEq(actualDateTime, expectedDateTime);
 
     // The time zone identifier is optional, so only compare its value if it's
     // present in |actual| and |expected|.
     if (expectedTimeZone !== undefined && actualTimeZone !== undefined) {
+        // Test against the alternative time zone identifier if necessary.
+        if (actualTimeZone !== expectedTimeZone && alternativeTimeZone !== undefined) {
+            expectedTimeZone = alternativeTimeZone;
+        }
         assertEq(actualTimeZone, expectedTimeZone);
     }
 }
 
 // bug 158328
 inTimeZone("Europe/London", () => {
     let dt1 = new Date(2002, Month.July, 19, 16, 10, 55);
     assertDateTime(dt1, "Fri Jul 19 2002 16:10:55 GMT+0100 (BST)");
@@ -207,17 +211,17 @@ inTimeZone("Europe/Vienna", () => {
     assertDateTime(dt3, "Sun Mar 30 2014 04:00:00 GMT+0200 (CEST)");
 });
 
 // bug 1084434
 inTimeZone("America/Sao_Paulo", () => {
     let dt = new Date(2014, Month.October, 19);
     assertEq(dt.getDate(), 19);
     assertEq(dt.getHours(), 1);
-    assertDateTime(dt, "Sun Oct 19 2014 01:00:00 GMT-0200 (BRST)");
+    assertDateTime(dt, "Sun Oct 19 2014 01:00:00 GMT-0200 (BRST)", "-02");
 });
 
 // bug 1084547
 inTimeZone("America/New_York", () => {
     let dt = new Date(Date.parse("2014-11-02T02:00:00-04:00"));
     assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0500 (EST)");
 
     dt.setMilliseconds(0);
@@ -243,23 +247,23 @@ inTimeZone("Europe/Moscow", () => {
 
     let dt4 = new Date(1984, Month.March, 32);
     assertEq(dt4.getDate(), 1);
 });
 
 // bug 1284507
 inTimeZone("Atlantic/Azores", () => {
     let dt1 = new Date(2017, Month.March, 25, 0, 0, 0);
-    assertDateTime(dt1, "Sat Mar 25 2017 00:00:00 GMT-0100 (AZOT)");
+    assertDateTime(dt1, "Sat Mar 25 2017 00:00:00 GMT-0100 (AZOT)", "-01");
 
     let dt2 = new Date(2016, Month.October, 30, 0, 0, 0);
-    assertDateTime(dt2, "Sun Oct 30 2016 00:00:00 GMT+0000 (AZOST)");
+    assertDateTime(dt2, "Sun Oct 30 2016 00:00:00 GMT+0000 (AZOST)", "+00");
 
     let dt3 = new Date(2016, Month.October, 30, 23, 0, 0);
-    assertDateTime(dt3, "Sun Oct 30 2016 23:00:00 GMT-0100 (AZOT)");
+    assertDateTime(dt3, "Sun Oct 30 2016 23:00:00 GMT-0100 (AZOT)", "-01");
 });
 
 // bug 1303306
 inTimeZone("America/New_York", () => {
     let dt = new Date(2016, Month.September, 15, 16, 14, 48);
     assertDateTime(dt, "Thu Sep 15 2016 16:14:48 GMT-0400 (EDT)");
 });