mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1834744
- Split up RealmBehaviors::shouldResistFingerprinting in js/src. r=spidermonkey-reviewers,jandem
Differential Revision: https://phabricator.services.mozilla.com/D179534
This commit is contained in:
parent
2b402cbc3b
commit
ca61e81327
@ -153,8 +153,8 @@ class JS_PUBLIC_API TransitiveCompileOptions {
|
||||
// strict-mode.
|
||||
bool forceStrictMode_ = false;
|
||||
|
||||
// The Realm of this script is configured to resist fingerprinting.
|
||||
bool shouldResistFingerprinting_ = false;
|
||||
// The Realm of this script is configured to use fdlibm math library.
|
||||
bool alwaysUseFdlibm_ = false;
|
||||
|
||||
// The context has specified that source pragmas should be parsed.
|
||||
bool sourcePragmas_ = true;
|
||||
@ -268,9 +268,7 @@ class JS_PUBLIC_API TransitiveCompileOptions {
|
||||
// Read-only accessors for non-POD options. The proper way to set these
|
||||
// depends on the derived type.
|
||||
bool mutedErrors() const { return mutedErrors_; }
|
||||
bool shouldResistFingerprinting() const {
|
||||
return shouldResistFingerprinting_;
|
||||
}
|
||||
bool alwaysUseFdlibm() const { return alwaysUseFdlibm_; }
|
||||
bool forceFullParse() const {
|
||||
return eagerDelazificationIsOneOf<
|
||||
DelazificationOption::ParseEverythingEagerly>();
|
||||
@ -315,7 +313,7 @@ class JS_PUBLIC_API TransitiveCompileOptions {
|
||||
PrintFields_(sourceMapURL_);
|
||||
PrintFields_(mutedErrors_);
|
||||
PrintFields_(forceStrictMode_);
|
||||
PrintFields_(shouldResistFingerprinting_);
|
||||
PrintFields_(alwaysUseFdlibm_);
|
||||
PrintFields_(sourcePragmas_);
|
||||
PrintFields_(skipFilenameValidation_);
|
||||
PrintFields_(hideScriptFromDebugger_);
|
||||
|
@ -187,11 +187,9 @@ JS_PUBLIC_API double DayFromYear(double year);
|
||||
JS_PUBLIC_API double DayWithinYear(double time, double year);
|
||||
|
||||
// The callback will be a wrapper function that accepts a double (the time
|
||||
// to clamp and jitter) as well as a bool indicating if we should be resisting
|
||||
// fingerprinting. Inside the JS Engine, other parameters that may be
|
||||
// to clamp and jitter). Inside the JS Engine, other parameters that may be
|
||||
// needed are all constant, so they are handled inside the wrapper function
|
||||
using ReduceMicrosecondTimePrecisionCallback = double (*)(double, bool,
|
||||
JSContext*);
|
||||
using ReduceMicrosecondTimePrecisionCallback = double (*)(double, JSContext*);
|
||||
|
||||
// Set a callback into the toolkit/components/resistfingerprinting function that
|
||||
// will centralize time resolution and jitter into one place.
|
||||
|
@ -259,6 +259,23 @@ class JS_PUBLIC_API RealmCreationOptions {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Force all date/time methods in JavaScript to use the UTC timezone for
|
||||
// fingerprinting protection.
|
||||
bool forceUTC() const { return forceUTC_; }
|
||||
RealmCreationOptions& setForceUTC(bool flag) {
|
||||
forceUTC_ = flag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Always use the fdlibm implementation of math functions instead of the
|
||||
// platform native libc implementations. Useful for fingerprinting protection
|
||||
// and cross-platform consistency.
|
||||
bool alwaysUseFdlibm() const { return alwaysUseFdlibm_; }
|
||||
RealmCreationOptions& setAlwaysUseFdlibm(bool flag) {
|
||||
alwaysUseFdlibm_ = flag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint64_t profilerRealmID() const { return profilerRealmID_; }
|
||||
RealmCreationOptions& setProfilerRealmID(uint64_t id) {
|
||||
profilerRealmID_ = id;
|
||||
@ -295,6 +312,8 @@ class JS_PUBLIC_API RealmCreationOptions {
|
||||
#endif
|
||||
bool secureContext_ = false;
|
||||
bool freezeBuiltins_ = false;
|
||||
bool forceUTC_ = false;
|
||||
bool alwaysUseFdlibm_ = false;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -319,14 +338,6 @@ class JS_PUBLIC_API RealmBehaviors {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool shouldResistFingerprinting() const {
|
||||
return shouldResistFingerprinting_;
|
||||
}
|
||||
RealmBehaviors& setShouldResistFingerprinting(bool flag) {
|
||||
shouldResistFingerprinting_ = flag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
class Override {
|
||||
public:
|
||||
Override() : mode_(Default) {}
|
||||
@ -362,7 +373,6 @@ class JS_PUBLIC_API RealmBehaviors {
|
||||
private:
|
||||
bool discardSource_ = false;
|
||||
bool clampAndJitterTime_ = true;
|
||||
bool shouldResistFingerprinting_ = false;
|
||||
bool isNonLive_ = false;
|
||||
};
|
||||
|
||||
|
@ -8360,7 +8360,7 @@ static bool GetICUOptions(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
intl::FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> buf(cx);
|
||||
|
||||
if (auto ok = DateTimeInfo::timeZoneId(DateTimeInfo::ShouldRFP::No, buf);
|
||||
if (auto ok = DateTimeInfo::timeZoneId(DateTimeInfo::ForceUTC::No, buf);
|
||||
ok.isErr()) {
|
||||
intl::ReportInternalError(cx, ok.unwrapErr());
|
||||
return false;
|
||||
|
@ -404,7 +404,7 @@ bool js::intl_defaultTimeZone(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> timeZone(cx);
|
||||
auto result =
|
||||
DateTimeInfo::timeZoneId(DateTimeInfo::shouldRFP(cx->realm()), timeZone);
|
||||
DateTimeInfo::timeZoneId(DateTimeInfo::forceUTC(cx->realm()), timeZone);
|
||||
if (result.isErr()) {
|
||||
intl::ReportInternalError(cx, result.unwrapErr());
|
||||
return false;
|
||||
@ -424,7 +424,7 @@ bool js::intl_defaultTimeZoneOffset(JSContext* cx, unsigned argc, Value* vp) {
|
||||
MOZ_ASSERT(args.length() == 0);
|
||||
|
||||
auto offset =
|
||||
DateTimeInfo::getRawOffsetMs(DateTimeInfo::shouldRFP(cx->realm()));
|
||||
DateTimeInfo::getRawOffsetMs(DateTimeInfo::forceUTC(cx->realm()));
|
||||
if (offset.isErr()) {
|
||||
intl::ReportInternalError(cx, offset.unwrapErr());
|
||||
return false;
|
||||
@ -448,7 +448,7 @@ bool js::intl_isDefaultTimeZone(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> chars(cx);
|
||||
auto result =
|
||||
DateTimeInfo::timeZoneId(DateTimeInfo::shouldRFP(cx->realm()), chars);
|
||||
DateTimeInfo::timeZoneId(DateTimeInfo::forceUTC(cx->realm()), chars);
|
||||
if (result.isErr()) {
|
||||
intl::ReportInternalError(cx, result.unwrapErr());
|
||||
return false;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
load(libdir + "asm.js");
|
||||
|
||||
var g = newGlobal({shouldResistFingerprinting: true})
|
||||
var g = newGlobal({alwaysUseFdlibm: true})
|
||||
|
||||
var code = (fun) => {
|
||||
return `(function asm(glob) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
let g = newGlobal({shouldResistFingerprinting: true});
|
||||
let g = newGlobal({alwaysUseFdlibm: true});
|
||||
|
||||
// Adapted from https://github.com/arkenfox/TZP/blob/master/tests/math.html
|
||||
// Tests all values that differed from libm for me on Linux and Windows.
|
||||
|
@ -13,7 +13,7 @@ let originalDT = Intl.DateTimeFormat("en-US", {
|
||||
assertEq(originalDT.format(original).endsWith("Pacific Standard Time"), true);
|
||||
assertEq(originalDT.resolvedOptions().timeZone, "PST8PDT");
|
||||
|
||||
let global = newGlobal({shouldResistFingerprinting: true});
|
||||
let global = newGlobal({forceUTC: true});
|
||||
|
||||
let date = new global.Date();
|
||||
assertEq(tzRE.exec(date.toString())[1], "Coordinated Universal Time");
|
||||
|
@ -7975,7 +7975,7 @@ AttachDecision InlinableNativeIRGenerator::tryAttachMathFunction(
|
||||
}
|
||||
|
||||
if (math_use_fdlibm_for_sin_cos_tan() ||
|
||||
callee_->realm()->behaviors().shouldResistFingerprinting()) {
|
||||
callee_->realm()->creationOptions().alwaysUseFdlibm()) {
|
||||
switch (fun) {
|
||||
case UnaryMathFunction::SinNative:
|
||||
fun = UnaryMathFunction::SinFdlibm;
|
||||
|
@ -2301,7 +2301,7 @@ void JS::TransitiveCompileOptions::copyPODTransitiveOptions(
|
||||
|
||||
mutedErrors_ = rhs.mutedErrors_;
|
||||
forceStrictMode_ = rhs.forceStrictMode_;
|
||||
shouldResistFingerprinting_ = rhs.shouldResistFingerprinting_;
|
||||
alwaysUseFdlibm_ = rhs.alwaysUseFdlibm_;
|
||||
sourcePragmas_ = rhs.sourcePragmas_;
|
||||
skipFilenameValidation_ = rhs.skipFilenameValidation_;
|
||||
hideScriptFromDebugger_ = rhs.hideScriptFromDebugger_;
|
||||
@ -2427,8 +2427,7 @@ JS::CompileOptions::CompileOptions(JSContext* cx) : ReadOnlyCompileOptions() {
|
||||
// Note: If we parse outside of a specific realm, we do not inherit any realm
|
||||
// behaviours. These can still be set manually on the options though.
|
||||
if (Realm* realm = cx->realm()) {
|
||||
shouldResistFingerprinting_ =
|
||||
realm->behaviors().shouldResistFingerprinting();
|
||||
alwaysUseFdlibm_ = realm->creationOptions().alwaysUseFdlibm();
|
||||
discardSource = realm->behaviors().discardSource();
|
||||
}
|
||||
}
|
||||
|
@ -138,25 +138,25 @@ namespace {
|
||||
class DateTimeHelper {
|
||||
private:
|
||||
#if JS_HAS_INTL_API
|
||||
static double localTZA(DateTimeInfo::ShouldRFP shouldRFP, double t,
|
||||
static double localTZA(DateTimeInfo::ForceUTC forceUTC, double t,
|
||||
DateTimeInfo::TimeZoneOffset offset);
|
||||
#else
|
||||
static int equivalentYearForDST(int year);
|
||||
static bool isRepresentableAsTime32(double t);
|
||||
static double daylightSavingTA(DateTimeInfo::ShouldRFP shouldRFP, double t);
|
||||
static double adjustTime(DateTimeInfo::ShouldRFP shouldRFP, double date);
|
||||
static PRMJTime toPRMJTime(DateTimeInfo::ShouldRFP shouldRFP,
|
||||
double localTime, double utcTime);
|
||||
static double daylightSavingTA(DateTimeInfo::ForceUTC forceUTC, double t);
|
||||
static double adjustTime(DateTimeInfo::ForceUTC forceUTC, double date);
|
||||
static PRMJTime toPRMJTime(DateTimeInfo::ForceUTC forceUTC, double localTime,
|
||||
double utcTime);
|
||||
#endif
|
||||
|
||||
public:
|
||||
static double localTime(DateTimeInfo::ShouldRFP shouldRFP, double t);
|
||||
static double UTC(DateTimeInfo::ShouldRFP shouldRFP, double t);
|
||||
static double localTime(DateTimeInfo::ForceUTC forceUTC, double t);
|
||||
static double UTC(DateTimeInfo::ForceUTC forceUTC, double t);
|
||||
static JSString* timeZoneComment(JSContext* cx,
|
||||
DateTimeInfo::ShouldRFP shouldRFP,
|
||||
DateTimeInfo::ForceUTC forceUTC,
|
||||
double utcTime, double localTime);
|
||||
#if !JS_HAS_INTL_API
|
||||
static size_t formatTime(DateTimeInfo::ShouldRFP shouldRFP, char* buf,
|
||||
static size_t formatTime(DateTimeInfo::ForceUTC forceUTC, char* buf,
|
||||
size_t buflen, const char* fmt, double utcTime,
|
||||
double localTime);
|
||||
#endif
|
||||
@ -164,10 +164,9 @@ class DateTimeHelper {
|
||||
|
||||
} // namespace
|
||||
|
||||
static DateTimeInfo::ShouldRFP ShouldRFP(const Realm* realm) {
|
||||
return realm->behaviors().shouldResistFingerprinting()
|
||||
? DateTimeInfo::ShouldRFP::Yes
|
||||
: DateTimeInfo::ShouldRFP::No;
|
||||
static DateTimeInfo::ForceUTC ForceUTC(const Realm* realm) {
|
||||
return realm->creationOptions().forceUTC() ? DateTimeInfo::ForceUTC::Yes
|
||||
: DateTimeInfo::ForceUTC::No;
|
||||
}
|
||||
|
||||
// ES2019 draft rev 0ceb728a1adbffe42b26972a6541fd7f398b1557
|
||||
@ -460,30 +459,30 @@ JS_PUBLIC_API void JS::SetTimeResolutionUsec(uint32_t resolution, bool jitter) {
|
||||
#if JS_HAS_INTL_API
|
||||
// ES2019 draft rev 0ceb728a1adbffe42b26972a6541fd7f398b1557
|
||||
// 20.3.1.7 LocalTZA ( t, isUTC )
|
||||
double DateTimeHelper::localTZA(DateTimeInfo::ShouldRFP shouldRFP, double t,
|
||||
double DateTimeHelper::localTZA(DateTimeInfo::ForceUTC forceUTC, double t,
|
||||
DateTimeInfo::TimeZoneOffset offset) {
|
||||
MOZ_ASSERT(std::isfinite(t));
|
||||
|
||||
int64_t milliseconds = static_cast<int64_t>(t);
|
||||
int32_t offsetMilliseconds =
|
||||
DateTimeInfo::getOffsetMilliseconds(shouldRFP, milliseconds, offset);
|
||||
DateTimeInfo::getOffsetMilliseconds(forceUTC, milliseconds, offset);
|
||||
return static_cast<double>(offsetMilliseconds);
|
||||
}
|
||||
|
||||
// ES2019 draft rev 0ceb728a1adbffe42b26972a6541fd7f398b1557
|
||||
// 20.3.1.8 LocalTime ( t )
|
||||
double DateTimeHelper::localTime(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
double DateTimeHelper::localTime(DateTimeInfo::ForceUTC forceUTC, double t) {
|
||||
if (!std::isfinite(t)) {
|
||||
return GenericNaN();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(StartOfTime <= t && t <= EndOfTime);
|
||||
return t + localTZA(shouldRFP, t, DateTimeInfo::TimeZoneOffset::UTC);
|
||||
return t + localTZA(forceUTC, t, DateTimeInfo::TimeZoneOffset::UTC);
|
||||
}
|
||||
|
||||
// ES2019 draft rev 0ceb728a1adbffe42b26972a6541fd7f398b1557
|
||||
// 20.3.1.9 UTC ( t )
|
||||
double DateTimeHelper::UTC(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
double DateTimeHelper::UTC(DateTimeInfo::ForceUTC forceUTC, double t) {
|
||||
if (!std::isfinite(t)) {
|
||||
return GenericNaN();
|
||||
}
|
||||
@ -492,7 +491,7 @@ double DateTimeHelper::UTC(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
return GenericNaN();
|
||||
}
|
||||
|
||||
return t - localTZA(shouldRFP, t, DateTimeInfo::TimeZoneOffset::Local);
|
||||
return t - localTZA(forceUTC, t, DateTimeInfo::TimeZoneOffset::Local);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
@ -539,7 +538,7 @@ bool DateTimeHelper::isRepresentableAsTime32(double t) {
|
||||
}
|
||||
|
||||
/* ES5 15.9.1.8. */
|
||||
double DateTimeHelper::daylightSavingTA(DateTimeInfo::ShouldRFP shouldRFP,
|
||||
double DateTimeHelper::daylightSavingTA(DateTimeInfo::ForceUTC forceUTC,
|
||||
double t) {
|
||||
if (!std::isfinite(t)) {
|
||||
return GenericNaN();
|
||||
@ -557,24 +556,24 @@ double DateTimeHelper::daylightSavingTA(DateTimeInfo::ShouldRFP shouldRFP,
|
||||
|
||||
int64_t utcMilliseconds = static_cast<int64_t>(t);
|
||||
int32_t offsetMilliseconds =
|
||||
DateTimeInfo::getDSTOffsetMilliseconds(shouldRFP, utcMilliseconds);
|
||||
DateTimeInfo::getDSTOffsetMilliseconds(forceUTC, utcMilliseconds);
|
||||
return static_cast<double>(offsetMilliseconds);
|
||||
}
|
||||
|
||||
double DateTimeHelper::adjustTime(DateTimeInfo::ShouldRFP shouldRFP,
|
||||
double DateTimeHelper::adjustTime(DateTimeInfo::ForceUTC forceUTC,
|
||||
double date) {
|
||||
double localTZA = DateTimeInfo::localTZA(shouldRFP);
|
||||
double t = daylightSavingTA(shouldRFP, date) + localTZA;
|
||||
double localTZA = DateTimeInfo::localTZA(forceUTC);
|
||||
double t = daylightSavingTA(forceUTC, date) + localTZA;
|
||||
t = (localTZA >= 0) ? fmod(t, msPerDay) : -fmod(msPerDay - t, msPerDay);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* ES5 15.9.1.9. */
|
||||
double DateTimeHelper::localTime(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
return t + adjustTime(shouldRFP, t);
|
||||
double DateTimeHelper::localTime(DateTimeInfo::ForceUTC forceUTC, double t) {
|
||||
return t + adjustTime(forceUTC, t);
|
||||
}
|
||||
|
||||
double DateTimeHelper::UTC(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
double DateTimeHelper::UTC(DateTimeInfo::ForceUTC forceUTC, double t) {
|
||||
// Following the ES2017 specification creates undesirable results at DST
|
||||
// transitions. For example when transitioning from PST to PDT,
|
||||
// |new Date(2016,2,13,2,0,0).toTimeString()| returns the string value
|
||||
@ -582,17 +581,17 @@ double DateTimeHelper::UTC(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
// V8 and subtract one hour before computing the offset.
|
||||
// Spec bug: https://bugs.ecmascript.org/show_bug.cgi?id=4007
|
||||
|
||||
return t - adjustTime(shouldRFP,
|
||||
t - DateTimeInfo::localTZA(shouldRFP) - msPerHour);
|
||||
return t -
|
||||
adjustTime(forceUTC, t - DateTimeInfo::localTZA(forceUTC) - msPerHour);
|
||||
}
|
||||
#endif /* JS_HAS_INTL_API */
|
||||
|
||||
static double LocalTime(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
return DateTimeHelper::localTime(shouldRFP, t);
|
||||
static double LocalTime(DateTimeInfo::ForceUTC forceUTC, double t) {
|
||||
return DateTimeHelper::localTime(forceUTC, t);
|
||||
}
|
||||
|
||||
static double UTC(DateTimeInfo::ShouldRFP shouldRFP, double t) {
|
||||
return DateTimeHelper::UTC(shouldRFP, t);
|
||||
static double UTC(DateTimeInfo::ForceUTC forceUTC, double t) {
|
||||
return DateTimeHelper::UTC(forceUTC, t);
|
||||
}
|
||||
|
||||
/* ES5 15.9.1.10. */
|
||||
@ -883,7 +882,7 @@ static int DaysInMonth(int year, int month) {
|
||||
* TZD = time zone designator (Z or +hh:mm or -hh:mm or missing for local)
|
||||
*/
|
||||
template <typename CharT>
|
||||
static bool ParseISOStyleDate(DateTimeInfo::ShouldRFP shouldRFP, const CharT* s,
|
||||
static bool ParseISOStyleDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
||||
size_t length, ClippedTime* result) {
|
||||
size_t i = 0;
|
||||
size_t pre = 0;
|
||||
@ -1033,7 +1032,7 @@ done:
|
||||
MakeTime(hour, min, sec, frac * 1000.0));
|
||||
|
||||
if (isLocalTime) {
|
||||
msec = UTC(shouldRFP, msec);
|
||||
msec = UTC(forceUTC, msec);
|
||||
} else {
|
||||
msec -= tzMul * (tzHour * msPerHour + tzMin * msPerMinute);
|
||||
}
|
||||
@ -1224,9 +1223,9 @@ constexpr size_t MinKeywordLength(const CharsAndAction (&keywords)[N]) {
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
static bool ParseDate(DateTimeInfo::ShouldRFP shouldRFP, const CharT* s,
|
||||
static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
||||
size_t length, ClippedTime* result) {
|
||||
if (ParseISOStyleDate(shouldRFP, s, length, result)) {
|
||||
if (ParseISOStyleDate(forceUTC, s, length, result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1619,7 +1618,7 @@ static bool ParseDate(DateTimeInfo::ShouldRFP shouldRFP, const CharT* s,
|
||||
double msec = MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, 0));
|
||||
|
||||
if (tzOffset == -1) { /* no time zone specified, have to use local */
|
||||
msec = UTC(shouldRFP, msec);
|
||||
msec = UTC(forceUTC, msec);
|
||||
} else {
|
||||
msec += tzOffset * msPerMinute;
|
||||
}
|
||||
@ -1628,12 +1627,12 @@ static bool ParseDate(DateTimeInfo::ShouldRFP shouldRFP, const CharT* s,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseDate(DateTimeInfo::ShouldRFP shouldRFP, JSLinearString* s,
|
||||
static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, JSLinearString* s,
|
||||
ClippedTime* result) {
|
||||
AutoCheckCannotGC nogc;
|
||||
return s->hasLatin1Chars()
|
||||
? ParseDate(shouldRFP, s->latin1Chars(nogc), s->length(), result)
|
||||
: ParseDate(shouldRFP, s->twoByteChars(nogc), s->length(), result);
|
||||
? ParseDate(forceUTC, s->latin1Chars(nogc), s->length(), result)
|
||||
: ParseDate(forceUTC, s->twoByteChars(nogc), s->length(), result);
|
||||
}
|
||||
|
||||
static bool date_parse(JSContext* cx, unsigned argc, Value* vp) {
|
||||
@ -1655,7 +1654,7 @@ static bool date_parse(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
ClippedTime result;
|
||||
if (!ParseDate(ShouldRFP(cx->realm()), linearStr, &result)) {
|
||||
if (!ParseDate(ForceUTC(cx->realm()), linearStr, &result)) {
|
||||
args.rval().setNaN();
|
||||
return true;
|
||||
}
|
||||
@ -1671,11 +1670,8 @@ static ClippedTime NowAsMillis(JSContext* cx) {
|
||||
|
||||
double now = PRMJ_Now();
|
||||
bool clampAndJitter = cx->realm()->behaviors().clampAndJitterTime();
|
||||
bool shouldResistFingerprinting =
|
||||
cx->realm()->behaviors().shouldResistFingerprinting();
|
||||
if (clampAndJitter && sReduceMicrosecondTimePrecisionCallback) {
|
||||
now = sReduceMicrosecondTimePrecisionCallback(
|
||||
now, shouldResistFingerprinting, cx);
|
||||
now = sReduceMicrosecondTimePrecisionCallback(now, cx);
|
||||
} else if (clampAndJitter && sResolutionUsec) {
|
||||
double clamped = floor(now / sResolutionUsec) * sResolutionUsec;
|
||||
|
||||
@ -1719,8 +1715,8 @@ bool js::date_now(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
DateTimeInfo::ShouldRFP DateObject::shouldRFP() const {
|
||||
return ShouldRFP(realm());
|
||||
DateTimeInfo::ForceUTC DateObject::forceUTC() const {
|
||||
return ForceUTC(realm());
|
||||
}
|
||||
|
||||
void DateObject::setUTCTime(ClippedTime t) {
|
||||
@ -1738,7 +1734,7 @@ void DateObject::setUTCTime(ClippedTime t, MutableHandleValue vp) {
|
||||
|
||||
void DateObject::fillLocalTimeSlots() {
|
||||
const int32_t utcTZOffset =
|
||||
DateTimeInfo::utcToLocalStandardOffsetSeconds(shouldRFP());
|
||||
DateTimeInfo::utcToLocalStandardOffsetSeconds(forceUTC());
|
||||
|
||||
/* Check if the cache is already populated. */
|
||||
if (!getReservedSlot(LOCAL_TIME_SLOT).isUndefined() &&
|
||||
@ -1758,7 +1754,7 @@ void DateObject::fillLocalTimeSlots() {
|
||||
return;
|
||||
}
|
||||
|
||||
double localTime = LocalTime(shouldRFP(), utcTime);
|
||||
double localTime = LocalTime(forceUTC(), utcTime);
|
||||
|
||||
setReservedSlot(LOCAL_TIME_SLOT, DoubleValue(localTime));
|
||||
|
||||
@ -2261,7 +2257,7 @@ static bool date_setMilliseconds(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!unwrapped) {
|
||||
return false;
|
||||
}
|
||||
double t = LocalTime(unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber());
|
||||
double t = LocalTime(unwrapped->forceUTC(), unwrapped->UTCTime().toNumber());
|
||||
|
||||
// Step 2.
|
||||
double ms;
|
||||
@ -2273,7 +2269,7 @@ static bool date_setMilliseconds(JSContext* cx, unsigned argc, Value* vp) {
|
||||
double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
|
||||
|
||||
// Step 4.
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->shouldRFP(), MakeDate(Day(t), time)));
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->forceUTC(), MakeDate(Day(t), time)));
|
||||
|
||||
// Steps 5-6.
|
||||
unwrapped->setUTCTime(u, args.rval());
|
||||
@ -2320,7 +2316,7 @@ static bool date_setSeconds(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
// Steps 1-2.
|
||||
double t = LocalTime(unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber());
|
||||
double t = LocalTime(unwrapped->forceUTC(), unwrapped->UTCTime().toNumber());
|
||||
|
||||
// Steps 3-4.
|
||||
double s;
|
||||
@ -2339,7 +2335,7 @@ static bool date_setSeconds(JSContext* cx, unsigned argc, Value* vp) {
|
||||
MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
|
||||
|
||||
// Step 8.
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->shouldRFP(), date));
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->forceUTC(), date));
|
||||
|
||||
// Step 9.
|
||||
unwrapped->setUTCTime(u, args.rval());
|
||||
@ -2394,7 +2390,7 @@ static bool date_setMinutes(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
// Steps 1-2.
|
||||
double t = LocalTime(unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber());
|
||||
double t = LocalTime(unwrapped->forceUTC(), unwrapped->UTCTime().toNumber());
|
||||
|
||||
// Steps 3-4.
|
||||
double m;
|
||||
@ -2418,7 +2414,7 @@ static bool date_setMinutes(JSContext* cx, unsigned argc, Value* vp) {
|
||||
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
|
||||
|
||||
// Step 10.
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->shouldRFP(), date));
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->forceUTC(), date));
|
||||
|
||||
// Steps 11-12.
|
||||
unwrapped->setUTCTime(u, args.rval());
|
||||
@ -2478,7 +2474,7 @@ static bool date_setHours(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
// Steps 1-2.
|
||||
double t = LocalTime(unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber());
|
||||
double t = LocalTime(unwrapped->forceUTC(), unwrapped->UTCTime().toNumber());
|
||||
|
||||
// Steps 3-4.
|
||||
double h;
|
||||
@ -2508,7 +2504,7 @@ static bool date_setHours(JSContext* cx, unsigned argc, Value* vp) {
|
||||
double date = MakeDate(Day(t), MakeTime(h, m, s, milli));
|
||||
|
||||
// Step 12.
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->shouldRFP(), date));
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->forceUTC(), date));
|
||||
|
||||
// Steps 13-14.
|
||||
unwrapped->setUTCTime(u, args.rval());
|
||||
@ -2574,7 +2570,7 @@ static bool date_setDate(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
/* Step 1. */
|
||||
double t = LocalTime(unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber());
|
||||
double t = LocalTime(unwrapped->forceUTC(), unwrapped->UTCTime().toNumber());
|
||||
|
||||
/* Step 2. */
|
||||
double date;
|
||||
@ -2587,7 +2583,7 @@ static bool date_setDate(JSContext* cx, unsigned argc, Value* vp) {
|
||||
TimeWithinDay(t));
|
||||
|
||||
/* Step 4. */
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->shouldRFP(), newDate));
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->forceUTC(), newDate));
|
||||
|
||||
/* Steps 5-6. */
|
||||
unwrapped->setUTCTime(u, args.rval());
|
||||
@ -2653,7 +2649,7 @@ static bool date_setMonth(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
/* Step 1. */
|
||||
double t = LocalTime(unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber());
|
||||
double t = LocalTime(unwrapped->forceUTC(), unwrapped->UTCTime().toNumber());
|
||||
|
||||
/* Step 2. */
|
||||
double m;
|
||||
@ -2672,7 +2668,7 @@ static bool date_setMonth(JSContext* cx, unsigned argc, Value* vp) {
|
||||
MakeDate(MakeDay(YearFromTime(t), m, date), TimeWithinDay(t));
|
||||
|
||||
/* Step 5. */
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->shouldRFP(), newDate));
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->forceUTC(), newDate));
|
||||
|
||||
/* Steps 6-7. */
|
||||
unwrapped->setUTCTime(u, args.rval());
|
||||
@ -2716,13 +2712,13 @@ static bool date_setUTCMonth(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static double ThisLocalTimeOrZero(DateTimeInfo::ShouldRFP shouldRFP,
|
||||
static double ThisLocalTimeOrZero(DateTimeInfo::ForceUTC forceUTC,
|
||||
Handle<DateObject*> dateObj) {
|
||||
double t = dateObj->UTCTime().toNumber();
|
||||
if (std::isnan(t)) {
|
||||
return +0;
|
||||
}
|
||||
return LocalTime(shouldRFP, t);
|
||||
return LocalTime(forceUTC, t);
|
||||
}
|
||||
|
||||
static double ThisUTCTimeOrZero(Handle<DateObject*> dateObj) {
|
||||
@ -2741,7 +2737,7 @@ static bool date_setFullYear(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
/* Step 1. */
|
||||
double t = ThisLocalTimeOrZero(unwrapped->shouldRFP(), unwrapped);
|
||||
double t = ThisLocalTimeOrZero(unwrapped->forceUTC(), unwrapped);
|
||||
|
||||
/* Step 2. */
|
||||
double y;
|
||||
@ -2765,7 +2761,7 @@ static bool date_setFullYear(JSContext* cx, unsigned argc, Value* vp) {
|
||||
double newDate = MakeDate(MakeDay(y, m, date), TimeWithinDay(t));
|
||||
|
||||
/* Step 6. */
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->shouldRFP(), newDate));
|
||||
ClippedTime u = TimeClip(UTC(unwrapped->forceUTC(), newDate));
|
||||
|
||||
/* Steps 7-8. */
|
||||
unwrapped->setUTCTime(u, args.rval());
|
||||
@ -2825,7 +2821,7 @@ static bool date_setYear(JSContext* cx, unsigned argc, Value* vp) {
|
||||
}
|
||||
|
||||
/* Step 1. */
|
||||
double t = ThisLocalTimeOrZero(unwrapped->shouldRFP(), unwrapped);
|
||||
double t = ThisLocalTimeOrZero(unwrapped->forceUTC(), unwrapped);
|
||||
|
||||
/* Step 2. */
|
||||
double y;
|
||||
@ -2849,7 +2845,7 @@ static bool date_setYear(JSContext* cx, unsigned argc, Value* vp) {
|
||||
double day = MakeDay(yint, MonthFromTime(t), DateFromTime(t));
|
||||
|
||||
/* Step 6. */
|
||||
double u = UTC(unwrapped->shouldRFP(), MakeDate(day, TimeWithinDay(t)));
|
||||
double u = UTC(unwrapped->forceUTC(), MakeDate(day, TimeWithinDay(t)));
|
||||
|
||||
/* Steps 7-8. */
|
||||
unwrapped->setUTCTime(TimeClip(u), args.rval());
|
||||
@ -2977,7 +2973,7 @@ static bool date_toJSON(JSContext* cx, unsigned argc, Value* vp) {
|
||||
|
||||
#if JS_HAS_INTL_API
|
||||
JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||
DateTimeInfo::ShouldRFP shouldRFP,
|
||||
DateTimeInfo::ForceUTC forceUTC,
|
||||
double utcTime, double localTime) {
|
||||
const char* locale = cx->runtime()->getDefaultLocale();
|
||||
if (!locale) {
|
||||
@ -2996,7 +2992,7 @@ JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||
|
||||
int64_t utcMilliseconds = static_cast<int64_t>(utcTime);
|
||||
if (!DateTimeInfo::timeZoneDisplayName(
|
||||
shouldRFP, timeZoneStart, remainingSpace, utcMilliseconds, locale)) {
|
||||
forceUTC, timeZoneStart, remainingSpace, utcMilliseconds, locale)) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
@ -3014,7 +3010,7 @@ JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||
}
|
||||
#else
|
||||
/* Interface to PRMJTime date struct. */
|
||||
PRMJTime DateTimeHelper::toPRMJTime(DateTimeInfo::ShouldRFP shouldRFP,
|
||||
PRMJTime DateTimeHelper::toPRMJTime(DateTimeInfo::ForceUTC forceUTC,
|
||||
double localTime, double utcTime) {
|
||||
double year = YearFromTime(localTime);
|
||||
|
||||
@ -3028,15 +3024,15 @@ PRMJTime DateTimeHelper::toPRMJTime(DateTimeInfo::ShouldRFP shouldRFP,
|
||||
prtm.tm_wday = int8_t(WeekDay(localTime));
|
||||
prtm.tm_year = year;
|
||||
prtm.tm_yday = int16_t(DayWithinYear(localTime, year));
|
||||
prtm.tm_isdst = (daylightSavingTA(shouldRFP, utcTime) != 0);
|
||||
prtm.tm_isdst = (daylightSavingTA(forceUTC, utcTime) != 0);
|
||||
|
||||
return prtm;
|
||||
}
|
||||
|
||||
size_t DateTimeHelper::formatTime(DateTimeInfo::ShouldRFP shouldRFP, char* buf,
|
||||
size_t DateTimeHelper::formatTime(DateTimeInfo::ForceUTC forceUTC, char* buf,
|
||||
size_t buflen, const char* fmt,
|
||||
double utcTime, double localTime) {
|
||||
PRMJTime prtm = toPRMJTime(shouldRFP, localTime, utcTime);
|
||||
PRMJTime prtm = toPRMJTime(forceUTC, localTime, utcTime);
|
||||
|
||||
// If an equivalent year was used to compute the date/time components, use
|
||||
// the same equivalent year to determine the time zone name and offset in
|
||||
@ -3051,12 +3047,12 @@ size_t DateTimeHelper::formatTime(DateTimeInfo::ShouldRFP shouldRFP, char* buf,
|
||||
}
|
||||
|
||||
JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||
DateTimeInfo::ShouldRFP shouldRFP,
|
||||
DateTimeInfo::ForceUTC forceUTC,
|
||||
double utcTime, double localTime) {
|
||||
char tzbuf[100];
|
||||
|
||||
size_t tzlen =
|
||||
formatTime(shouldRFP, tzbuf, sizeof tzbuf, " (%Z)", utcTime, localTime);
|
||||
formatTime(forceUTC, tzbuf, sizeof tzbuf, " (%Z)", utcTime, localTime);
|
||||
if (tzlen != 0) {
|
||||
// Decide whether to use the resulting time zone string.
|
||||
//
|
||||
@ -3088,7 +3084,7 @@ JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||
|
||||
enum class FormatSpec { DateTime, Date, Time };
|
||||
|
||||
static bool FormatDate(JSContext* cx, DateTimeInfo::ShouldRFP shouldRFP,
|
||||
static bool FormatDate(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
||||
double utcTime, FormatSpec format,
|
||||
MutableHandleValue rval) {
|
||||
if (!std::isfinite(utcTime)) {
|
||||
@ -3098,7 +3094,7 @@ static bool FormatDate(JSContext* cx, DateTimeInfo::ShouldRFP shouldRFP,
|
||||
|
||||
MOZ_ASSERT(NumbersAreIdentical(TimeClip(utcTime).toDouble(), utcTime));
|
||||
|
||||
double localTime = LocalTime(shouldRFP, utcTime);
|
||||
double localTime = LocalTime(forceUTC, utcTime);
|
||||
|
||||
int offset = 0;
|
||||
RootedString timeZoneComment(cx);
|
||||
@ -3126,7 +3122,7 @@ static bool FormatDate(JSContext* cx, DateTimeInfo::ShouldRFP shouldRFP,
|
||||
|
||||
// Get a time zone string from the OS or ICU to include as a comment.
|
||||
timeZoneComment =
|
||||
DateTimeHelper::timeZoneComment(cx, shouldRFP, utcTime, localTime);
|
||||
DateTimeHelper::timeZoneComment(cx, forceUTC, utcTime, localTime);
|
||||
if (!timeZoneComment) {
|
||||
return false;
|
||||
}
|
||||
@ -3176,23 +3172,22 @@ static bool FormatDate(JSContext* cx, DateTimeInfo::ShouldRFP shouldRFP,
|
||||
}
|
||||
|
||||
#if !JS_HAS_INTL_API
|
||||
static bool ToLocaleFormatHelper(JSContext* cx,
|
||||
DateTimeInfo::ShouldRFP shouldRFP,
|
||||
static bool ToLocaleFormatHelper(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
||||
double utcTime, const char* format,
|
||||
MutableHandleValue rval) {
|
||||
char buf[100];
|
||||
if (!std::isfinite(utcTime)) {
|
||||
strcpy(buf, js_InvalidDate_str);
|
||||
} else {
|
||||
double localTime = LocalTime(shouldRFP, utcTime);
|
||||
double localTime = LocalTime(forceUTC, utcTime);
|
||||
|
||||
/* Let PRMJTime format it. */
|
||||
size_t result_len = DateTimeHelper::formatTime(shouldRFP, buf, sizeof buf,
|
||||
size_t result_len = DateTimeHelper::formatTime(forceUTC, buf, sizeof buf,
|
||||
format, utcTime, localTime);
|
||||
|
||||
/* If it failed, default to toString. */
|
||||
if (result_len == 0) {
|
||||
return FormatDate(cx, shouldRFP, utcTime, FormatSpec::DateTime, rval);
|
||||
return FormatDate(cx, forceUTC, utcTime, FormatSpec::DateTime, rval);
|
||||
}
|
||||
|
||||
/* Hacked check against undesired 2-digit year 00/00/00 form. */
|
||||
@ -3247,7 +3242,7 @@ static bool date_toLocaleString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
# endif
|
||||
;
|
||||
|
||||
return ToLocaleFormatHelper(cx, unwrapped->shouldRFP(),
|
||||
return ToLocaleFormatHelper(cx, unwrapped->forceUTC(),
|
||||
unwrapped->UTCTime().toNumber(), format,
|
||||
args.rval());
|
||||
}
|
||||
@ -3275,7 +3270,7 @@ static bool date_toLocaleDateString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
# endif
|
||||
;
|
||||
|
||||
return ToLocaleFormatHelper(cx, unwrapped->shouldRFP(),
|
||||
return ToLocaleFormatHelper(cx, unwrapped->forceUTC(),
|
||||
unwrapped->UTCTime().toNumber(), format,
|
||||
args.rval());
|
||||
}
|
||||
@ -3291,7 +3286,7 @@ static bool date_toLocaleTimeString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ToLocaleFormatHelper(cx, unwrapped->shouldRFP(),
|
||||
return ToLocaleFormatHelper(cx, unwrapped->forceUTC(),
|
||||
unwrapped->UTCTime().toNumber(), "%X",
|
||||
args.rval());
|
||||
}
|
||||
@ -3307,7 +3302,7 @@ static bool date_toTimeString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return FormatDate(cx, unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber(),
|
||||
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->UTCTime().toNumber(),
|
||||
FormatSpec::Time, args.rval());
|
||||
}
|
||||
|
||||
@ -3321,7 +3316,7 @@ static bool date_toDateString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return FormatDate(cx, unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber(),
|
||||
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->UTCTime().toNumber(),
|
||||
FormatSpec::Date, args.rval());
|
||||
}
|
||||
|
||||
@ -3358,7 +3353,7 @@ bool date_toString(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return FormatDate(cx, unwrapped->shouldRFP(), unwrapped->UTCTime().toNumber(),
|
||||
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->UTCTime().toNumber(),
|
||||
FormatSpec::DateTime, args.rval());
|
||||
}
|
||||
|
||||
@ -3476,7 +3471,7 @@ static bool NewDateObject(JSContext* cx, const CallArgs& args, ClippedTime t) {
|
||||
}
|
||||
|
||||
static bool ToDateString(JSContext* cx, const CallArgs& args, ClippedTime t) {
|
||||
return FormatDate(cx, ShouldRFP(cx->realm()), t.toDouble(),
|
||||
return FormatDate(cx, ForceUTC(cx->realm()), t.toDouble(),
|
||||
FormatSpec::DateTime, args.rval());
|
||||
}
|
||||
|
||||
@ -3525,7 +3520,7 @@ static bool DateOneArgument(JSContext* cx, const CallArgs& args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ParseDate(ShouldRFP(cx->realm()), linearStr, &t)) {
|
||||
if (!ParseDate(ForceUTC(cx->realm()), linearStr, &t)) {
|
||||
t = ClippedTime::invalid();
|
||||
}
|
||||
} else {
|
||||
@ -3623,7 +3618,7 @@ static bool DateMultipleArguments(JSContext* cx, const CallArgs& args) {
|
||||
|
||||
// Steps 3q-t.
|
||||
return NewDateObject(cx, args,
|
||||
TimeClip(UTC(ShouldRFP(cx->realm()), finalDate)));
|
||||
TimeClip(UTC(ForceUTC(cx->realm()), finalDate)));
|
||||
}
|
||||
|
||||
return ToDateString(cx, args, NowAsMillis(cx));
|
||||
@ -3699,8 +3694,7 @@ JS_PUBLIC_API JSObject* js::NewDateObject(JSContext* cx, int year, int mon,
|
||||
MOZ_ASSERT(mon < 12);
|
||||
double msec_time =
|
||||
MakeDate(MakeDay(year, mon, mday), MakeTime(hour, min, sec, 0.0));
|
||||
return NewDateObjectMsec(cx,
|
||||
TimeClip(UTC(ShouldRFP(cx->realm()), msec_time)));
|
||||
return NewDateObjectMsec(cx, TimeClip(UTC(ForceUTC(cx->realm()), msec_time)));
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool js::DateIsValid(JSContext* cx, HandleObject obj,
|
||||
|
@ -58,7 +58,7 @@ bool js::math_use_fdlibm_for_sin_cos_tan() { return sUseFdlibmForSinCosTan; }
|
||||
|
||||
static inline bool UseFdlibmForSinCosTan(const CallArgs& args) {
|
||||
return sUseFdlibmForSinCosTan ||
|
||||
args.callee().nonCCWRealm()->behaviors().shouldResistFingerprinting();
|
||||
args.callee().nonCCWRealm()->creationOptions().alwaysUseFdlibm();
|
||||
}
|
||||
|
||||
template <UnaryMathFunctionType F>
|
||||
|
@ -6641,11 +6641,18 @@ static bool NewGlobal(JSContext* cx, unsigned argc, Value* vp) {
|
||||
creationOptions.setDefineSharedArrayBufferConstructor(v.toBoolean());
|
||||
}
|
||||
|
||||
if (!JS_GetProperty(cx, opts, "shouldResistFingerprinting", &v)) {
|
||||
if (!JS_GetProperty(cx, opts, "forceUTC", &v)) {
|
||||
return false;
|
||||
}
|
||||
if (v.isBoolean()) {
|
||||
behaviors.setShouldResistFingerprinting(v.toBoolean());
|
||||
creationOptions.setForceUTC(v.toBoolean());
|
||||
}
|
||||
|
||||
if (!JS_GetProperty(cx, opts, "alwaysUseFdlibm", &v)) {
|
||||
return false;
|
||||
}
|
||||
if (v.isBoolean()) {
|
||||
creationOptions.setAlwaysUseFdlibm(v.toBoolean());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class DateObject : public NativeObject {
|
||||
static const JSClass class_;
|
||||
static const JSClass protoClass_;
|
||||
|
||||
js::DateTimeInfo::ShouldRFP shouldRFP() const;
|
||||
js::DateTimeInfo::ForceUTC forceUTC() const;
|
||||
|
||||
JS::ClippedTime clippedTime() const {
|
||||
double t = getFixedSlot(UTC_TIME_SLOT).toDouble();
|
||||
|
@ -38,10 +38,9 @@
|
||||
#include "vm/Realm.h"
|
||||
|
||||
/* static */
|
||||
js::DateTimeInfo::ShouldRFP js::DateTimeInfo::shouldRFP(JS::Realm* realm) {
|
||||
return realm->behaviors().shouldResistFingerprinting()
|
||||
? DateTimeInfo::ShouldRFP::Yes
|
||||
: DateTimeInfo::ShouldRFP::No;
|
||||
js::DateTimeInfo::ForceUTC js::DateTimeInfo::forceUTC(JS::Realm* realm) {
|
||||
return realm->creationOptions().forceUTC() ? DateTimeInfo::ForceUTC::Yes
|
||||
: DateTimeInfo::ForceUTC::No;
|
||||
}
|
||||
|
||||
static bool ComputeLocalTime(time_t local, struct tm* ptm) {
|
||||
@ -233,8 +232,7 @@ void js::DateTimeInfo::updateTimeZone() {
|
||||
}
|
||||
}
|
||||
|
||||
js::DateTimeInfo::DateTimeInfo(bool shouldResistFingerprinting)
|
||||
: shouldResistFingerprinting_(shouldResistFingerprinting) {
|
||||
js::DateTimeInfo::DateTimeInfo(bool forceUTC) : forceUTC_(forceUTC) {
|
||||
// Set the time zone status into the invalid state, so we compute the actual
|
||||
// defaults on first access. We don't yet want to initialize neither <ctime>
|
||||
// nor ICU's time zone classes, because that may cause I/O operations slowing
|
||||
@ -486,7 +484,7 @@ mozilla::intl::TimeZone* js::DateTimeInfo::timeZone() {
|
||||
if (!timeZone_) {
|
||||
// For resist finger printing mode we always use the UTC time zone.
|
||||
mozilla::Maybe<mozilla::Span<const char16_t>> timeZoneOverride;
|
||||
if (shouldResistFingerprinting_) {
|
||||
if (forceUTC_) {
|
||||
timeZoneOverride = mozilla::Some(mozilla::MakeStringSpan(u"UTC"));
|
||||
}
|
||||
|
||||
@ -506,17 +504,17 @@ mozilla::intl::TimeZone* js::DateTimeInfo::timeZone() {
|
||||
#endif /* JS_HAS_INTL_API */
|
||||
|
||||
/* static */ js::ExclusiveData<js::DateTimeInfo>* js::DateTimeInfo::instance;
|
||||
/* static */ js::ExclusiveData<js::DateTimeInfo>* js::DateTimeInfo::instanceRFP;
|
||||
/* static */ js::ExclusiveData<js::DateTimeInfo>* js::DateTimeInfo::instanceUTC;
|
||||
|
||||
bool js::InitDateTimeState() {
|
||||
MOZ_ASSERT(!DateTimeInfo::instance && !DateTimeInfo::instanceRFP,
|
||||
MOZ_ASSERT(!DateTimeInfo::instance && !DateTimeInfo::instanceUTC,
|
||||
"we should be initializing only once");
|
||||
|
||||
DateTimeInfo::instance =
|
||||
js_new<ExclusiveData<DateTimeInfo>>(mutexid::DateTimeInfoMutex, false);
|
||||
DateTimeInfo::instanceRFP =
|
||||
DateTimeInfo::instanceUTC =
|
||||
js_new<ExclusiveData<DateTimeInfo>>(mutexid::DateTimeInfoMutex, true);
|
||||
return DateTimeInfo::instance && DateTimeInfo::instanceRFP;
|
||||
return DateTimeInfo::instance && DateTimeInfo::instanceUTC;
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -755,7 +753,7 @@ void js::DateTimeInfo::internalResyncICUDefaultTimeZone() {
|
||||
// instance depending on the resist fingerprinting status. For now we return
|
||||
// early to prevent overwriting the default time zone with the UTC time zone
|
||||
// used by RFP.
|
||||
if (shouldResistFingerprinting_) {
|
||||
if (forceUTC_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -113,25 +113,25 @@ extern void ResetTimeZoneInternal(ResetTimeZoneMode mode);
|
||||
*/
|
||||
class DateTimeInfo {
|
||||
public:
|
||||
// Whether we should resist fingerprinting. For realms in RFP mode a separate
|
||||
// DateTimeInfo instance is used that is always in the UTC time zone.
|
||||
enum class ShouldRFP { No, Yes };
|
||||
// For realms that force the UTC time zone (for fingerprinting protection) a
|
||||
// separate DateTimeInfo instance is used that is always in the UTC time zone.
|
||||
enum class ForceUTC { No, Yes };
|
||||
|
||||
private:
|
||||
static ExclusiveData<DateTimeInfo>* instance;
|
||||
static ExclusiveData<DateTimeInfo>* instanceRFP;
|
||||
static ExclusiveData<DateTimeInfo>* instanceUTC;
|
||||
|
||||
friend class ExclusiveData<DateTimeInfo>;
|
||||
|
||||
friend bool InitDateTimeState();
|
||||
friend void FinishDateTimeState();
|
||||
|
||||
explicit DateTimeInfo(bool shouldResistFingerprinting);
|
||||
explicit DateTimeInfo(bool forceUTC);
|
||||
~DateTimeInfo();
|
||||
|
||||
static auto acquireLockWithValidTimeZone(ShouldRFP shouldRFP) {
|
||||
static auto acquireLockWithValidTimeZone(ForceUTC forceUTC) {
|
||||
auto guard =
|
||||
shouldRFP == ShouldRFP::Yes ? instanceRFP->lock() : instance->lock();
|
||||
forceUTC == ForceUTC::Yes ? instanceUTC->lock() : instance->lock();
|
||||
if (guard->timeZoneStatus_ != TimeZoneStatus::Valid) {
|
||||
guard->updateTimeZone();
|
||||
}
|
||||
@ -139,7 +139,7 @@ class DateTimeInfo {
|
||||
}
|
||||
|
||||
public:
|
||||
static ShouldRFP shouldRFP(JS::Realm* realm);
|
||||
static ForceUTC forceUTC(JS::Realm* realm);
|
||||
|
||||
// The spec implicitly assumes DST and time zone adjustment information
|
||||
// never change in the course of a function -- sometimes even across
|
||||
@ -151,9 +151,9 @@ class DateTimeInfo {
|
||||
* zone (Lord Howe Island, Australia) has a fractional-hour offset, just to
|
||||
* keep things interesting.
|
||||
*/
|
||||
static int32_t getDSTOffsetMilliseconds(ShouldRFP shouldRFP,
|
||||
static int32_t getDSTOffsetMilliseconds(ForceUTC forceUTC,
|
||||
int64_t utcMilliseconds) {
|
||||
auto guard = acquireLockWithValidTimeZone(shouldRFP);
|
||||
auto guard = acquireLockWithValidTimeZone(forceUTC);
|
||||
return guard->internalGetDSTOffsetMilliseconds(utcMilliseconds);
|
||||
}
|
||||
|
||||
@ -162,8 +162,8 @@ class DateTimeInfo {
|
||||
* standard time (i.e. not including any offset due to DST) as computed by the
|
||||
* operating system.
|
||||
*/
|
||||
static int32_t utcToLocalStandardOffsetSeconds(ShouldRFP shouldRFP) {
|
||||
auto guard = acquireLockWithValidTimeZone(shouldRFP);
|
||||
static int32_t utcToLocalStandardOffsetSeconds(ForceUTC forceUTC) {
|
||||
auto guard = acquireLockWithValidTimeZone(forceUTC);
|
||||
return guard->utcToLocalStandardOffsetSeconds_;
|
||||
}
|
||||
|
||||
@ -174,10 +174,9 @@ class DateTimeInfo {
|
||||
* Return the time zone offset, including DST, in milliseconds at the
|
||||
* given time. The input time can be either at UTC or at local time.
|
||||
*/
|
||||
static int32_t getOffsetMilliseconds(ShouldRFP shouldRFP,
|
||||
int64_t milliseconds,
|
||||
static int32_t getOffsetMilliseconds(ForceUTC forceUTC, int64_t milliseconds,
|
||||
TimeZoneOffset offset) {
|
||||
auto guard = acquireLockWithValidTimeZone(shouldRFP);
|
||||
auto guard = acquireLockWithValidTimeZone(forceUTC);
|
||||
return guard->internalGetOffsetMilliseconds(milliseconds, offset);
|
||||
}
|
||||
|
||||
@ -187,10 +186,10 @@ class DateTimeInfo {
|
||||
* buffer is too small, an empty string is stored. The stored display name
|
||||
* is null-terminated in any case.
|
||||
*/
|
||||
static bool timeZoneDisplayName(ShouldRFP shouldRFP, char16_t* buf,
|
||||
static bool timeZoneDisplayName(ForceUTC forceUTC, char16_t* buf,
|
||||
size_t buflen, int64_t utcMilliseconds,
|
||||
const char* locale) {
|
||||
auto guard = acquireLockWithValidTimeZone(shouldRFP);
|
||||
auto guard = acquireLockWithValidTimeZone(forceUTC);
|
||||
return guard->internalTimeZoneDisplayName(buf, buflen, utcMilliseconds,
|
||||
locale);
|
||||
}
|
||||
@ -200,8 +199,8 @@ class DateTimeInfo {
|
||||
* buffer.
|
||||
*/
|
||||
template <typename B>
|
||||
static mozilla::intl::ICUResult timeZoneId(ShouldRFP shouldRFP, B& buffer) {
|
||||
auto guard = acquireLockWithValidTimeZone(shouldRFP);
|
||||
static mozilla::intl::ICUResult timeZoneId(ForceUTC forceUTC, B& buffer) {
|
||||
auto guard = acquireLockWithValidTimeZone(forceUTC);
|
||||
return guard->timeZone()->GetId(buffer);
|
||||
}
|
||||
|
||||
@ -209,8 +208,8 @@ class DateTimeInfo {
|
||||
* A number indicating the raw offset from GMT in milliseconds.
|
||||
*/
|
||||
static mozilla::Result<int32_t, mozilla::intl::ICUError> getRawOffsetMs(
|
||||
ShouldRFP shouldRFP) {
|
||||
auto guard = acquireLockWithValidTimeZone(shouldRFP);
|
||||
ForceUTC forceUTC) {
|
||||
auto guard = acquireLockWithValidTimeZone(forceUTC);
|
||||
return guard->timeZone()->GetRawOffsetMs();
|
||||
}
|
||||
#else
|
||||
@ -218,8 +217,8 @@ class DateTimeInfo {
|
||||
* Return the local time zone adjustment (ES2019 20.3.1.7) as computed by
|
||||
* the operating system.
|
||||
*/
|
||||
static int32_t localTZA(ShouldRFP shouldRFP) {
|
||||
return utcToLocalStandardOffsetSeconds(shouldRFP) * msPerSecond;
|
||||
static int32_t localTZA(ForceUTC forceUTC) {
|
||||
return utcToLocalStandardOffsetSeconds(forceUTC) * msPerSecond;
|
||||
}
|
||||
#endif /* JS_HAS_INTL_API */
|
||||
|
||||
@ -235,7 +234,7 @@ class DateTimeInfo {
|
||||
{
|
||||
// Only needed to initialize the default state and any later call will
|
||||
// perform an unnecessary reset.
|
||||
auto guard = instanceRFP->lock();
|
||||
auto guard = instanceUTC->lock();
|
||||
guard->internalResetTimeZone(mode);
|
||||
}
|
||||
}
|
||||
@ -255,7 +254,7 @@ class DateTimeInfo {
|
||||
void sanityCheck();
|
||||
};
|
||||
|
||||
bool shouldResistFingerprinting_;
|
||||
bool forceUTC_;
|
||||
|
||||
enum class TimeZoneStatus : uint8_t { Valid, NeedsUpdate, UpdateIfChanged };
|
||||
|
||||
|
@ -367,7 +367,7 @@ struct js::AsmJSMetadata : Metadata, AsmJSMetadataCacheablePod {
|
||||
uint32_t toStringStart;
|
||||
uint32_t srcStart;
|
||||
bool strict;
|
||||
bool shouldResistFingerprinting = false;
|
||||
bool alwaysUseFdlibm = false;
|
||||
RefPtr<ScriptSource> source;
|
||||
|
||||
uint32_t srcEndBeforeCurly() const { return srcStart + srcLength; }
|
||||
@ -1988,8 +1988,7 @@ class MOZ_STACK_CLASS ModuleValidator : public ModuleValidatorShared {
|
||||
asmJSMetadata_->srcStart = moduleFunctionNode_->body()->pn_pos.begin;
|
||||
asmJSMetadata_->strict = parser_.pc_->sc()->strict() &&
|
||||
!parser_.pc_->sc()->hasExplicitUseStrict();
|
||||
asmJSMetadata_->shouldResistFingerprinting =
|
||||
parser_.options().shouldResistFingerprinting();
|
||||
asmJSMetadata_->alwaysUseFdlibm = parser_.options().alwaysUseFdlibm();
|
||||
asmJSMetadata_->source = do_AddRef(parser_.ss);
|
||||
|
||||
if (!initModuleEnvironment()) {
|
||||
@ -2002,9 +2001,7 @@ class MOZ_STACK_CLASS ModuleValidator : public ModuleValidatorShared {
|
||||
|
||||
auto& tokenStream() const { return parser_.tokenStream; }
|
||||
|
||||
bool shouldResistFingerprinting() const {
|
||||
return asmJSMetadata_->shouldResistFingerprinting;
|
||||
}
|
||||
bool alwaysUseFdlibm() const { return asmJSMetadata_->alwaysUseFdlibm; }
|
||||
|
||||
public:
|
||||
bool addFuncDef(TaggedParserAtomIndex name, uint32_t firstUse, FuncType&& sig,
|
||||
@ -4359,7 +4356,7 @@ static bool CheckMathBuiltinCall(FunctionValidator<Unit>& f,
|
||||
break;
|
||||
case AsmJSMathBuiltin_sin:
|
||||
arity = 1;
|
||||
if (!f.m().shouldResistFingerprinting()) {
|
||||
if (!f.m().alwaysUseFdlibm()) {
|
||||
mozf64 = MozOp::F64SinNative;
|
||||
} else {
|
||||
mozf64 = MozOp::F64SinFdlibm;
|
||||
@ -4368,7 +4365,7 @@ static bool CheckMathBuiltinCall(FunctionValidator<Unit>& f,
|
||||
break;
|
||||
case AsmJSMathBuiltin_cos:
|
||||
arity = 1;
|
||||
if (!f.m().shouldResistFingerprinting()) {
|
||||
if (!f.m().alwaysUseFdlibm()) {
|
||||
mozf64 = MozOp::F64CosNative;
|
||||
} else {
|
||||
mozf64 = MozOp::F64CosFdlibm;
|
||||
@ -4377,7 +4374,7 @@ static bool CheckMathBuiltinCall(FunctionValidator<Unit>& f,
|
||||
break;
|
||||
case AsmJSMathBuiltin_tan:
|
||||
arity = 1;
|
||||
if (!f.m().shouldResistFingerprinting()) {
|
||||
if (!f.m().alwaysUseFdlibm()) {
|
||||
mozf64 = MozOp::F64TanNative;
|
||||
} else {
|
||||
mozf64 = MozOp::F64TanFdlibm;
|
||||
@ -6756,11 +6753,11 @@ static bool ValidateMathBuiltinFunction(JSContext* cx,
|
||||
fun->jitInfo()->inlinableNative != native) {
|
||||
return LinkFail(cx, "bad Math.* builtin function");
|
||||
}
|
||||
if (fun->realm()->behaviors().shouldResistFingerprinting() !=
|
||||
metadata.shouldResistFingerprinting) {
|
||||
if (fun->realm()->creationOptions().alwaysUseFdlibm() !=
|
||||
metadata.alwaysUseFdlibm) {
|
||||
return LinkFail(cx,
|
||||
"Math.* builtin function and asm.js module have a "
|
||||
"different resist fingerprinting mode");
|
||||
"Math.* builtin function and asm.js use different native"
|
||||
" math implementations.");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1936,11 +1936,11 @@ void* wasm::MaybeGetBuiltinThunk(JSFunction* f, const FuncType& funcType) {
|
||||
|
||||
const BuiltinThunks& thunks = *builtinThunks;
|
||||
|
||||
// If this function should resist fingerprinting first try to lookup
|
||||
// If this function must use the fdlibm implementation first try to lookup
|
||||
// the fdlibm version. If that version doesn't exist we still fallback to
|
||||
// the normal native.
|
||||
if (math_use_fdlibm_for_sin_cos_tan() ||
|
||||
f->realm()->behaviors().shouldResistFingerprinting()) {
|
||||
f->realm()->creationOptions().alwaysUseFdlibm()) {
|
||||
TypedNative typedNative(f->jitInfo()->inlinableNative, *abiType,
|
||||
TypedNative::FdlibmImpl::Yes);
|
||||
auto p =
|
||||
|
Loading…
Reference in New Issue
Block a user