Bug 1413505: Apply TimeClip in Intl.DateTimeFormat format methods. r=gandalf
authorAndré Bargull <andre.bargull@gmail.com>
Thu, 07 Dec 2017 04:59:05 -0800
changeset 450951 071076af815da074a65c6f8a09ffc02a6a67fa95
parent 450950 5590c751f6d814d8bf0b4fefa69fdf46182a63ed
child 450952 b8ded26d5d1960d2cb3cf8e46409643d811ba333
push id8543
push userryanvm@gmail.com
push dateTue, 16 Jan 2018 14:33:22 +0000
treeherdermozilla-beta@a6525ed16a32 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgandalf
bugs1413505
milestone59.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 1413505: Apply TimeClip in Intl.DateTimeFormat format methods. r=gandalf
js/src/builtin/Intl.cpp
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -25,16 +25,17 @@
 #include "jscntxt.h"
 #include "jsfriendapi.h"
 #include "jsobj.h"
 #include "jsstr.h"
 #include "jsutil.h"
 
 #include "builtin/IntlTimeZoneData.h"
 #include "ds/Sort.h"
+#include "js/Date.h"
 #if ENABLE_INTL_API
 #include "unicode/ucal.h"
 #include "unicode/ucol.h"
 #include "unicode/udat.h"
 #include "unicode/udatpg.h"
 #include "unicode/udisplaycontext.h"
 #include "unicode/uenum.h"
 #include "unicode/uloc.h"
@@ -62,16 +63,19 @@ using namespace js;
 using mozilla::AssertedCast;
 using mozilla::IsFinite;
 using mozilla::IsNaN;
 using mozilla::IsNegativeZero;
 using mozilla::PodCopy;
 using mozilla::Range;
 using mozilla::RangedPtr;
 
+using JS::ClippedTime;
+using JS::TimeClip;
+
 /*
  * Pervasive note: ICU functions taking a UErrorCode in/out parameter always
  * test that parameter before doing anything, and will return immediately if
  * the value indicates that a failure occurred in a prior ICU call,
  * without doing anything else. See
  * http://userguide.icu-project.org/design#TOC-Error-Handling
  */
 
@@ -3336,25 +3340,22 @@ NewUDateFormat(JSContext* cx, Handle<Dat
     ucal_setGregorianChange(cal, StartOfTime, &status);
 
     // An error here means the calendar is not Gregorian, so we don't care.
 
     return df;
 }
 
 static bool
-intl_FormatDateTime(JSContext* cx, UDateFormat* df, double x, MutableHandleValue result)
+intl_FormatDateTime(JSContext* cx, UDateFormat* df, ClippedTime x, MutableHandleValue result)
 {
-    if (!IsFinite(x)) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DATE_NOT_FINITE);
-        return false;
-    }
+    MOZ_ASSERT(x.isValid());
 
     JSString* str = Call(cx, [df, x](UChar* chars, int32_t size, UErrorCode* status) {
-        return udat_format(df, x, chars, size, nullptr, status);
+        return udat_format(df, x.toDouble(), chars, size, nullptr, status);
     });
     if (!str)
         return false;
 
     result.setString(str);
     return true;
 }
 
@@ -3440,34 +3441,32 @@ GetFieldTypeForFormatField(UDateFormatFi
     }
 
     MOZ_ASSERT_UNREACHABLE("unenumerated, undocumented format field returned "
                            "by iterator");
     return nullptr;
 }
 
 static bool
-intl_FormatToPartsDateTime(JSContext* cx, UDateFormat* df, double x, MutableHandleValue result)
+intl_FormatToPartsDateTime(JSContext* cx, UDateFormat* df, ClippedTime x,
+                           MutableHandleValue result)
 {
-    if (!IsFinite(x)) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DATE_NOT_FINITE);
-        return false;
-    }
+    MOZ_ASSERT(x.isValid());
 
     UErrorCode status = U_ZERO_ERROR;
     UFieldPositionIterator* fpositer = ufieldpositer_open(&status);
     if (U_FAILURE(status)) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
         return false;
     }
     ScopedICUObject<UFieldPositionIterator, ufieldpositer_close> toClose(fpositer);
 
     RootedString overallResult(cx);
     overallResult = Call(cx, [df, x, fpositer](UChar* chars, int32_t size, UErrorCode* status) {
-        return udat_formatForFields(df, x, chars, size, fpositer, status);
+        return udat_formatForFields(df, x.toDouble(), chars, size, fpositer, status);
     });
     if (!overallResult)
         return false;
 
     RootedArrayObject partsArray(cx, NewDenseEmptyArray(cx));
     if (!partsArray)
         return false;
 
@@ -3556,31 +3555,37 @@ js::intl_FormatDateTime(JSContext* cx, u
     MOZ_ASSERT(args.length() == 3);
     MOZ_ASSERT(args[0].isObject());
     MOZ_ASSERT(args[1].isNumber());
     MOZ_ASSERT(args[2].isBoolean());
 
     Rooted<DateTimeFormatObject*> dateTimeFormat(cx);
     dateTimeFormat = &args[0].toObject().as<DateTimeFormatObject>();
 
+    ClippedTime x = TimeClip(args[1].toNumber());
+    if (!x.isValid()) {
+        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DATE_NOT_FINITE);
+        return false;
+    }
+
     // Obtain a cached UDateFormat object.
     void* priv =
         dateTimeFormat->getReservedSlot(DateTimeFormatObject::UDATE_FORMAT_SLOT).toPrivate();
     UDateFormat* df = static_cast<UDateFormat*>(priv);
     if (!df) {
         df = NewUDateFormat(cx, dateTimeFormat);
         if (!df)
             return false;
         dateTimeFormat->setReservedSlot(DateTimeFormatObject::UDATE_FORMAT_SLOT, PrivateValue(df));
     }
 
     // Use the UDateFormat to actually format the time stamp.
     return args[2].toBoolean()
-           ? intl_FormatToPartsDateTime(cx, df, args[1].toNumber(), args.rval())
-           : intl_FormatDateTime(cx, df, args[1].toNumber(), args.rval());
+           ? intl_FormatToPartsDateTime(cx, df, x, args.rval())
+           : intl_FormatDateTime(cx, df, x, args.rval());
 }
 
 
 /**************** PluralRules *****************/
 
 const ClassOps PluralRulesObject::classOps_ = {
     nullptr, /* addProperty */
     nullptr, /* delProperty */