Bug 1862922 - Run telemetry on day of week support r=arai

Differential Revision: https://phabricator.services.mozilla.com/D193367
This commit is contained in:
Vinny Diehl 2023-11-15 10:26:23 +00:00
parent 8c1e539630
commit 71067c635f
6 changed files with 114 additions and 24 deletions

View file

@ -71,6 +71,7 @@ custom onunderflow sets an element onunderflow event listener
// JavaScript feature usage // JavaScript feature usage
custom JS_asmjs uses asm.js custom JS_asmjs uses asm.js
custom JS_wasm uses WebAssembly custom JS_wasm uses WebAssembly
custom JS_late_weekday parses a Date with day of week in an unexpected position
// Console API // Console API
method console.assert method console.assert

View file

@ -91,7 +91,7 @@ extern JS_PUBLIC_API void JS_SetAccumulateTelemetryCallback(
* fixed member of the mozilla::UseCounter enum by the callback. * fixed member of the mozilla::UseCounter enum by the callback.
*/ */
enum class JSUseCounter { ASMJS, WASM }; enum class JSUseCounter { ASMJS, WASM, LATE_WEEKDAY };
using JSSetUseCounterCallback = void (*)(JSObject*, JSUseCounter); using JSSetUseCounterCallback = void (*)(JSObject*, JSUseCounter);

View file

@ -1118,15 +1118,6 @@ static bool TryParseDashedDatePrefix(const CharT* s, size_t length,
int* monOut, int* mdayOut) { int* monOut, int* mdayOut) {
size_t i = *indexOut; size_t i = *indexOut;
if (*monOut != -1) {
// If the month has already been set by ParseDate, we'll be at a '-', we
// can skip it and start parsing the mday
if (i >= length || s[i] != '-') {
return false;
}
++i;
}
size_t pre = i; size_t pre = i;
size_t mday; size_t mday;
if (!ParseDigitsNOrLess(6, &mday, s, &i, length)) { if (!ParseDigitsNOrLess(6, &mday, s, &i, length)) {
@ -1355,7 +1346,8 @@ constexpr size_t MinKeywordLength(const CharsAndAction (&keywords)[N]) {
template <typename CharT> template <typename CharT>
static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s, static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
size_t length, ClippedTime* result) { size_t length, ClippedTime* result,
bool* countLateWeekday) {
if (length == 0) { if (length == 0) {
return false; return false;
} }
@ -1369,7 +1361,7 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
bool seenMonthName = false; bool seenMonthName = false;
// Before we begin, we need to scrub any words from the beginning of the // Before we begin, we need to scrub any words from the beginning of the
// string that are not a month name // string up to the first number, recording the month if we encounter it
for (; index < length; index++) { for (; index < length; index++) {
int c = s[index]; int c = s[index];
@ -1403,11 +1395,6 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
break; break;
} }
} }
if (seenMonthName) {
// If we've found the month name, we're done with this loop, otherwise we
// move on to the next word
break;
}
} }
if (index >= length) { if (index >= length) {
@ -1430,6 +1417,8 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
bool negativeYear = false; bool negativeYear = false;
// Includes "GMT", "UTC", "UT", and "Z" timezone keywords // Includes "GMT", "UTC", "UT", and "Z" timezone keywords
bool seenGmtAbbr = false; bool seenGmtAbbr = false;
// For telemetry purposes
bool seenLateWeekday = false;
// Try parsing the leading dashed-date. // Try parsing the leading dashed-date.
// //
@ -1676,6 +1665,7 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
// Completely ignore days of the week, and don't derive any semantics // Completely ignore days of the week, and don't derive any semantics
// from them. // from them.
if (action == 0) { if (action == 0) {
seenLateWeekday = true;
break; break;
} }
@ -1845,16 +1835,38 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
date += tzOffset * msPerMinute; date += tzOffset * msPerMinute;
} }
// Setting this down here so that it only counts the telemetry in
// the case of a successful parse.
if (seenLateWeekday) {
*countLateWeekday = true;
}
*result = TimeClip(date); *result = TimeClip(date);
return true; return true;
} }
static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, JSLinearString* s, static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, JSLinearString* s,
ClippedTime* result) { ClippedTime* result, JSContext* cx) {
bool countLateWeekday = false;
bool success;
{
AutoCheckCannotGC nogc; AutoCheckCannotGC nogc;
return s->hasLatin1Chars() success = s->hasLatin1Chars()
? ParseDate(forceUTC, s->latin1Chars(nogc), s->length(), result) ? ParseDate(forceUTC, s->latin1Chars(nogc), s->length(),
: ParseDate(forceUTC, s->twoByteChars(nogc), s->length(), result); result, &countLateWeekday)
: ParseDate(forceUTC, s->twoByteChars(nogc), s->length(),
result, &countLateWeekday);
}
// We are running telemetry to see if support for day of week after
// mday can be dropped. It is being done here to keep
// JSRuntime::setUseCounter out of AutoCheckCannotGC's scope.
if (countLateWeekday) {
cx->runtime()->setUseCounter(cx->global(), JSUseCounter::LATE_WEEKDAY);
}
return success;
} }
static bool date_parse(JSContext* cx, unsigned argc, Value* vp) { static bool date_parse(JSContext* cx, unsigned argc, Value* vp) {
@ -1876,7 +1888,7 @@ static bool date_parse(JSContext* cx, unsigned argc, Value* vp) {
} }
ClippedTime result; ClippedTime result;
if (!ParseDate(ForceUTC(cx->realm()), linearStr, &result)) { if (!ParseDate(ForceUTC(cx->realm()), linearStr, &result, cx)) {
args.rval().setNaN(); args.rval().setNaN();
return true; return true;
} }
@ -3704,7 +3716,7 @@ static bool DateOneArgument(JSContext* cx, const CallArgs& args) {
return false; return false;
} }
if (!ParseDate(ForceUTC(cx->realm()), linearStr, &t)) { if (!ParseDate(ForceUTC(cx->realm()), linearStr, &t, cx)) {
t = ClippedTime::invalid(); t = ClippedTime::invalid();
} }
} else { } else {

View file

@ -2587,6 +2587,9 @@ static void SetUseCounterCallback(JSObject* obj, JSUseCounter counter) {
case JSUseCounter::WASM: case JSUseCounter::WASM:
SetUseCounter(obj, eUseCounter_custom_JS_wasm); SetUseCounter(obj, eUseCounter_custom_JS_wasm);
break; break;
case JSUseCounter::LATE_WEEKDAY:
SetUseCounter(obj, eUseCounter_custom_JS_late_weekday);
break;
default: default:
MOZ_ASSERT_UNREACHABLE("Unexpected JSUseCounter id"); MOZ_ASSERT_UNREACHABLE("Unexpected JSUseCounter id");
} }

