-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Historically Node process sends Runtime.executionContextDestroyed with main context as argument when it is finished. This approach has some disadvantages. V8 prevents running some protocol command on destroyed contexts, e.g. Runtime.evaluate will return an error or Debugger.enable won't return a list of scripts. Both command might be useful for different tools, e.g. tool runs Profiler.startPreciseCoverage and at the end of node process it would like to get list of all scripts to match data to source code. Or some tooling frontend would like to provide capabilities to run commands in console when node process is finished to allow user to inspect state of the program at exit. This PR adds new domain: NodeRuntime. When this domain is enabled by at least one client, node will send NodeRuntime.waitingForDebuggerToDisconnect event instead of Runtime.executionContextDestroyed. Based on this signal any protocol client can capture all required information and then disconnect its session.
- Loading branch information
1 parent
153c101
commit 74a3c97
Showing
7 changed files
with
144 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include "runtime_agent.h" | ||
|
||
#include "env-inl.h" | ||
#include "inspector_agent.h" | ||
|
||
namespace node { | ||
namespace inspector { | ||
namespace protocol { | ||
|
||
RuntimeAgent::RuntimeAgent(Environment* env) | ||
: enabled_(false) | ||
, env_(env) {} | ||
|
||
void RuntimeAgent::Wire(UberDispatcher* dispatcher) { | ||
frontend_.reset(new NodeRuntime::Frontend(dispatcher->channel())); | ||
NodeRuntime::Dispatcher::wire(dispatcher, this); | ||
} | ||
|
||
DispatchResponse RuntimeAgent::enable() { | ||
if (!env_->owns_process_state()) { | ||
return DispatchResponse::Error( | ||
"NodeRuntime domain can only be used through main thread sessions"); | ||
} | ||
enabled_ = true; | ||
return DispatchResponse::OK(); | ||
} | ||
|
||
DispatchResponse RuntimeAgent::disable() { | ||
if (!env_->owns_process_state()) { | ||
return DispatchResponse::Error( | ||
"NodeRuntime domain can only be used through main thread sessions"); | ||
} | ||
enabled_ = false; | ||
return DispatchResponse::OK(); | ||
} | ||
|
||
bool RuntimeAgent::reportWaitingForDebuggerToDisconnect() { | ||
if (enabled_) frontend_->waitingForDebuggerToDisconnect(); | ||
return enabled_; | ||
} | ||
} // namespace protocol | ||
} // namespace inspector | ||
} // namespace node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef SRC_INSPECTOR_RUNTIME_AGENT_H_ | ||
#define SRC_INSPECTOR_RUNTIME_AGENT_H_ | ||
|
||
#include "node/inspector/protocol/NodeRuntime.h" | ||
#include "v8.h" | ||
|
||
namespace node { | ||
class Environment; | ||
|
||
namespace inspector { | ||
namespace protocol { | ||
|
||
class RuntimeAgent : public NodeRuntime::Backend { | ||
public: | ||
explicit RuntimeAgent(Environment* env); | ||
|
||
void Wire(UberDispatcher* dispatcher); | ||
|
||
DispatchResponse enable() override; | ||
DispatchResponse disable() override; | ||
|
||
bool reportWaitingForDebuggerToDisconnect(); | ||
|
||
private: | ||
std::shared_ptr<NodeRuntime::Frontend> frontend_; | ||
bool enabled_; | ||
Environment* env_; | ||
}; | ||
} // namespace protocol | ||
} // namespace inspector | ||
} // namespace node | ||
|
||
#endif // SRC_INSPECTOR_RUNTIME_AGENT_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
test/parallel/test-inspector-waiting-for-debugger-to-disconnect.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Flags: --expose-internals | ||
'use strict'; | ||
const common = require('../common'); | ||
|
||
common.skipIfInspectorDisabled(); | ||
|
||
const assert = require('assert'); | ||
const { NodeInstance } = require('../common/inspector-helper.js'); | ||
|
||
async function runTest() { | ||
const child = new NodeInstance(['--inspect-brk=0', '-e', 'process.exit(55)']); | ||
const session = await child.connectInspectorSession(); | ||
await session.send([ | ||
{ method: 'Runtime.enable' }, | ||
{ method: 'NodeRuntime.enable' }, | ||
{ method: 'Runtime.runIfWaitingForDebugger' }]); | ||
await session.waitForNotification((notification) => { | ||
return notification.method === 'NodeRuntime.waitingForDebuggerToDisconnect'; | ||
}); | ||
const receivedExecutionContextDestroyed = session.unprocessedNotifications().some((notification) => { | ||
return notification.method === 'Runtime.executionContextDestroyed' && | ||
notification.params.executionContextId === 1; | ||
}); | ||
if (receivedExecutionContextDestroyed) { | ||
assert.fail(`When NodeRuntime enabled, Runtime.executionContextDestroyed should not be sent`); | ||
} | ||
await session.disconnect(); | ||
assert.strictEqual((await child.expectShutdown()).exitCode, 55); | ||
} | ||
|
||
runTest(); |