1
1
#include " inspector_agent.h"
2
2
3
3
#include " inspector_io.h"
4
+ #include " base-object.h"
5
+ #include " base-object-inl.h"
4
6
#include " node_internals.h"
5
7
#include " v8-inspector.h"
6
8
#include " v8-platform.h"
@@ -26,9 +28,9 @@ using node::FatalError;
26
28
using v8::Array;
27
29
using v8::Boolean;
28
30
using v8::Context;
29
- using v8::External;
30
31
using v8::Function;
31
32
using v8::FunctionCallbackInfo;
33
+ using v8::FunctionTemplate;
32
34
using v8::HandleScope;
33
35
using v8::Integer;
34
36
using v8::Isolate;
@@ -191,143 +193,117 @@ static int StartDebugSignalHandler() {
191
193
}
192
194
#endif // _WIN32
193
195
194
- class JsBindingsSessionDelegate : public InspectorSessionDelegate {
196
+ class JSBindingsConnection : public AsyncWrap {
195
197
public:
196
- JsBindingsSessionDelegate (Environment* env,
197
- Local<Object> session,
198
- Local<Object> receiver,
199
- Local<Function> callback)
200
- : env_(env),
201
- session_ (env->isolate (), session),
202
- receiver_(env->isolate (), receiver),
203
- callback_(env->isolate (), callback) {
204
- session_.SetWeak (this , JsBindingsSessionDelegate::Release,
205
- v8::WeakCallbackType::kParameter );
206
- }
207
-
208
- ~JsBindingsSessionDelegate () override {
209
- session_.Reset ();
210
- receiver_.Reset ();
211
- callback_.Reset ();
212
- }
198
+ class JSBindingsSessionDelegate : public InspectorSessionDelegate {
199
+ public:
200
+ JSBindingsSessionDelegate (Environment* env,
201
+ JSBindingsConnection* connection)
202
+ : env_(env),
203
+ connection_ (connection) {
204
+ }
213
205
214
- bool WaitForFrontendMessageWhilePaused () override {
215
- return false ;
216
- }
206
+ bool WaitForFrontendMessageWhilePaused () override {
207
+ return false ;
208
+ }
217
209
218
- void SendMessageToFrontend (const v8_inspector::StringView& message) override {
219
- Isolate* isolate = env_->isolate ();
220
- v8::HandleScope handle_scope (isolate);
221
- Context::Scope context_scope (env_->context ());
222
- MaybeLocal<String> v8string =
223
- String::NewFromTwoByte (isolate, message.characters16 (),
224
- NewStringType::kNormal , message.length ());
225
- Local<Value> argument = v8string.ToLocalChecked ().As <Value>();
226
- Local<Function> callback = callback_.Get (isolate);
227
- Local<Object> receiver = receiver_.Get (isolate);
228
- callback->Call (env_->context (), receiver, 1 , &argument)
229
- .FromMaybe (Local<Value>());
230
- }
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
+ }
231
221
232
- void Disconnect () {
233
- Agent* agent = env_->inspector_agent ();
234
- if (agent->delegate () == this )
235
- agent->Disconnect ();
236
- }
222
+ void Disconnect () {
223
+ Agent* agent = env_->inspector_agent ();
224
+ if (agent->delegate () == this )
225
+ agent->Disconnect ();
226
+ }
237
227
238
- private:
239
- static void Release (
240
- const v8::WeakCallbackInfo<JsBindingsSessionDelegate>& info) {
241
- info.SetSecondPassCallback (ReleaseSecondPass);
242
- info.GetParameter ()->session_ .Reset ();
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_);
243
247
}
244
248
245
- static void ReleaseSecondPass (
246
- const v8::WeakCallbackInfo<JsBindingsSessionDelegate>& info) {
247
- JsBindingsSessionDelegate* delegate = info.GetParameter ();
248
- delegate->Disconnect ();
249
- delete delegate;
249
+ ~JSBindingsConnection () override {
250
+ callback_.Reset ();
250
251
}
251
252
252
- Environment* env_;
253
- Persistent<Object> session_;
254
- Persistent<Object> receiver_;
255
- Persistent<Function> callback_;
256
- };
253
+ void OnMessage (Local<Value> value) {
254
+ MakeCallback (callback_.Get (env ()->isolate ()), 1 , &value);
255
+ }
257
256
258
- void SetDelegate (Environment* env, Local<Object> inspector,
259
- JsBindingsSessionDelegate* delegate) {
260
- inspector->SetPrivate (env->context (),
261
- env->inspector_delegate_private_symbol (),
262
- v8::External::New (env->isolate (), delegate));
263
- }
257
+ void CheckIsCurrent () {
258
+ Agent* inspector = env ()->inspector_agent ();
259
+ CHECK_EQ (&delegate_, inspector->delegate ());
260
+ }
264
261
265
- Maybe<JsBindingsSessionDelegate*> GetDelegate (
266
- const FunctionCallbackInfo<Value>& info) {
267
- Environment* env = Environment::GetCurrent (info);
268
- Local<Value> delegate;
269
- MaybeLocal<Value> maybe_delegate =
270
- info.This ()->GetPrivate (env->context (),
271
- env->inspector_delegate_private_symbol ());
272
-
273
- if (maybe_delegate.ToLocal (&delegate)) {
274
- CHECK (delegate->IsExternal ());
275
- void * value = delegate.As <External>()->Value ();
276
- if (value != nullptr ) {
277
- return v8::Just (static_cast <JsBindingsSessionDelegate*>(value));
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 ;
278
267
}
268
+ Local<Function> callback = info[0 ].As <Function>();
269
+ new JSBindingsConnection (env, info.This (), callback);
279
270
}
280
- env->ThrowError (" Inspector is not connected" );
281
- return v8::Nothing<JsBindingsSessionDelegate*>();
282
- }
283
271
284
- void Dispatch (const FunctionCallbackInfo<Value>& info) {
285
- Environment* env = Environment::GetCurrent (info);
286
- if (!info[0 ]->IsString ()) {
287
- env->ThrowError (" Inspector message must be a string" );
288
- return ;
272
+ void Disconnect () {
273
+ delegate_.Disconnect ();
274
+ if (!persistent ().IsEmpty ()) {
275
+ ClearWrap (object ());
276
+ persistent ().Reset ();
277
+ }
278
+ delete this ;
289
279
}
290
- Maybe<JsBindingsSessionDelegate*> maybe_delegate = GetDelegate (info);
291
- if (maybe_delegate.IsNothing ())
292
- return ;
293
- Agent* inspector = env->inspector_agent ();
294
- CHECK_EQ (maybe_delegate.ToChecked (), inspector->delegate ());
295
- inspector->Dispatch (ToProtocolString (env->isolate (), info[0 ])->string ());
296
- }
297
280
298
- void Disconnect (const FunctionCallbackInfo<Value>& info) {
299
- Environment* env = Environment::GetCurrent (info);
300
- Maybe<JsBindingsSessionDelegate*> delegate = GetDelegate (info);
301
- if (delegate.IsNothing ()) {
302
- return ;
281
+ static void Disconnect (const FunctionCallbackInfo<Value>& info) {
282
+ JSBindingsConnection* session;
283
+ ASSIGN_OR_RETURN_UNWRAP (&session, info.Holder ());
284
+ session->Disconnect ();
303
285
}
304
- delegate.ToChecked ()->Disconnect ();
305
- SetDelegate (env, info.This (), nullptr );
306
- delete delegate.ToChecked ();
307
- }
308
286
309
- void ConnectJSBindingsSession (const FunctionCallbackInfo<Value>& info) {
310
- Environment* env = Environment::GetCurrent (info);
311
- if (!info[0 ]->IsFunction ()) {
312
- env->ThrowError (" Message callback is required" );
313
- return ;
314
- }
315
- Agent* inspector = env->inspector_agent ();
316
- if (inspector->delegate () != nullptr ) {
317
- env->ThrowError (" Session is already attached" );
318
- return ;
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 ());
319
299
}
320
- Local<Object> session = Object::New (env->isolate ());
321
- env->SetMethod (session, " dispatch" , Dispatch);
322
- env->SetMethod (session, " disconnect" , Disconnect);
323
- info.GetReturnValue ().Set (session);
324
300
325
- JsBindingsSessionDelegate* delegate =
326
- new JsBindingsSessionDelegate (env, session, info. Holder (),
327
- info[ 0 ]. As <Function>());
328
- inspector-> Connect (delegate) ;
329
- SetDelegate (env, session, delegate) ;
330
- }
301
+ size_t self_size () const override { return sizeof (* this ); }
302
+
303
+ private:
304
+ JSBindingsSessionDelegate delegate_ ;
305
+ Persistent<Function> callback_ ;
306
+ };
331
307
332
308
void InspectorConsoleCall (const v8::FunctionCallbackInfo<Value>& info) {
333
309
Isolate* isolate = info.GetIsolate ();
@@ -973,7 +949,6 @@ void Agent::InitInspector(Local<Object> target, Local<Value> unused,
973
949
env->SetMethod (target, " addCommandLineAPI" , AddCommandLineAPI);
974
950
if (agent->debug_options_ .wait_for_connect ())
975
951
env->SetMethod (target, " callAndPauseOnStart" , CallAndPauseOnStart);
976
- env->SetMethod (target, " connect" , ConnectJSBindingsSession);
977
952
env->SetMethod (target, " open" , Open);
978
953
env->SetMethod (target, " url" , Url);
979
954
@@ -987,6 +962,16 @@ void Agent::InitInspector(Local<Object> target, Local<Value> unused,
987
962
988
963
env->SetMethod (target, " registerAsyncHook" , RegisterAsyncHookWrapper);
989
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 ();
990
975
}
991
976
992
977
void Agent::RequestIoThreadStart () {
0 commit comments