зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1158399 - Expose the [[DateValue]] field in Date objects only through a ClippedTime class that enforces prior TimeClip-ing on the given value. r=evilpie, r=bz, r=dhylands, r=mt, r=froydnj, r=khuey, r=baku, r=smaug
--HG-- extra : rebase_source : 803fe39f338b6b32cb0fe2be6cf4056bab57283a
This commit is contained in:
Родитель
0cacb70da5
Коммит
1b62a9d07b
|
@ -526,7 +526,7 @@ File::GetLastModifiedDate(ErrorResult& aRv)
|
|||
return Date();
|
||||
}
|
||||
|
||||
return Date(value);
|
||||
return Date(JS::TimeClip(value));
|
||||
}
|
||||
|
||||
int64_t
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
|
||||
#include "mozilla/dom/Date.h"
|
||||
|
||||
#include "jsapi.h" // for JS_ObjectIsDate, JS_NewDateObjectMsec
|
||||
#include "jsapi.h" // for JS_ObjectIsDate
|
||||
#include "jsfriendapi.h" // for DateGetMsecSinceEpoch
|
||||
#include "js/Date.h" // for JS::NewDateObject, JS::ClippedTime, JS::TimeClip
|
||||
#include "js/RootingAPI.h" // for Rooted, MutableHandle
|
||||
#include "js/Value.h" // for Value
|
||||
#include "mozilla/FloatingPoint.h" // for IsNaN, UnspecifiedNaN
|
||||
|
@ -15,30 +16,22 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
Date::Date()
|
||||
: mMsecSinceEpoch(UnspecifiedNaN<double>())
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Date::IsUndefined() const
|
||||
{
|
||||
return IsNaN(mMsecSinceEpoch);
|
||||
}
|
||||
|
||||
bool
|
||||
Date::SetTimeStamp(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
JS::Rooted<JSObject*> obj(aCx, aObject);
|
||||
MOZ_ASSERT(JS_ObjectIsDate(aCx, obj));
|
||||
mMsecSinceEpoch = js::DateGetMsecSinceEpoch(aCx, obj);
|
||||
double msecs = js::DateGetMsecSinceEpoch(aCx, obj);
|
||||
JS::ClippedTime time = JS::TimeClip(msecs);
|
||||
MOZ_ASSERT(NumbersAreIdentical(msecs, time.toDouble()));
|
||||
mMsecSinceEpoch = time;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Date::ToDateObject(JSContext* aCx, JS::MutableHandle<JS::Value> aRval) const
|
||||
{
|
||||
JSObject* obj = JS_NewDateObjectMsec(aCx, mMsecSinceEpoch);
|
||||
JSObject* obj = JS::NewDateObject(aCx, mMsecSinceEpoch);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef mozilla_dom_Date_h
|
||||
#define mozilla_dom_Date_h
|
||||
|
||||
#include "js/Date.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -17,21 +18,33 @@ namespace dom {
|
|||
class Date
|
||||
{
|
||||
public:
|
||||
// Not inlining much here to avoid the includes we'd need.
|
||||
Date();
|
||||
explicit Date(double aMilliseconds)
|
||||
Date() {}
|
||||
explicit Date(JS::ClippedTime aMilliseconds)
|
||||
: mMsecSinceEpoch(aMilliseconds)
|
||||
{}
|
||||
|
||||
bool IsUndefined() const;
|
||||
double TimeStamp() const
|
||||
bool IsUndefined() const
|
||||
{
|
||||
return !mMsecSinceEpoch.isValid();
|
||||
}
|
||||
|
||||
JS::ClippedTime TimeStamp() const
|
||||
{
|
||||
return mMsecSinceEpoch;
|
||||
}
|
||||
void SetTimeStamp(double aMilliseconds)
|
||||
|
||||
// Returns an integer in the range [-8.64e15, +8.64e15] (-0 excluded), *or*
|
||||
// returns NaN. DO NOT ASSUME THIS IS FINITE!
|
||||
double ToDouble() const
|
||||
{
|
||||
return mMsecSinceEpoch.toDouble();
|
||||
}
|
||||
|
||||
void SetTimeStamp(JS::ClippedTime aMilliseconds)
|
||||
{
|
||||
mMsecSinceEpoch = aMilliseconds;
|
||||
}
|
||||
|
||||
// Can return false if CheckedUnwrap fails. This will NOT throw;
|
||||
// callers should do it as needed.
|
||||
bool SetTimeStamp(JSContext* aCx, JSObject* aObject);
|
||||
|
@ -39,7 +52,7 @@ public:
|
|||
bool ToDateObject(JSContext* aCx, JS::MutableHandle<JS::Value> aRval) const;
|
||||
|
||||
private:
|
||||
double mMsecSinceEpoch;
|
||||
JS::ClippedTime mMsecSinceEpoch;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -4319,7 +4319,7 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
|
|||
|
||||
PRTime since = 0;
|
||||
if (aOptions.mSince.WasPassed() && !aOptions.mSince.Value().IsUndefined()) {
|
||||
since = PRTime(aOptions.mSince.Value().TimeStamp());
|
||||
since = PRTime(aOptions.mSince.Value().TimeStamp().toDouble());
|
||||
}
|
||||
|
||||
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "js/Value.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "jsapi.h"
|
||||
#include "js/Date.h"
|
||||
#include "mozilla/dom/FileModeBinding.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIFileStreams.h"
|
||||
|
@ -49,7 +50,7 @@ MetadataHelper::GetSuccessResult(JSContext* aCx,
|
|||
|
||||
if (mParams->LastModifiedRequested()) {
|
||||
double msec = mParams->LastModified();
|
||||
JSObject *date = JS_NewDateObjectMsec(aCx, msec);
|
||||
JSObject *date = JS::NewDateObject(aCx, JS::TimeClip(msec));
|
||||
NS_ENSURE_TRUE(date, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
JS::Rooted<JS::Value> dateRoot(aCx, JS::ObjectValue(*date));
|
||||
|
|
|
@ -1514,12 +1514,12 @@ HTMLInputElement::ConvertStringToNumber(nsAString& aValue,
|
|||
return false;
|
||||
}
|
||||
|
||||
double date = JS::MakeDate(year, month - 1, day);
|
||||
if (IsNaN(date)) {
|
||||
JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day));
|
||||
if (!time.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResultValue = Decimal::fromDouble(date);
|
||||
aResultValue = Decimal::fromDouble(time.toDouble());
|
||||
return true;
|
||||
}
|
||||
case NS_FORM_INPUT_TIME:
|
||||
|
@ -1762,7 +1762,8 @@ HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
|
|||
return Nullable<Date>();
|
||||
}
|
||||
|
||||
return Nullable<Date>(Date(JS::MakeDate(year, month - 1, day)));
|
||||
JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day));
|
||||
return Nullable<Date>(Date(time));
|
||||
}
|
||||
case NS_FORM_INPUT_TIME:
|
||||
{
|
||||
|
@ -1773,7 +1774,11 @@ HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
|
|||
return Nullable<Date>();
|
||||
}
|
||||
|
||||
return Nullable<Date>(Date(millisecond));
|
||||
JS::ClippedTime time = JS::TimeClip(millisecond);
|
||||
MOZ_ASSERT(time.toDouble() == millisecond,
|
||||
"HTML times are restricted to the day after the epoch and "
|
||||
"never clip");
|
||||
return Nullable<Date>(Date(time));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1795,7 +1800,7 @@ HTMLInputElement::SetValueAsDate(Nullable<Date> aDate, ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
|
||||
SetValue(Decimal::fromDouble(aDate.Value().TimeStamp()));
|
||||
SetValue(Decimal::fromDouble(aDate.Value().TimeStamp().toDouble()));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "IndexedDatabaseInlines.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/Date.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "KeyPath.h"
|
||||
#include "mozilla/Endian.h"
|
||||
|
@ -749,8 +750,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> date(aCx,
|
||||
JS_NewDateObjectMsec(aCx, aData.lastModifiedDate));
|
||||
JS::ClippedTime time = JS::TimeClip(aData.lastModifiedDate);
|
||||
JS::Rooted<JSObject*> date(aCx, JS::NewDateObject(aCx, time));
|
||||
if (NS_WARN_IF(!date)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "Key.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "js/Date.h"
|
||||
#include "js/Value.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/Endian.h"
|
||||
|
@ -237,7 +238,11 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
|||
}
|
||||
else if (*aPos - aTypeOffset == eDate) {
|
||||
double msec = static_cast<double>(DecodeNumber(aPos, aEnd));
|
||||
JSObject* date = JS_NewDateObjectMsec(aCx, msec);
|
||||
JS::ClippedTime time = JS::TimeClip(msec);
|
||||
MOZ_ASSERT(msec == time.toDouble(),
|
||||
"encoding from a Date object not containing an invalid date "
|
||||
"means we should always have clipped values");
|
||||
JSObject* date = JS::NewDateObject(aCx, time);
|
||||
if (!date) {
|
||||
IDB_WARNING("Failed to make date!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "mozilla/dom/Date.h"
|
||||
#include "mozilla/dom/CryptoKey.h"
|
||||
#include "mtransport/dtlsidentity.h"
|
||||
#include "js/Date.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
|
@ -54,7 +55,10 @@ public:
|
|||
|
||||
// WebIDL expires attribute. Note: JS dates are milliseconds since epoch;
|
||||
// NSPR PRTime is in microseconds since the same epoch.
|
||||
int64_t Expires() const { return mExpires / PR_USEC_PER_MSEC; }
|
||||
JS::ClippedTime Expires() const
|
||||
{
|
||||
return JS::TimeClip(mExpires / PR_USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
// Accessors for use by PeerConnectionImpl.
|
||||
RefPtr<DtlsIdentity> CreateDtlsIdentity() const;
|
||||
|
|
|
@ -34,7 +34,7 @@ TimeManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
void
|
||||
TimeManager::Set(Date& aDate)
|
||||
{
|
||||
Set(aDate.TimeStamp());
|
||||
Set(aDate.ToDouble());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
107
js/public/Date.h
107
js/public/Date.h
|
@ -3,51 +3,118 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* JavaScript date/time computation and creation functions. */
|
||||
|
||||
#ifndef js_Date_h
|
||||
#define js_Date_h
|
||||
|
||||
/*
|
||||
* Dates in JavaScript are defined by IEEE-754 double precision numbers from
|
||||
* the set:
|
||||
*
|
||||
* { t ∈ ℕ : -8.64e15 ≤ t ≤ +8.64e15 } ∪ { NaN }
|
||||
*
|
||||
* The single NaN value represents any invalid-date value. All other values
|
||||
* represent idealized durations in milliseconds since the UTC epoch. (Leap
|
||||
* seconds are ignored; leap days are not.) +0 is the only zero in this set.
|
||||
* The limit represented by 8.64e15 milliseconds is 100 million days either
|
||||
* side of 00:00 January 1, 1970 UTC.
|
||||
*
|
||||
* Dates in the above set are represented by the |ClippedTime| class. The
|
||||
* double type is a superset of the above set, so it *may* (but need not)
|
||||
* represent a date. Use ECMAScript's |TimeClip| method to produce a date from
|
||||
* a double.
|
||||
*
|
||||
* Date *objects* are simply wrappers around |TimeClip|'d numbers, with a bunch
|
||||
* of accessor methods to the various aspects of the represented date.
|
||||
*/
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/Conversions.h"
|
||||
#include "js/Value.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace JS {
|
||||
|
||||
class ClippedTime;
|
||||
inline ClippedTime TimeClip(double time);
|
||||
|
||||
/*
|
||||
* |ClippedTime| represents the limited subset of dates/times described above.
|
||||
*
|
||||
* An invalid date/time may be created through the |ClippedTime::invalid|
|
||||
* method. Otherwise, a |ClippedTime| may be created using the |TimeClip|
|
||||
* method.
|
||||
*
|
||||
* In typical use, the user might wish to manipulate a timestamp. The user
|
||||
* performs a series of operations on it, but the final value might not be a
|
||||
* date as defined above -- it could have overflowed, acquired a fractional
|
||||
* component, &c. So as a *final* step, the user passes that value through
|
||||
* |TimeClip| to produce a number restricted to JavaScript's date range.
|
||||
*
|
||||
* APIs that accept a JavaScript date value thus accept a |ClippedTime|, not a
|
||||
* double. This ensures that date/time APIs will only ever receive acceptable
|
||||
* JavaScript dates. This also forces users to perform any desired clipping,
|
||||
* as only the user knows what behavior is desired when clipping occurs.
|
||||
*/
|
||||
class ClippedTime
|
||||
{
|
||||
double t;
|
||||
|
||||
/* ES5 15.9.1.14. */
|
||||
double timeClip(double time) {
|
||||
/* Steps 1-2. */
|
||||
const double MaxTimeMagnitude = 8.64e15;
|
||||
if (!mozilla::IsFinite(time) || mozilla::Abs(time) > MaxTimeMagnitude)
|
||||
return JS::GenericNaN();
|
||||
|
||||
/* Step 3. */
|
||||
return JS::ToInteger(time) + (+0.0);
|
||||
}
|
||||
explicit ClippedTime(double time) : t(time) {}
|
||||
friend ClippedTime TimeClip(double time);
|
||||
|
||||
public:
|
||||
ClippedTime() : t(JS::GenericNaN()) {}
|
||||
explicit ClippedTime(double time) : t(timeClip(time)) {}
|
||||
// Create an invalid date.
|
||||
ClippedTime() : t(mozilla::UnspecifiedNaN<double>()) {}
|
||||
|
||||
static ClippedTime NaN() { return ClippedTime(); }
|
||||
// Create an invalid date/time, more explicitly; prefer this to the default
|
||||
// constructor.
|
||||
static ClippedTime invalid() { return ClippedTime(); }
|
||||
|
||||
double value() const { return t; }
|
||||
double toDouble() const { return t; }
|
||||
|
||||
bool isValid() const { return !mozilla::IsNaN(t); }
|
||||
};
|
||||
|
||||
// ES6 20.3.1.15.
|
||||
//
|
||||
// Clip a double to JavaScript's date range (or to an invalid date) using the
|
||||
// ECMAScript TimeClip algorithm.
|
||||
inline ClippedTime
|
||||
TimeClip(double d)
|
||||
TimeClip(double time)
|
||||
{
|
||||
return ClippedTime(d);
|
||||
// Steps 1-2.
|
||||
const double MaxTimeMagnitude = 8.64e15;
|
||||
if (!mozilla::IsFinite(time) || mozilla::Abs(time) > MaxTimeMagnitude)
|
||||
return ClippedTime(mozilla::UnspecifiedNaN<double>());
|
||||
|
||||
// Step 3.
|
||||
return ClippedTime(ToInteger(time) + (+0.0));
|
||||
}
|
||||
|
||||
// Year is a year, month is 0-11, day is 1-based. The return value is
|
||||
// a number of milliseconds since the epoch. Can return NaN.
|
||||
// Produce a double Value from the given time. Because times may be NaN,
|
||||
// prefer using this to manual canonicalization.
|
||||
inline Value
|
||||
TimeValue(ClippedTime time)
|
||||
{
|
||||
return DoubleValue(JS::CanonicalizeNaN(time.toDouble()));
|
||||
}
|
||||
|
||||
// Create a new Date object whose [[DateValue]] internal slot contains the
|
||||
// clipped |time|. (Users who must represent times outside that range must use
|
||||
// another representation.)
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
NewDateObject(JSContext* cx, ClippedTime time);
|
||||
|
||||
// Year is a year, month is 0-11, day is 1-based. The return value is a number
|
||||
// of milliseconds since the epoch.
|
||||
//
|
||||
// Consistent with the MakeDate algorithm defined in ECMAScript, this value is
|
||||
// *not* clipped! Use JS::TimeClip if you need a clipped date.
|
||||
JS_PUBLIC_API(double)
|
||||
MakeDate(double year, unsigned month, unsigned day);
|
||||
|
||||
|
|
|
@ -5500,11 +5500,11 @@ JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min,
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
JS_NewDateObjectMsec(JSContext* cx, double msec)
|
||||
JS::NewDateObject(JSContext* cx, JS::ClippedTime time)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return NewDateObjectMsec(cx, JS::TimeClip(msec));
|
||||
return NewDateObjectMsec(cx, time);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
|
|
@ -4761,9 +4761,6 @@ SetForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue
|
|||
extern JS_PUBLIC_API(JSObject*)
|
||||
JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min, int sec);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
JS_NewDateObjectMsec(JSContext* cx, double msec);
|
||||
|
||||
/*
|
||||
* Infallible predicate to test whether obj is a date object.
|
||||
*/
|
||||
|
|
|
@ -353,7 +353,7 @@ MakeDate(double day, double time)
|
|||
JS_PUBLIC_API(double)
|
||||
JS::MakeDate(double year, unsigned month, unsigned day)
|
||||
{
|
||||
return TimeClip(::MakeDate(MakeDay(year, month, day), 0)).value();
|
||||
return ::MakeDate(MakeDay(year, month, day), 0);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(double)
|
||||
|
@ -640,7 +640,7 @@ date_UTC(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
// Step 16.
|
||||
ClippedTime time = TimeClip(MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)));
|
||||
args.rval().setDouble(time.value());
|
||||
args.rval().set(TimeValue(time));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -878,7 +878,7 @@ ParseISODate(const CharT* s, size_t length, ClippedTime* result, DateTimeInfo* d
|
|||
msec -= tzMul * (tzHour * msPerHour + tzMin * msPerMinute);
|
||||
|
||||
*result = TimeClip(msec);
|
||||
return NumbersAreIdentical(msec, result->value());
|
||||
return NumbersAreIdentical(msec, result->toDouble());
|
||||
|
||||
#undef PEEK
|
||||
#undef NEED
|
||||
|
@ -1193,21 +1193,21 @@ date_parse(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
args.rval().setDouble(result.value());
|
||||
args.rval().set(TimeValue(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
static ClippedTime
|
||||
NowAsMillis()
|
||||
{
|
||||
return ClippedTime(static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_MSEC);
|
||||
return TimeClip(static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
bool
|
||||
js::date_now(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setDouble(NowAsMillis().value());
|
||||
args.rval().set(TimeValue(NowAsMillis()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1217,14 +1217,14 @@ DateObject::setUTCTime(ClippedTime t)
|
|||
for (size_t ind = COMPONENTS_START_SLOT; ind < RESERVED_SLOTS; ind++)
|
||||
setReservedSlot(ind, UndefinedValue());
|
||||
|
||||
setFixedSlot(UTC_TIME_SLOT, DoubleValue(t.value()));
|
||||
setFixedSlot(UTC_TIME_SLOT, TimeValue(t));
|
||||
}
|
||||
|
||||
void
|
||||
DateObject::setUTCTime(ClippedTime t, MutableHandleValue vp)
|
||||
{
|
||||
setUTCTime(t);
|
||||
vp.setDouble(t.value());
|
||||
vp.set(TimeValue(t));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1687,7 +1687,7 @@ date_setTime_impl(JSContext* cx, CallArgs args)
|
|||
{
|
||||
Rooted<DateObject*> dateObj(cx, &args.thisv().toObject().as<DateObject>());
|
||||
if (args.length() == 0) {
|
||||
dateObj->setUTCTime(ClippedTime::NaN(), args.rval());
|
||||
dateObj->setUTCTime(ClippedTime::invalid(), args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2322,7 +2322,7 @@ date_setYear_impl(JSContext* cx, CallArgs args)
|
|||
|
||||
/* Step 3. */
|
||||
if (IsNaN(y)) {
|
||||
dateObj->setUTCTime(ClippedTime::NaN(), args.rval());
|
||||
dateObj->setUTCTime(ClippedTime::invalid(), args.rval());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2366,7 +2366,7 @@ static const char * const months[] =
|
|||
static void
|
||||
print_gmt_string(char* buf, size_t size, double utctime)
|
||||
{
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(utctime).value(), utctime));
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(utctime).toDouble(), utctime));
|
||||
JS_snprintf(buf, size, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
|
||||
days[int(WeekDay(utctime))],
|
||||
int(DateFromTime(utctime)),
|
||||
|
@ -2380,7 +2380,7 @@ print_gmt_string(char* buf, size_t size, double utctime)
|
|||
static void
|
||||
print_iso_string(char* buf, size_t size, double utctime)
|
||||
{
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(utctime).value(), utctime));
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(utctime).toDouble(), utctime));
|
||||
JS_snprintf(buf, size, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ",
|
||||
int(YearFromTime(utctime)),
|
||||
int(MonthFromTime(utctime)) + 1,
|
||||
|
@ -2394,7 +2394,7 @@ print_iso_string(char* buf, size_t size, double utctime)
|
|||
static void
|
||||
print_iso_extended_string(char* buf, size_t size, double utctime)
|
||||
{
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(utctime).value(), utctime));
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(utctime).toDouble(), utctime));
|
||||
JS_snprintf(buf, size, "%+.6d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ",
|
||||
int(YearFromTime(utctime)),
|
||||
int(MonthFromTime(utctime)) + 1,
|
||||
|
@ -2550,7 +2550,7 @@ date_format(JSContext* cx, double date, formatspec format, MutableHandleValue rv
|
|||
if (!IsFinite(date)) {
|
||||
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
|
||||
} else {
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(date).value(), date));
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(date).toDouble(), date));
|
||||
|
||||
double local = LocalTime(date, &cx->runtime()->dateTimeInfo);
|
||||
|
||||
|
@ -2990,7 +2990,7 @@ NewDateObject(JSContext* cx, const CallArgs& args, ClippedTime t)
|
|||
static bool
|
||||
ToDateString(JSContext* cx, const CallArgs& args, ClippedTime t)
|
||||
{
|
||||
return date_format(cx, t.value(), FORMATSPEC_FULL, args.rval());
|
||||
return date_format(cx, t.toDouble(), FORMATSPEC_FULL, args.rval());
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -3023,7 +3023,7 @@ DateOneArgument(JSContext* cx, const CallArgs& args)
|
|||
return false;
|
||||
|
||||
if (!ParseDate(linearStr, &t, &cx->runtime()->dateTimeInfo))
|
||||
t = ClippedTime::NaN();
|
||||
t = ClippedTime::invalid();
|
||||
} else {
|
||||
double d;
|
||||
if (!ToNumber(cx, args[0], &d))
|
||||
|
|
|
@ -43,7 +43,14 @@ class DateObject : public NativeObject
|
|||
static const Class class_;
|
||||
static const Class protoClass_;
|
||||
|
||||
inline const js::Value& UTCTime() const {
|
||||
JS::ClippedTime clippedTime() const {
|
||||
double t = getFixedSlot(UTC_TIME_SLOT).toDouble();
|
||||
JS::ClippedTime clipped = JS::TimeClip(t);
|
||||
MOZ_ASSERT(mozilla::NumbersAreIdentical(clipped.toDouble(), t));
|
||||
return clipped;
|
||||
}
|
||||
|
||||
const js::Value& UTCTime() const {
|
||||
return getFixedSlot(UTC_TIME_SLOT);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/WeakSetObject.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "js/Date.h"
|
||||
#include "vm/Compression.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
#include "vm/Interpreter.h"
|
||||
|
@ -1777,7 +1778,7 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
|
|||
MOZ_ASSERT(source->isPermanentAtom());
|
||||
clone = RegExpObject::createNoStatics(cx, source, reobj.getFlags(), nullptr, cx->tempLifoAlloc());
|
||||
} else if (selfHostedObject->is<DateObject>()) {
|
||||
clone = JS_NewDateObjectMsec(cx, selfHostedObject->as<DateObject>().UTCTime().toNumber());
|
||||
clone = JS::NewDateObject(cx, selfHostedObject->as<DateObject>().clippedTime());
|
||||
} else if (selfHostedObject->is<BooleanObject>()) {
|
||||
clone = BooleanObject::create(cx, selfHostedObject->as<BooleanObject>().unbox());
|
||||
} else if (selfHostedObject->is<NumberObject>()) {
|
||||
|
|
|
@ -1592,7 +1592,7 @@ JSStructuredCloneReader::startRead(MutableHandleValue vp)
|
|||
if (!in.readDouble(&d) || !checkDouble(d))
|
||||
return false;
|
||||
JS::ClippedTime t = JS::TimeClip(d);
|
||||
if (!NumbersAreIdentical(d, t.value())) {
|
||||
if (!NumbersAreIdentical(d, t.toDouble())) {
|
||||
JS_ReportErrorNumber(context(), GetErrorMessage, nullptr,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA, "date");
|
||||
return false;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mozilla/Services.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "jsapi.h"
|
||||
#include "js/Date.h"
|
||||
#include "prenv.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
||||
|
@ -780,7 +781,7 @@ nsAppStartup::GetStartupInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aRetva
|
|||
if (stamp >= procTime) {
|
||||
PRTime prStamp = ComputeAbsoluteTimestamp(absNow, now, stamp)
|
||||
/ PR_USEC_PER_MSEC;
|
||||
JS::Rooted<JSObject*> date(aCx, JS_NewDateObjectMsec(aCx, prStamp));
|
||||
JS::Rooted<JSObject*> date(aCx, JS::NewDateObject(aCx, JS::TimeClip(prStamp)));
|
||||
JS_DefineProperty(aCx, obj, StartupTimeline::Describe(ev), date, JSPROP_ENUMERATE);
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::STARTUP_MEASUREMENT_ERRORS, ev);
|
||||
|
|
Загрузка…
Ссылка в новой задаче