Bug 1775207 - Add per-realm option to enable async stack capturing. r=tcampbell

Differential Revision: https://phabricator.services.mozilla.com/D150061
This commit is contained in:
Tooru Fujisawa 2022-06-30 15:11:36 +00:00
Родитель 400192a425
Коммит 421e48f234
5 изменённых файлов: 94 добавлений и 2 удалений

Просмотреть файл

@ -4136,6 +4136,8 @@ struct MOZ_STACK_CLASS Debugger::CallData {
bool adoptDebuggeeValue();
bool adoptFrame();
bool adoptSource();
bool enableAsyncStack();
bool disableAsyncStack();
using Method = bool (CallData::*)();
@ -6290,6 +6292,36 @@ bool Debugger::CallData::adoptSource() {
return true;
}
bool Debugger::CallData::enableAsyncStack() {
if (!args.requireAtLeast(cx, "Debugger.enableAsyncStack", 1)) {
return false;
}
Rooted<GlobalObject*> global(cx, dbg->unwrapDebuggeeArgument(cx, args[0]));
if (!global) {
return false;
}
global->realm()->isAsyncStackCapturingEnabled = true;
args.rval().setUndefined();
return true;
}
bool Debugger::CallData::disableAsyncStack() {
if (!args.requireAtLeast(cx, "Debugger.disableAsyncStack", 1)) {
return false;
}
Rooted<GlobalObject*> global(cx, dbg->unwrapDebuggeeArgument(cx, args[0]));
if (!global) {
return false;
}
global->realm()->isAsyncStackCapturingEnabled = false;
args.rval().setUndefined();
return true;
}
const JSPropertySpec Debugger::properties[] = {
JS_DEBUG_PSGS("onDebuggerStatement", getOnDebuggerStatement,
setOnDebuggerStatement),
@ -6332,6 +6364,8 @@ const JSFunctionSpec Debugger::methods[] = {
JS_DEBUG_FN("adoptDebuggeeValue", adoptDebuggeeValue, 1),
JS_DEBUG_FN("adoptFrame", adoptFrame, 1),
JS_DEBUG_FN("adoptSource", adoptSource, 1),
JS_DEBUG_FN("enableAsyncStack", enableAsyncStack, 1),
JS_DEBUG_FN("disableAsyncStack", disableAsyncStack, 1),
JS_FS_END};
const JSFunctionSpec Debugger::static_methods[]{

Просмотреть файл

@ -518,6 +518,14 @@ the adopting debugger, this method will throw.
Given `source` of type `Debugger.Source` which is owned by an arbitrary
`Debugger`, return an equivalent `Debugger.Source` owned by this `Debugger`.
### `enableAsyncStack(global)`
Enable async stack capturing for the realm for the global object designated by
<i>global</i>.
### `disableAsyncStack(global)`
Disable async stack capturing for the realm for the global object designated by
<i>global</i>.
## Static methods of the Debugger Object
The functions described below are not called with a `this` value.

Просмотреть файл

@ -0,0 +1,35 @@
// |jit-test| --async-stacks-capture-debuggee-only
const g = newGlobal({newCompartment: true});
const code = `
var stack = "";
async function Async() {
await 1;
stack = new Error().stack;
}
function Sync() {
Async();
}
Sync();
`;
g.eval(code);
drainJobQueue();
assertEq(g.stack.includes("Sync"), false);
let dbg = new Debugger();
dbg.enableAsyncStack(g);
g.eval(code);
drainJobQueue();
assertEq(g.stack.includes("Sync"), true);
dbg.disableAsyncStack(g);
g.eval(code);
drainJobQueue();
assertEq(g.stack.includes("Sync"), false);

Просмотреть файл

@ -4593,8 +4593,12 @@ JS_PUBLIC_API bool JS::IsAsyncStackCaptureEnabledForRealm(JSContext* cx) {
return false;
}
return !cx->options().asyncStackCaptureDebuggeeOnly() ||
cx->realm()->isDebuggee();
if (!cx->options().asyncStackCaptureDebuggeeOnly() ||
cx->realm()->isDebuggee()) {
return true;
}
return cx->realm()->isAsyncStackCapturingEnabled;
}
JS_PUBLIC_API bool JS::CopyAsyncStack(JSContext* cx,

Просмотреть файл

@ -431,6 +431,17 @@ class JS::Realm : public JS::shadow::Realm {
// This prevents us from creating new wrappers for the compartment.
bool nukedIncomingWrappers = false;
// Enable async stack capturing for this realm even if
// JS::ContextOptions::asyncStackCaptureDebuggeeOnly_ is true.
//
// No-op when JS::ContextOptions::asyncStack_ is false, or
// JS::ContextOptions::asyncStackCaptureDebuggeeOnly_ is false.
//
// This can be used as a lightweight alternative for making the global
// debuggee, if the async stack capturing is necessary but no other debugging
// features are used.
bool isAsyncStackCapturingEnabled = false;
private:
void updateDebuggerObservesFlag(unsigned flag);