View file

@ -9,6 +9,8 @@ support-files = [
"browser_promise_userInteractionHandling.html" "browser_promise_userInteractionHandling.html"
] ]
["browser_date_telemetry.js"]
["browser_dead_object.js"] ["browser_dead_object.js"]
["browser_exception_leak.js"] ["browser_exception_leak.js"]

View file

@ -0,0 +1,72 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/.
*/
const HIST_ID = "USE_COUNTER2_JS_LATE_WEEKDAY_PAGE";
const triggers = [
"Sep 26 Tues 1995",
"Sep 26 1995 Tues",
"Sep 26 1995 Tues 09:30",
"Sep 26 1995 09:Tues:30",
"Sep 26 1995 09:30 Tues GMT",
"Sep 26 1995 09:30 GMT Tues",
"26 Tues Sep 1995",
"26 Sep Tues 1995",
"26 Sep 1995 Tues",
"1995-09-26 Tues",
// Multiple occurences should only trigger 1 counter
"Sep 26 Tues 1995 Tues",
];
const nonTriggers = [
"Sep 26 1995",
"Tues Sep 26 1995",
"Sep Tues 26 1995",
// Invalid format shouldn't trigger the counter
"Sep 26 Tues 1995 foo",
];
function getCount() {
return Services.telemetry.getHistogramById(HIST_ID).snapshot().sum;
}
/**
* Opens and closes a browser tab with minimal JS code which parses
* the given Date format.
*/
async function parseFormat(format, call = "new Date") {
let newTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
`data:text/html;charset=utf-8,<script>${call}("${format}")</script>`
);
BrowserTestUtils.removeTab(newTab);
}
add_task(async function test_date_telemetry() {
let sum = getCount();
// waitForCondition cannot be used to test if nothing has changed,
// so these tests aren't as reliable as the ones in the next loop.
// If you encounter an inexplicable failure in any of these tests,
// debug by adding a delay to the end of the parseFormat function.
for (const format of nonTriggers) {
await parseFormat(format);
const count = getCount();
is(count, sum, `${format} should not trigger telemetry`);
sum = count;
}
for (const [i, format] of triggers.entries()) {
// Alternate between Date constructor and Date.parse
await parseFormat(format, ["new Date", "Date.parse"][i % 2]);
await BrowserTestUtils.waitForCondition(() => getCount() > sum);
const count = getCount();
is(count, sum + 1, `${format} should trigger telemetry`);
sum = count;
}
});