Skip to content

Commit 4faa231

Browse files
Eugene Ostroukhovjasnell
authored andcommitted
inspector: Move JS API code to separate file
PR-URL: nodejs#16056 Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 07ec10d commit 4faa231

File tree

4 files changed

+364
-343
lines changed

4 files changed

+364
-343
lines changed

node.gypi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
'sources': [
8383
'src/inspector_agent.cc',
8484
'src/inspector_io.cc',
85+
'src/inspector_js_api.cc',
8586
'src/inspector_socket.cc',
8687
'src/inspector_socket_server.cc',
8788
'src/inspector_agent.h',

src/inspector_agent.cc

Lines changed: 5 additions & 329 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
#include "inspector_agent.h"
22

33
#include "inspector_io.h"
4-
#include "base-object.h"
5-
#include "base-object-inl.h"
64
#include "node_internals.h"
75
#include "v8-inspector.h"
86
#include "v8-platform.h"
9-
#include "zlib.h"
107

118
#include "libplatform/libplatform.h"
129

@@ -16,6 +13,7 @@
1613
#include <vector>
1714

1815
#ifdef __POSIX__
16+
#include <limits.h>
1917
#include <unistd.h> // setuid, getuid
2018
#endif // __POSIX__
2119

@@ -26,23 +24,12 @@ namespace {
2624
using node::FatalError;
2725

2826
using v8::Array;
29-
using v8::Boolean;
3027
using v8::Context;
3128
using v8::Function;
32-
using v8::FunctionCallbackInfo;
33-
using v8::FunctionTemplate;
3429
using v8::HandleScope;
35-
using v8::Integer;
3630
using v8::Isolate;
3731
using v8::Local;
38-
using v8::Maybe;
39-
using v8::MaybeLocal;
40-
using v8::Name;
41-
using v8::NewStringType;
4232
using v8::Object;
43-
using v8::Persistent;
44-
using v8::String;
45-
using v8::Undefined;
4633
using v8::Value;
4734

4835
using v8_inspector::StringBuffer;
@@ -193,173 +180,6 @@ static int StartDebugSignalHandler() {
193180
}
194181
#endif // _WIN32
195182

196-
class JSBindingsConnection : public AsyncWrap {
197-
public:
198-
class JSBindingsSessionDelegate : public InspectorSessionDelegate {
199-
public:
200-
JSBindingsSessionDelegate(Environment* env,
201-
JSBindingsConnection* connection)
202-
: env_(env),
203-
connection_(connection) {
204-
}
205-
206-
bool WaitForFrontendMessageWhilePaused() override {
207-
return false;
208-
}
209-
210-
void SendMessageToFrontend(const v8_inspector::StringView& message)
211-
override {
212-
Isolate* isolate = env_->isolate();
213-
HandleScope handle_scope(isolate);
214-
Context::Scope context_scope(env_->context());
215-
MaybeLocal<String> v8string =
216-
String::NewFromTwoByte(isolate, message.characters16(),
217-
NewStringType::kNormal, message.length());
218-
Local<Value> argument = v8string.ToLocalChecked().As<Value>();
219-
connection_->OnMessage(argument);
220-
}
221-
222-
void Disconnect() {
223-
Agent* agent = env_->inspector_agent();
224-
if (agent->delegate() == this)
225-
agent->Disconnect();
226-
}
227-
228-
private:
229-
Environment* env_;
230-
JSBindingsConnection* connection_;
231-
};
232-
233-
JSBindingsConnection(Environment* env,
234-
Local<Object> wrap,
235-
Local<Function> callback)
236-
: AsyncWrap(env, wrap, PROVIDER_INSPECTORJSBINDING),
237-
delegate_(env, this),
238-
callback_(env->isolate(), callback) {
239-
Wrap(wrap, this);
240-
241-
Agent* inspector = env->inspector_agent();
242-
if (inspector->delegate() != nullptr) {
243-
env->ThrowTypeError("Session is already attached");
244-
return;
245-
}
246-
inspector->Connect(&delegate_);
247-
}
248-
249-
~JSBindingsConnection() override {
250-
callback_.Reset();
251-
}
252-
253-
void OnMessage(Local<Value> value) {
254-
MakeCallback(callback_.Get(env()->isolate()), 1, &value);
255-
}
256-
257-
void CheckIsCurrent() {
258-
Agent* inspector = env()->inspector_agent();
259-
CHECK_EQ(&delegate_, inspector->delegate());
260-
}
261-
262-
static void New(const FunctionCallbackInfo<Value>& info) {
263-
Environment* env = Environment::GetCurrent(info);
264-
if (!info[0]->IsFunction()) {
265-
env->ThrowTypeError("Message callback is required");
266-
return;
267-
}
268-
Local<Function> callback = info[0].As<Function>();
269-
new JSBindingsConnection(env, info.This(), callback);
270-
}
271-
272-
void Disconnect() {
273-
delegate_.Disconnect();
274-
if (!persistent().IsEmpty()) {
275-
ClearWrap(object());
276-
persistent().Reset();
277-
}
278-
delete this;
279-
}
280-
281-
static void Disconnect(const FunctionCallbackInfo<Value>& info) {
282-
JSBindingsConnection* session;
283-
ASSIGN_OR_RETURN_UNWRAP(&session, info.Holder());
284-
session->Disconnect();
285-
}
286-
287-
static void Dispatch(const FunctionCallbackInfo<Value>& info) {
288-
Environment* env = Environment::GetCurrent(info);
289-
JSBindingsConnection* session;
290-
ASSIGN_OR_RETURN_UNWRAP(&session, info.Holder());
291-
if (!info[0]->IsString()) {
292-
env->ThrowTypeError("Inspector message must be a string");
293-
return;
294-
}
295-
296-
session->CheckIsCurrent();
297-
Agent* inspector = env->inspector_agent();
298-
inspector->Dispatch(ToProtocolString(env->isolate(), info[0])->string());
299-
}
300-
301-
size_t self_size() const override { return sizeof(*this); }
302-
303-
private:
304-
JSBindingsSessionDelegate delegate_;
305-
Persistent<Function> callback_;
306-
};
307-
308-
void InspectorConsoleCall(const v8::FunctionCallbackInfo<Value>& info) {
309-
Isolate* isolate = info.GetIsolate();
310-
HandleScope handle_scope(isolate);
311-
Local<Context> context = isolate->GetCurrentContext();
312-
CHECK_LT(2, info.Length());
313-
std::vector<Local<Value>> call_args;
314-
for (int i = 3; i < info.Length(); ++i) {
315-
call_args.push_back(info[i]);
316-
}
317-
Environment* env = Environment::GetCurrent(isolate);
318-
if (env->inspector_agent()->enabled()) {
319-
Local<Value> inspector_method = info[0];
320-
CHECK(inspector_method->IsFunction());
321-
Local<Value> config_value = info[2];
322-
CHECK(config_value->IsObject());
323-
Local<Object> config_object = config_value.As<Object>();
324-
Local<String> in_call_key = FIXED_ONE_BYTE_STRING(isolate, "in_call");
325-
if (!config_object->Has(context, in_call_key).FromMaybe(false)) {
326-
CHECK(config_object->Set(context,
327-
in_call_key,
328-
v8::True(isolate)).FromJust());
329-
CHECK(!inspector_method.As<Function>()->Call(context,
330-
info.Holder(),
331-
call_args.size(),
332-
call_args.data()).IsEmpty());
333-
}
334-
CHECK(config_object->Delete(context, in_call_key).FromJust());
335-
}
336-
337-
Local<Value> node_method = info[1];
338-
CHECK(node_method->IsFunction());
339-
node_method.As<Function>()->Call(context,
340-
info.Holder(),
341-
call_args.size(),
342-
call_args.data()).FromMaybe(Local<Value>());
343-
}
344-
345-
void CallAndPauseOnStart(
346-
const v8::FunctionCallbackInfo<v8::Value>& args) {
347-
Environment* env = Environment::GetCurrent(args);
348-
CHECK_GT(args.Length(), 1);
349-
CHECK(args[0]->IsFunction());
350-
std::vector<v8::Local<v8::Value>> call_args;
351-
for (int i = 2; i < args.Length(); i++) {
352-
call_args.push_back(args[i]);
353-
}
354-
355-
env->inspector_agent()->PauseOnNextJavascriptStatement("Break on start");
356-
v8::MaybeLocal<v8::Value> retval =
357-
args[0].As<v8::Function>()->Call(env->context(), args[1],
358-
call_args.size(), call_args.data());
359-
if (!retval.IsEmpty()) {
360-
args.GetReturnValue().Set(retval.ToLocalChecked());
361-
}
362-
}
363183

364184
// Used in NodeInspectorClient::currentTimeMS() below.
365185
const int NANOS_PER_MSEC = 1000000;
@@ -710,20 +530,6 @@ bool Agent::StartIoThread(bool wait_for_connect) {
710530
return true;
711531
}
712532

713-
static void AddCommandLineAPI(
714-
const FunctionCallbackInfo<Value>& info) {
715-
auto env = Environment::GetCurrent(info);
716-
Local<Context> context = env->context();
717-
718-
if (info.Length() != 2 || !info[0]->IsString()) {
719-
return env->ThrowTypeError("inspector.addCommandLineAPI takes "
720-
"exactly 2 arguments: a string and a value.");
721-
}
722-
723-
Local<Object> console_api = env->inspector_console_api_object();
724-
console_api->Set(context, info[0], info[1]).FromJust();
725-
}
726-
727533
void Agent::Stop() {
728534
if (io_ != nullptr) {
729535
io_->Stop();
@@ -842,138 +648,6 @@ void Agent::AllAsyncTasksCanceled() {
842648
client_->AllAsyncTasksCanceled();
843649
}
844650

845-
void Open(const FunctionCallbackInfo<Value>& args) {
846-
Environment* env = Environment::GetCurrent(args);
847-
inspector::Agent* agent = env->inspector_agent();
848-
bool wait_for_connect = false;
849-
850-
if (args.Length() > 0 && args[0]->IsUint32()) {
851-
uint32_t port = args[0]->Uint32Value();
852-
agent->options().set_port(static_cast<int>(port));
853-
}
854-
855-
if (args.Length() > 1 && args[1]->IsString()) {
856-
node::Utf8Value host(env->isolate(), args[1].As<String>());
857-
agent->options().set_host_name(*host);
858-
}
859-
860-
if (args.Length() > 2 && args[2]->IsBoolean()) {
861-
wait_for_connect = args[2]->BooleanValue();
862-
}
863-
864-
agent->StartIoThread(wait_for_connect);
865-
}
866-
867-
void Url(const FunctionCallbackInfo<Value>& args) {
868-
Environment* env = Environment::GetCurrent(args);
869-
inspector::Agent* agent = env->inspector_agent();
870-
inspector::InspectorIo* io = agent->io();
871-
872-
if (!io) return;
873-
874-
std::vector<std::string> ids = io->GetTargetIds();
875-
876-
if (ids.empty()) return;
877-
878-
std::string url = FormatWsAddress(io->host(), io->port(), ids[0], true);
879-
args.GetReturnValue().Set(OneByteString(env->isolate(), url.c_str()));
880-
}
881-
882-
static void* GetAsyncTask(int64_t asyncId) {
883-
// The inspector assumes that when other clients use its asyncTask* API,
884-
// they use real pointers, or at least something aligned like real pointer.
885-
// In general it means that our task_id should always be even.
886-
//
887-
// On 32bit platforms, the 64bit asyncId would get truncated when converted
888-
// to a 32bit pointer. However, the javascript part will never enable
889-
// the async_hook on 32bit platforms, therefore the truncation will never
890-
// happen in practice.
891-
return reinterpret_cast<void*>(asyncId << 1);
892-
}
893-
894-
template<void (Agent::*asyncTaskFn)(void*)>
895-
static void InvokeAsyncTaskFnWithId(const FunctionCallbackInfo<Value>& args) {
896-
Environment* env = Environment::GetCurrent(args);
897-
CHECK(args[0]->IsNumber());
898-
int64_t task_id = args[0]->IntegerValue(env->context()).FromJust();
899-
(env->inspector_agent()->*asyncTaskFn)(GetAsyncTask(task_id));
900-
}
901-
902-
static void AsyncTaskScheduledWrapper(const FunctionCallbackInfo<Value>& args) {
903-
Environment* env = Environment::GetCurrent(args);
904-
905-
CHECK(args[0]->IsString());
906-
Local<String> task_name = args[0].As<String>();
907-
String::Value task_name_value(task_name);
908-
StringView task_name_view(*task_name_value, task_name_value.length());
909-
910-
CHECK(args[1]->IsNumber());
911-
int64_t task_id = args[1]->IntegerValue(env->context()).FromJust();
912-
void* task = GetAsyncTask(task_id);
913-
914-
CHECK(args[2]->IsBoolean());
915-
bool recurring = args[2]->BooleanValue(env->context()).FromJust();
916-
917-
env->inspector_agent()->AsyncTaskScheduled(task_name_view, task, recurring);
918-
}
919-
920-
static void RegisterAsyncHookWrapper(const FunctionCallbackInfo<Value>& args) {
921-
Environment* env = Environment::GetCurrent(args);
922-
923-
CHECK(args[0]->IsFunction());
924-
v8::Local<v8::Function> enable_function = args[0].As<Function>();
925-
CHECK(args[1]->IsFunction());
926-
v8::Local<v8::Function> disable_function = args[1].As<Function>();
927-
env->inspector_agent()->RegisterAsyncHook(env->isolate(),
928-
enable_function, disable_function);
929-
}
930-
931-
static void IsEnabled(const FunctionCallbackInfo<Value>& args) {
932-
Environment* env = Environment::GetCurrent(args);
933-
args.GetReturnValue().Set(env->inspector_agent()->enabled());
934-
}
935-
936-
// static
937-
void Agent::InitInspector(Local<Object> target, Local<Value> unused,
938-
Local<Context> context, void* priv) {
939-
Environment* env = Environment::GetCurrent(context);
940-
{
941-
auto obj = Object::New(env->isolate());
942-
auto null = Null(env->isolate());
943-
CHECK(obj->SetPrototype(context, null).FromJust());
944-
env->set_inspector_console_api_object(obj);
945-
}
946-
947-
Agent* agent = env->inspector_agent();
948-
env->SetMethod(target, "consoleCall", InspectorConsoleCall);
949-
env->SetMethod(target, "addCommandLineAPI", AddCommandLineAPI);
950-
if (agent->debug_options_.wait_for_connect())
951-
env->SetMethod(target, "callAndPauseOnStart", CallAndPauseOnStart);
952-
env->SetMethod(target, "open", Open);
953-
env->SetMethod(target, "url", Url);
954-
955-
env->SetMethod(target, "asyncTaskScheduled", AsyncTaskScheduledWrapper);
956-
env->SetMethod(target, "asyncTaskCanceled",
957-
InvokeAsyncTaskFnWithId<&Agent::AsyncTaskCanceled>);
958-
env->SetMethod(target, "asyncTaskStarted",
959-
InvokeAsyncTaskFnWithId<&Agent::AsyncTaskStarted>);
960-
env->SetMethod(target, "asyncTaskFinished",
961-
InvokeAsyncTaskFnWithId<&Agent::AsyncTaskFinished>);
962-
963-
env->SetMethod(target, "registerAsyncHook", RegisterAsyncHookWrapper);
964-
env->SetMethod(target, "isEnabled", IsEnabled);
965-
966-
auto conn_str = FIXED_ONE_BYTE_STRING(env->isolate(), "Connection");
967-
Local<FunctionTemplate> tmpl =
968-
env->NewFunctionTemplate(JSBindingsConnection::New);
969-
tmpl->InstanceTemplate()->SetInternalFieldCount(1);
970-
tmpl->SetClassName(conn_str);
971-
AsyncWrap::AddWrapMethods(env, tmpl);
972-
env->SetProtoMethod(tmpl, "dispatch", JSBindingsConnection::Dispatch);
973-
env->SetProtoMethod(tmpl, "disconnect", JSBindingsConnection::Disconnect);
974-
target->Set(env->context(), conn_str, tmpl->GetFunction()).ToChecked();
975-
}
976-
977651
void Agent::RequestIoThreadStart() {
978652
// We need to attempt to interrupt V8 flow (in case Node is running
979653
// continuous JS code) and to wake up libuv thread (in case Node is waiting
@@ -993,8 +667,10 @@ void Agent::ContextCreated(Local<Context> context) {
993667
client_->contextCreated(context, name.str());
994668
}
995669

670+
bool Agent::IsWaitingForConnect() {
671+
return debug_options_.wait_for_connect();
672+
}
673+
996674
} // namespace inspector
997675
} // namespace node
998676

999-
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector,
1000-
node::inspector::Agent::InitInspector);

0 commit comments

Comments
 (0)