Skip to content

Commit 8516003

Browse files
trivikraduh95
authored andcommitted
debugger: await initialization after run and restart
Ensure the debugger CLI waits for post-connect initialization before resolving the run and restart commands. This prevents tests and users from observing a prompt before Runtime.runIfWaitingForDebugger() has released the new debuggee. Refs: #61762 Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: #63607 Refs: #61762 Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
1 parent 44809b1 commit 8516003

2 files changed

Lines changed: 126 additions & 5 deletions

File tree

‎lib/internal/debugger/inspect_repl.js‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,11 @@ function createRepl(inspector) {
945945
);
946946
});
947947

948+
asyncfunctionrunAndInit(){
949+
awaitinspector.run();
950+
awaitinitAfterStart();
951+
}
952+
948953
functioninitializeContext(context){
949954
ArrayPrototypeForEach(inspector.domainNames,(domain)=>{
950955
ObjectDefineProperty(context,domain,{
@@ -962,15 +967,15 @@ function createRepl(inspector) {
962967
},
963968

964969
getrun(){
965-
returninspector.run();
970+
returnrunAndInit();
966971
},
967972

968973
getkill(){
969974
returninspector.killChild();
970975
},
971976

972977
getrestart(){
973-
returninspector.run();
978+
returnrunAndInit();
974979
},
975980

976981
getcont(){
@@ -1196,9 +1201,6 @@ function createRepl(inspector) {
11961201
inspector.client.on('close',()=>{
11971202
resetOnStart();
11981203
});
1199-
inspector.client.on('ready',()=>{
1200-
initAfterStart();
1201-
});
12021204

12031205
// Init once for the initial connection
12041206
awaitinitAfterStart();
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
constcommon=require('../common');
5+
6+
common.skipIfInspectorDisabled();
7+
8+
constassert=require('assert');
9+
const{ EventEmitter }=require('events');
10+
const{ PassThrough }=require('stream');
11+
constcreateRepl=require('internal/debugger/inspect_repl');
12+
13+
functioncreateGate(){
14+
letresolve;
15+
constpromise=newPromise((res)=>{
16+
resolve=res;
17+
});
18+
return{ promise, resolve };
19+
}
20+
21+
functioncreateAgent(domain,calls,gates){
22+
constagent=newEventEmitter();
23+
constmethod=(name)=>async()=>{
24+
calls.push(`${domain}.${name}`);
25+
if(domain==='Runtime'&&name==='runIfWaitingForDebugger'){
26+
constgate=gates.shift();
27+
if(gate){
28+
awaitgate.promise;
29+
}
30+
}
31+
};
32+
33+
agent.enable=method('enable');
34+
agent.setSamplingInterval=method('setSamplingInterval');
35+
agent.setAsyncCallStackDepth=method('setAsyncCallStackDepth');
36+
agent.setBlackboxPatterns=method('setBlackboxPatterns');
37+
agent.setPauseOnExceptions=method('setPauseOnExceptions');
38+
agent.runIfWaitingForDebugger=method('runIfWaitingForDebugger');
39+
returnagent;
40+
}
41+
42+
functionevalCommand(repl,command){
43+
returnnewPromise((resolve,reject)=>{
44+
repl.eval(
45+
command,
46+
repl.context,
47+
'debugger-repl-test',
48+
(error,result)=>{
49+
if(error){
50+
reject(error);
51+
}else{
52+
resolve(result);
53+
}
54+
},
55+
);
56+
});
57+
}
58+
59+
asyncfunctionassertCommandWaitsForInit(repl,command,gate,calls){
60+
letsettled=false;
61+
constpromise=evalCommand(repl,command).then(()=>{
62+
settled=true;
63+
});
64+
65+
awaitnewPromise(setImmediate);
66+
assert.strictEqual(
67+
settled,
68+
false,
69+
`${command} resolved before post-connect initialization completed: ${calls}`,
70+
);
71+
72+
gate.resolve();
73+
awaitpromise;
74+
assert.strictEqual(settled,true);
75+
}
76+
77+
(async()=>{
78+
constcalls=[];
79+
construnGate=createGate();
80+
constrestartGate=createGate();
81+
constgates=[null,runGate,restartGate];
82+
constinspector={
83+
client: newEventEmitter(),
84+
domainNames: ['Debugger','HeapProfiler','Profiler','Runtime'],
85+
stdin: newPassThrough(),
86+
stdout: newPassThrough(),
87+
run: common.mustCall(async()=>{
88+
calls.push('inspector.run');
89+
},2),
90+
suspendReplWhile(fn){
91+
returnfn();
92+
},
93+
};
94+
95+
for(constdomainofinspector.domainNames){
96+
inspector[domain]=createAgent(domain,calls,gates);
97+
}
98+
99+
constrepl=awaitcreateRepl(inspector)();
100+
101+
awaitassertCommandWaitsForInit(repl,'run',runGate,calls);
102+
awaitassertCommandWaitsForInit(repl,'restart',restartGate,calls);
103+
104+
assert.deepStrictEqual(
105+
calls.filter((call)=>(
106+
call==='inspector.run'||
107+
call==='Runtime.runIfWaitingForDebugger'
108+
)),
109+
[
110+
'Runtime.runIfWaitingForDebugger',
111+
'inspector.run',
112+
'Runtime.runIfWaitingForDebugger',
113+
'inspector.run',
114+
'Runtime.runIfWaitingForDebugger',
115+
],
116+
);
117+
118+
repl.close();
119+
})().then(common.mustCall());

0 commit comments

Comments
 (0)