Skip to content

Commit 3f48ab3

Browse files
author
Eugene Ostroukhov
committed
inspector: do not add 'inspector' property
'inspector' property is not an official API and should not be published on process object, where the user may discover it. This change was extracted from #12263 that will be focused on creating JS bindings. PR-URL: #12656 Reviewed-By: Aleksey Kozyatinskiy <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]>
1 parent 6ade7f3 commit 3f48ab3

File tree

6 files changed

+115
-161
lines changed

6 files changed

+115
-161
lines changed

lib/internal/bootstrap_node.js

+17-28
Original file line numberDiff line numberDiff line change
@@ -254,52 +254,41 @@
254254
}
255255

256256
function setupGlobalConsole() {
257-
var inspectorConsole;
258-
var wrapConsoleCall;
259-
if (process.inspector) {
260-
inspectorConsole = global.console;
261-
wrapConsoleCall = process.inspector.wrapConsoleCall;
262-
delete process.inspector.wrapConsoleCall;
263-
if (Object.keys(process.inspector).length === 0)
264-
delete process.inspector;
265-
}
266-
var console;
257+
const originalConsole = global.console;
258+
let console;
267259
Object.defineProperty(global, 'console', {
268260
configurable: true,
269261
enumerable: true,
270262
get: function() {
271263
if (!console) {
272-
console = NativeModule.require('console');
273-
installInspectorConsoleIfNeeded(console,
274-
inspectorConsole,
275-
wrapConsoleCall);
264+
console = installInspectorConsole(originalConsole);
276265
}
277266
return console;
278267
}
279268
});
280269
}
281270

