Skip to content

Commit 4ce0133

Browse files
committed
src: initialize inspector before RunBootstrapping()
This is necessary for `--inspect-brk-node` to work, and for the inspector to be aware of scripts created before bootstrapping. Fixes: #32648 Refs: #30467 (comment)
1 parent 0ddfd0f commit 4ce0133

File tree

3 files changed

+67
-35
lines changed

3 files changed

+67
-35
lines changed

src/api/environment.cc

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,19 @@ void FreeIsolateData(IsolateData* isolate_data) {
330330
delete isolate_data;
331331
}
332332

333+
InspectorParentHandle::~InspectorParentHandle() {}
334+
335+
// Hide the internal handle class from the public API.
336+
#if HAVE_INSPECTOR
337+
struct InspectorParentHandleImpl : public InspectorParentHandle {
338+
std::unique_ptr<inspector::ParentInspectorHandle> impl;
339+
340+
explicit InspectorParentHandleImpl(
341+
std::unique_ptr<inspector::ParentInspectorHandle>&& impl)
342+
: impl(std::move(impl)) {}
343+
};
344+
#endif
345+
333346
Environment* CreateEnvironment(IsolateData* isolate_data,
334347
Local<Context> context,
335348
int argc,
@@ -348,7 +361,8 @@ Environment* CreateEnvironment(
348361
const std::vector<std::string>& args,
349362
const std::vector<std::string>& exec_args,
350363
EnvironmentFlags::Flags flags,
351-
ThreadId thread_id) {
364+
ThreadId thread_id,
365+
std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
352366
Isolate* isolate = context->GetIsolate();
353367
HandleScope handle_scope(isolate);
354368
Context::Scope context_scope(context);
@@ -365,6 +379,16 @@ Environment* CreateEnvironment(
365379
env->set_abort_on_uncaught_exception(false);
366380
}
367381

382+
#if HAVE_INSPECTOR
383+
if (inspector_parent_handle) {
384+
env->InitializeInspector(
385+
std::move(static_cast<InspectorParentHandleImpl*>(
386+
inspector_parent_handle.get())->impl));
387+
} else {
388+
env->InitializeInspector({});
389+
}
390+
#endif
391+
368392
if (env->RunBootstrapping().IsEmpty()) {
369393
FreeEnvironment(env);
370394
return nullptr;
@@ -394,19 +418,6 @@ void FreeEnvironment(Environment* env) {
394418
delete env;
395419
}
396420

397-
InspectorParentHandle::~InspectorParentHandle() {}
398-
399-
// Hide the internal handle class from the public API.
400-
#if HAVE_INSPECTOR
401-
struct InspectorParentHandleImpl : public InspectorParentHandle {
402-
std::unique_ptr<inspector::ParentInspectorHandle> impl;
403-
404-
explicit InspectorParentHandleImpl(
405-
std::unique_ptr<inspector::ParentInspectorHandle>&& impl)
406-
: impl(std::move(impl)) {}
407-
};
408-
#endif
409-
410421
NODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
411422
Environment* env,
412423
ThreadId thread_id,
@@ -430,27 +441,17 @@ void LoadEnvironment(Environment* env) {
430441
MaybeLocal<Value> LoadEnvironment(
431442
Environment* env,
432443
StartExecutionCallback cb,
433-
std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
444+
std::unique_ptr<InspectorParentHandle> removeme) {
434445
env->InitializeLibuv(per_process::v8_is_profiling);
435446
env->InitializeDiagnostics();
436447

437-
#if HAVE_INSPECTOR
438-
if (inspector_parent_handle) {
439-
env->InitializeInspector(
440-
std::move(static_cast<InspectorParentHandleImpl*>(
441-
inspector_parent_handle.get())->impl));
442-
} else {
443-
env->InitializeInspector({});
444-
}
445-
#endif
446-
447448
return StartExecution(env, cb);
448449
}
449450

450451
MaybeLocal<Value> LoadEnvironment(
451452
Environment* env,
452453
const char* main_script_source_utf8,
453-
std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
454+
std::unique_ptr<InspectorParentHandle> removeme) {
454455
CHECK_NOT_NULL(main_script_source_utf8);
455456
return LoadEnvironment(
456457
env,
@@ -475,8 +476,7 @@ MaybeLocal<Value> LoadEnvironment(
475476
env->process_object(),
476477
env->native_module_require()};
477478
return ExecuteBootstrapper(env, name.c_str(), &params, &args);
478-
},
479-
std::move(inspector_parent_handle));
479+
});
480480
}
481481

482482
Environment* GetCurrentEnvironment(Local<Context> context) {

src/node.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,10 @@ enum Flags : uint64_t {
420420
};
421421
} // namespace EnvironmentFlags
422422

423+
struct InspectorParentHandle {
424+
virtual ~InspectorParentHandle();
425+
};
426+
423427
// TODO(addaleax): Maybe move per-Environment options parsing here.
424428
// Returns nullptr when the Environment cannot be created e.g. there are
425429
// pending JavaScript exceptions.
@@ -436,16 +440,14 @@ NODE_EXTERN Environment* CreateEnvironment(
436440
const std::vector<std::string>& args,
437441
const std::vector<std::string>& exec_args,
438442
EnvironmentFlags::Flags flags = EnvironmentFlags::kDefaultFlags,
439-
ThreadId thread_id = {} /* allocates a thread id automatically */);
443+
ThreadId thread_id = {} /* allocates a thread id automatically */,
444+
std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
440445

441-
struct InspectorParentHandle {
442-
virtual ~InspectorParentHandle();
443-
};
444446
// Returns a handle that can be passed to `LoadEnvironment()`, making the
445447
// child Environment accessible to the inspector as if it were a Node.js Worker.
446448
// `child_thread_id` can be created using `AllocateEnvironmentThreadId()`
447449
// and then later passed on to `CreateEnvironment()` to create the child
448-
// Environment.
450+
// Environment, together with the inspector handle.
449451
// This method should not be called while the parent Environment is active
450452
// on another thread.
451453
NODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
@@ -463,14 +465,16 @@ using StartExecutionCallback =
463465

464466
// TODO(addaleax): Deprecate this in favour of the MaybeLocal<> overload.
465467
NODE_EXTERN void LoadEnvironment(Environment* env);
468+
// The `InspectorParentHandle` arguments here are ignored and not used.
469+
// For passing `InspectorParentHandle`, use `CreateEnvironment()`.
466470
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment(
467471
Environment* env,
468472
StartExecutionCallback cb,
469-
std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
473+
std::unique_ptr<InspectorParentHandle> ignored_donotuse_removeme = {});
470474
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment(
471475
Environment* env,
472476
const char* main_script_source_utf8,
473-
std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
477+
std::unique_ptr<InspectorParentHandle> ignored_donotuse_removeme = {});
474478
NODE_EXTERN void FreeEnvironment(Environment* env);
475479

476480
// Set a callback that is called when process.exit() is called from JS,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
// Regression test for https://github.com/nodejs/node/issues/32648
5+
6+
common.skipIfInspectorDisabled();
7+
8+
const { NodeInstance } = require('../common/inspector-helper.js');
9+
10+
async function runTest() {
11+
const child = new NodeInstance(['--inspect-brk-node=0', '-p', '42']);
12+
const session = await child.connectInspectorSession();
13+
await session.send({ method: 'Runtime.enable' });
14+
await session.send({ method: 'Debugger.enable' });
15+
await session.send({ method: 'Runtime.runIfWaitingForDebugger' });
16+
await session.waitForNotification((notification) => {
17+
// The main assertion here is that we do hit the loader script first.
18+
return notification.method === 'Debugger.scriptParsed' &&
19+
notification.params.url === 'internal/bootstrap/loaders.js';
20+
});
21+
22+
await session.waitForNotification('Debugger.paused');
23+
await session.send({ method: 'Debugger.resume' });
24+
await session.waitForNotification('Debugger.paused');
25+
await session.runToCompletion();
26+
}
27+
28+
runTest().then(common.mustCall());

0 commit comments

Comments
 (0)