282-
function installInspectorConsoleIfNeeded(console,
283-
inspectorConsole,
284-
wrapConsoleCall) {
285-
if (!inspectorConsole)
286-
return;
271+
function installInspectorConsole(globalConsole) {
272+
const wrappedConsole = NativeModule.require('console');
273+
const inspector = process.binding('inspector');
287274
const config = {};
288-
for (const key of Object.keys(console)) {
289-
if (!inspectorConsole.hasOwnProperty(key))
275+
for (const key of Object.keys(wrappedConsole)) {
276+
if (!globalConsole.hasOwnProperty(key))
290277
continue;
291-
// If node console has the same method as inspector console,
278+
// If global console has the same method as inspector console,
292279
// then wrap these two methods into one. Native wrapper will preserve
293280
// the original stack.
294-
console[key] = wrapConsoleCall(inspectorConsole[key],
295-
console[key],
296-
config);
281+
wrappedConsole[key] = inspector.consoleCall.bind(wrappedConsole,
282+
globalConsole[key],
283+
wrappedConsole[key],
284+
config);
297285
}
298-
for (const key of Object.keys(inspectorConsole)) {
299-
if (console.hasOwnProperty(key))
286+
for (const key of Object.keys(globalConsole)) {
287+
if (wrappedConsole.hasOwnProperty(key))
300288
continue;
301-
console[key] = inspectorConsole[key];
289+
wrappedConsole[key] = globalConsole[key];
302290
}
291+
return wrappedConsole;
303292
}
304293

305294
function setupProcessFatal() {

lib/module.js

+1-14
Original file line numberDiff line numberDiff line change
@@ -472,19 +472,6 @@ function tryModuleLoad(module, filename) {
472472
}
473473
}
474474

475-
function getInspectorCallWrapper() {
476-
var inspector = process.inspector;
477-
if (!inspector || !inspector.callAndPauseOnStart) {
478-
return null;
479-
}
480-
var wrapper = inspector.callAndPauseOnStart.bind(inspector);
481-
delete inspector.callAndPauseOnStart;
482-
if (Object.keys(process.inspector).length === 0) {
483-
delete process.inspector;
484-
}
485-
return wrapper;
486-
}
487-
488475
Module._resolveFilename = function(request, parent, isMain) {
489476
if (NativeModule.nonInternalExists(request)) {
490477
return request;
@@ -563,7 +550,7 @@ Module.prototype._compile = function(content, filename) {
563550
// Set breakpoint on module start
564551
if (filename === resolvedArgv) {
565552
delete process._debugWaitConnect;
566-
inspectorWrapper = getInspectorCallWrapper();
553+
inspectorWrapper = process.binding('inspector').callAndPauseOnStart;
567554
if (!inspectorWrapper) {
568555
const Debug = vm.runInDebugContext('Debug');
569556
Debug.setBreakPoint(compiledWrapper, 0, 0);

src/env.h

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ namespace node {
7272
V(arrow_message_private_symbol, "node:arrowMessage") \
7373
V(contextify_context_private_symbol, "node:contextify:context") \
7474
V(contextify_global_private_symbol, "node:contextify:global") \
75+
V(inspector_delegate_private_symbol, "node:inspector:delegate") \
7576
V(decorated_private_symbol, "node:decorated") \
7677
V(npn_buffer_private_symbol, "node:npnBuffer") \
7778
V(processed_private_symbol, "node:processed") \

src/inspector_agent.cc

+79-112
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,61 @@ static int RegisterDebugSignalHandler() {
154154
return 0;
155155
}
156156
#endif // _WIN32
157-
} // namespace
158157

158+
void InspectorConsoleCall(const v8::FunctionCallbackInfo<Value>& info) {
159+
Isolate* isolate = info.GetIsolate();
160+
HandleScope handle_scope(isolate);
161+
Local<Context> context = isolate->GetCurrentContext();
162+
CHECK_LT(2, info.Length());
163+
std::vector<Local<Value>> call_args;
164+
for (int i = 3; i < info.Length(); ++i) {
165+
call_args.push_back(info[i]);
166+
}
167+
Environment* env = Environment::GetCurrent(isolate);
168+
if (env->inspector_agent()->enabled()) {
169+
Local<Value> inspector_method = info[0];
170+
CHECK(inspector_method->IsFunction());
171+
Local<Value> config_value = info[2];
172+
CHECK(config_value->IsObject());
173+
Local<Object> config_object = config_value.As<Object>();
174+
Local<String> in_call_key = FIXED_ONE_BYTE_STRING(isolate, "in_call");
175+
if (!config_object->Has(context, in_call_key).FromMaybe(false)) {
176+
CHECK(config_object->Set(context,
177+
in_call_key,
178+
v8::True(isolate)).FromJust());
179+
CHECK(!inspector_method.As<Function>()->Call(context,
180+
info.Holder(),
181+
call_args.size(),
182+
call_args.data()).IsEmpty());
183+
}
184+
CHECK(config_object->Delete(context, in_call_key).FromJust());
185+
}
186+
187+
Local<Value> node_method = info[1];
188+
CHECK(node_method->IsFunction());
189+
static_cast<void>(node_method.As<Function>()->Call(context,
190+
info.Holder(),
191+
call_args.size(),
192+
call_args.data()));
193+
}
194+
195+
void CallAndPauseOnStart(
196+
const v8::FunctionCallbackInfo<v8::Value>& args) {
197+
Environment* env = Environment::GetCurrent(args);
198+
CHECK_GT(args.Length(), 1);
199+
CHECK(args[0]->IsFunction());
200+
std::vector<v8::Local<v8::Value>> call_args;
201+
for (int i = 2; i < args.Length(); i++) {
202+
call_args.push_back(args[i]);
203+
}
204+
205+
env->inspector_agent()->PauseOnNextJavascriptStatement("Break on start");
206+
v8::MaybeLocal<v8::Value> retval =
207+
args[0].As<v8::Function>()->Call(env->context(), args[1],
208+
call_args.size(), call_args.data());
209+
args.GetReturnValue().Set(retval.ToLocalChecked());
210+
}
211+
} // namespace
159212

160213
// Used in NodeInspectorClient::currentTimeMS() below.
161214
const int NANOS_PER_MSEC = 1000000;
@@ -263,12 +316,6 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient {
263316
channel_->dispatchProtocolMessage(message);
264317
}
265318

266-
void schedulePauseOnNextStatement(const std::string& reason) {
267-
if (channel_ != nullptr) {
268-
channel_->schedulePauseOnNextStatement(reason);
269-
}
270-
}
271-
272319
Local<Context> ensureDefaultContextInGroup(int contextGroupId) override {
273320
return env_->context();
274321
}
@@ -302,10 +349,8 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient {
302349
script_id);
303350
}
304351

305-
InspectorSessionDelegate* delegate() {
306-
if (channel_ == nullptr)
307-
return nullptr;
308-
return channel_->delegate();
352+
ChannelImpl* channel() {
353+
return channel_.get();
309354
}
310355

311356
private:
@@ -320,98 +365,22 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient {
320365
Agent::Agent(Environment* env) : parent_env_(env),
321366
inspector_(nullptr),
322367
platform_(nullptr),
323-
inspector_console_(false) {}
368+
enabled_(false) {}
324369

325-
// Header has unique_ptr to some incomplete types - this definition tells
326-
// the compiler to figure out destruction here, were those types are complete
370+
// Destructor needs to be defined here in implementation file as the header
371+
// does not have full definition of some classes.
327372
Agent::~Agent() {
328373
}
329374

330-
// static
331-
void Agent::InspectorConsoleCall(const v8::FunctionCallbackInfo<Value>& info) {
332-
Isolate* isolate = info.GetIsolate();
333-
Local<Context> context = isolate->GetCurrentContext();
334-
335-
CHECK(info.Data()->IsArray());
336-
Local<v8::Array> args = info.Data().As<v8::Array>();
337-
CHECK_EQ(args->Length(), 3);
338-
339-
std::vector<Local<Value>> call_args(info.Length());
340-
for (int i = 0; i < info.Length(); ++i) {
341-
call_args[i] = info[i];
342-
}
343-
344-
Environment* env = Environment::GetCurrent(isolate);
345-
if (env->inspector_agent()->inspector_console_) {
346-
Local<Value> inspector_method = args->Get(context, 0).ToLocalChecked();
347-
CHECK(inspector_method->IsFunction());
348-
Local<Value> config_value = args->Get(context, 2).ToLocalChecked();
349-
CHECK(config_value->IsObject());
350-
Local<Object> config_object = config_value.As<Object>();
351-
Local<String> in_call_key = FIXED_ONE_BYTE_STRING(isolate, "in_call");
352-
if (!config_object->Has(context, in_call_key).FromMaybe(false)) {
353-
CHECK(config_object->Set(context,
354-
in_call_key,
355-
v8::True(isolate)).FromJust());
356-
CHECK(!inspector_method.As<Function>()->Call(context,
357-
info.Holder(),
358-
call_args.size(),
359-
call_args.data()).IsEmpty());
360-
}
361-
CHECK(config_object->Delete(context, in_call_key).FromJust());
362-
}
363-
364-
Local<Value> node_method =
365-
args->Get(context, 1).ToLocalChecked();
366-
CHECK(node_method->IsFunction());
367-
static_cast<void>(node_method.As<Function>()->Call(context,
368-
info.Holder(),
369-
call_args.size(),
370-
call_args.data()));
371-
}
372-
373-
// static
374-
void Agent::InspectorWrapConsoleCall(const FunctionCallbackInfo<Value>& info) {
375-
Environment* env = Environment::GetCurrent(info);
376-
if (info.Length() != 3 || !info[0]->IsFunction() ||
377-
!info[1]->IsFunction() || !info[2]->IsObject()) {
378-
return env->ThrowError("inspector.wrapConsoleCall takes exactly 3 "
379-
"arguments: two functions and an object.");
380-
}
381-
382-
Local<v8::Array> array = v8::Array::New(env->isolate(), info.Length());
383-
CHECK(array->Set(env->context(), 0, info[0]).FromJust());
384-
CHECK(array->Set(env->context(), 1, info[1]).FromJust());
385-
CHECK(array->Set(env->context(), 2, info[2]).FromJust());
386-
info.GetReturnValue().Set(Function::New(env->context(),
387-
InspectorConsoleCall,
388-
array).ToLocalChecked());
389-
}
390-
391375
bool Agent::Start(v8::Platform* platform, const char* path,
392376
const DebugOptions& options) {
393377
path_ = path == nullptr ? "" : path;
394378
debug_options_ = options;
395-
inspector_console_ = false;
396379
inspector_ =
397380
std::unique_ptr<NodeInspectorClient>(
398381
new NodeInspectorClient(parent_env_, platform));
399382
platform_ = platform;
400-
Local<Object> process = parent_env_->process_object();
401-
Local<Object> inspector = Object::New(parent_env_->isolate());
402-
Local<String> name =
403-
FIXED_ONE_BYTE_STRING(parent_env_->isolate(), "inspector");
404-
process->DefineOwnProperty(parent_env_->context(),
405-
name,
406-
inspector,
407-
v8::ReadOnly).FromJust();
408-
parent_env_->SetMethod(inspector, "wrapConsoleCall",
409-
InspectorWrapConsoleCall);
410383
if (options.inspector_enabled()) {
411-
if (options.wait_for_connect()) {
412-
parent_env_->SetMethod(inspector, "callAndPauseOnStart",
413-
CallAndPauseOnStart);
414-
}
415384
return StartIoThread();
416385
} else {
417386
CHECK_EQ(0, uv_async_init(uv_default_loop(),
@@ -431,7 +400,7 @@ bool Agent::StartIoThread() {
431400

432401
CHECK_NE(inspector_, nullptr);
433402

434-
inspector_console_ = true;
403+
enabled_ = true;
435404
io_ = std::unique_ptr<InspectorIo>(
436405
new InspectorIo(parent_env_, platform_, path_, debug_options_));
437406
if (!io_->Start()) {
@@ -469,7 +438,7 @@ void Agent::Stop() {
469438
}
470439

471440
void Agent::Connect(InspectorSessionDelegate* delegate) {
472-
inspector_console_ = true;
441+
enabled_ = true;
473442
inspector_->connectFrontend(delegate);
474443
}
475444

@@ -481,26 +450,6 @@ bool Agent::IsStarted() {
481450
return !!inspector_;
482451
}
483452

484-
// static
485-
void Agent::CallAndPauseOnStart(
486-
const v8::FunctionCallbackInfo<v8::Value>& args) {
487-
Environment* env = Environment::GetCurrent(args);
488-
CHECK_GT(args.Length(), 1);
489-
CHECK(args[0]->IsFunction());
490-
std::vector<v8::Local<v8::Value>> call_args;
491-
for (int i = 2; i < args.Length(); i++) {
492-
call_args.push_back(args[i]);
493-
}
494-
495-
Agent* agent = env->inspector_agent();
496-
agent->inspector_->schedulePauseOnNextStatement("Break on start");
497-
498-
v8::MaybeLocal<v8::Value> retval =
499-
args[0].As<v8::Function>()->Call(env->context(), args[1],
500-
call_args.size(), call_args.data());
501-
args.GetReturnValue().Set(retval.ToLocalChecked());
502-
}
503-
504453
void Agent::WaitForDisconnect() {
505454
if (io_ != nullptr) {
506455
io_->WaitForDisconnect();
@@ -529,5 +478,23 @@ void Agent::RunMessageLoop() {
529478
inspector_->runMessageLoopOnPause(CONTEXT_GROUP_ID);
530479
}
531480

481+
void Agent::PauseOnNextJavascriptStatement(const std::string& reason) {
482+
ChannelImpl* channel = inspector_->channel();
483+
if (channel != nullptr)
484+
channel->schedulePauseOnNextStatement(reason);
485+
}
486+
487+
// static
488+
void Agent::InitJSBindings(Local<Object> target, Local<Value> unused,
489+
Local<Context> context, void* priv) {
490+
Environment* env = Environment::GetCurrent(context);
491+
Agent* agent = env->inspector_agent();
492+
env->SetMethod(target, "consoleCall", InspectorConsoleCall);
493+
if (agent->debug_options_.wait_for_connect())
494+
env->SetMethod(target, "callAndPauseOnStart", CallAndPauseOnStart);
495+
}
532496
} // namespace inspector
533497
} // namespace node
498+
499+
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector,
500+
node::inspector::Agent::InitJSBindings);

0 commit comments

Comments
 (0)