@ -154,8 +154,61 @@ static int RegisterDebugSignalHandler() {
return 0 ;
}
# endif // _WIN32
} // namespace
void InspectorConsoleCall ( const v8 : : FunctionCallbackInfo < Value > & info ) {
Isolate * isolate = info . GetIsolate ( ) ;
HandleScope handle_scope ( isolate ) ;
Local < Context > context = isolate - > GetCurrentContext ( ) ;
CHECK_LT ( 2 , info . Length ( ) ) ;
std : : vector < Local < Value > > call_args ;
for ( int i = 3 ; i < info . Length ( ) ; + + i ) {
call_args . push_back ( info [ i ] ) ;
}
Environment * env = Environment : : GetCurrent ( isolate ) ;
if ( env - > inspector_agent ( ) - > enabled ( ) ) {
Local < Value > inspector_method = info [ 0 ] ;
CHECK ( inspector_method - > IsFunction ( ) ) ;
Local < Value > config_value = info [ 2 ] ;
CHECK ( config_value - > IsObject ( ) ) ;
Local < Object > config_object = config_value . As < Object > ( ) ;
Local < String > in_call_key = FIXED_ONE_BYTE_STRING ( isolate , " in_call " ) ;
if ( ! config_object - > Has ( context , in_call_key ) . FromMaybe ( false ) ) {
CHECK ( config_object - > Set ( context ,
in_call_key ,
v8 : : True ( isolate ) ) . FromJust ( ) ) ;
CHECK ( ! inspector_method . As < Function > ( ) - > Call ( context ,
info . Holder ( ) ,
call_args . size ( ) ,
call_args . data ( ) ) . IsEmpty ( ) ) ;
}
CHECK ( config_object - > Delete ( context , in_call_key ) . FromJust ( ) ) ;
}
Local < Value > node_method = info [ 1 ] ;
CHECK ( node_method - > IsFunction ( ) ) ;
static_cast < void > ( node_method . As < Function > ( ) - > Call ( context ,
info . Holder ( ) ,
call_args . size ( ) ,
call_args . data ( ) ) ) ;
}
void CallAndPauseOnStart (
const v8 : : FunctionCallbackInfo < v8 : : Value > & args ) {
Environment * env = Environment : : GetCurrent ( args ) ;
CHECK_GT ( args . Length ( ) , 1 ) ;
CHECK ( args [ 0 ] - > IsFunction ( ) ) ;
std : : vector < v8 : : Local < v8 : : Value > > call_args ;
for ( int i = 2 ; i < args . Length ( ) ; i + + ) {
call_args . push_back ( args [ i ] ) ;
}
env - > inspector_agent ( ) - > PauseOnNextJavascriptStatement ( " Break on start " ) ;
v8 : : MaybeLocal < v8 : : Value > retval =
args [ 0 ] . As < v8 : : Function > ( ) - > Call ( env - > context ( ) , args [ 1 ] ,
call_args . size ( ) , call_args . data ( ) ) ;
args . GetReturnValue ( ) . Set ( retval . ToLocalChecked ( ) ) ;
}
} // namespace
// Used in NodeInspectorClient::currentTimeMS() below.
const int NANOS_PER_MSEC = 1000000 ;
@ -263,12 +316,6 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient {
channel_ - > dispatchProtocolMessage ( message ) ;
}
void schedulePauseOnNextStatement ( const std : : string & reason ) {
if ( channel_ ! = nullptr ) {
channel_ - > schedulePauseOnNextStatement ( reason ) ;
}
}
Local < Context > ensureDefaultContextInGroup ( int contextGroupId ) override {
return env_ - > context ( ) ;
}
@ -302,10 +349,8 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient {
script_id ) ;
}
InspectorSessionDelegate * delegate ( ) {
if ( channel_ = = nullptr )
return nullptr ;
return channel_ - > delegate ( ) ;
ChannelImpl * channel ( ) {
return channel_ . get ( ) ;
}
private :
@ -320,98 +365,22 @@ class NodeInspectorClient : public v8_inspector::V8InspectorClient {
Agent : : Agent ( Environment * env ) : parent_env_ ( env ) ,
inspector_ ( nullptr ) ,
platform_ ( nullptr ) ,
inspector_console _( false ) { }
enabled _( false ) { }
// Header has unique_ptr to some incomplete types - this definition tells
// the compiler to figure out destruction here, were those types are complete
// Destructor needs to be defined here in implementation file as the header
// does not have full definition of some classes.
Agent : : ~ Agent ( ) {
}
// static
void Agent : : InspectorConsoleCall ( const v8 : : FunctionCallbackInfo < Value > & info ) {
Isolate * isolate = info . GetIsolate ( ) ;
Local < Context > context = isolate - > GetCurrentContext ( ) ;
CHECK ( info . Data ( ) - > IsArray ( ) ) ;
Local < v8 : : Array > args = info . Data ( ) . As < v8 : : Array > ( ) ;
CHECK_EQ ( args - > Length ( ) , 3 ) ;
std : : vector < Local < Value > > call_args ( info . Length ( ) ) ;
for ( int i = 0 ; i < info . Length ( ) ; + + i ) {
call_args [ i ] = info [ i ] ;
}
Environment * env = Environment : : GetCurrent ( isolate ) ;
if ( env - > inspector_agent ( ) - > inspector_console_ ) {
Local < Value > inspector_method = args - > Get ( context , 0 ) . ToLocalChecked ( ) ;
CHECK ( inspector_method - > IsFunction ( ) ) ;
Local < Value > config_value = args - > Get ( context , 2 ) . ToLocalChecked ( ) ;
CHECK ( config_value - > IsObject ( ) ) ;
Local < Object > config_object = config_value . As < Object > ( ) ;
Local < String > in_call_key = FIXED_ONE_BYTE_STRING ( isolate , " in_call " ) ;
if ( ! config_object - > Has ( context , in_call_key ) . FromMaybe ( false ) ) {
CHECK ( config_object - > Set ( context ,
in_call_key ,
v8 : : True ( isolate ) ) . FromJust ( ) ) ;
CHECK ( ! inspector_method . As < Function > ( ) - > Call ( context ,
info . Holder ( ) ,
call_args . size ( ) ,
call_args . data ( ) ) . IsEmpty ( ) ) ;
}
CHECK ( config_object - > Delete ( context , in_call_key ) . FromJust ( ) ) ;
}
Local < Value > node_method =
args - > Get ( context , 1 ) . ToLocalChecked ( ) ;
CHECK ( node_method - > IsFunction ( ) ) ;
static_cast < void > ( node_method . As < Function > ( ) - > Call ( context ,
info . Holder ( ) ,
call_args . size ( ) ,
call_args . data ( ) ) ) ;
}
// static
void Agent : : InspectorWrapConsoleCall ( const FunctionCallbackInfo < Value > & info ) {
Environment * env = Environment : : GetCurrent ( info ) ;
if ( info . Length ( ) ! = 3 | | ! info [ 0 ] - > IsFunction ( ) | |
! info [ 1 ] - > IsFunction ( ) | | ! info [ 2 ] - > IsObject ( ) ) {
return env - > ThrowError ( " inspector.wrapConsoleCall takes exactly 3 "
" arguments: two functions and an object. " ) ;
}
Local < v8 : : Array > array = v8 : : Array : : New ( env - > isolate ( ) , info . Length ( ) ) ;
CHECK ( array - > Set ( env - > context ( ) , 0 , info [ 0 ] ) . FromJust ( ) ) ;
CHECK ( array - > Set ( env - > context ( ) , 1 , info [ 1 ] ) . FromJust ( ) ) ;
CHECK ( array - > Set ( env - > context ( ) , 2 , info [ 2 ] ) . FromJust ( ) ) ;
info . GetReturnValue ( ) . Set ( Function : : New ( env - > context ( ) ,
InspectorConsoleCall ,
array ) . ToLocalChecked ( ) ) ;
}
bool Agent : : Start ( v8 : : Platform * platform , const char * path ,
const DebugOptions & options ) {
path_ = path = = nullptr ? " " : path ;
debug_options_ = options ;
inspector_console_ = false ;
inspector_ =
std : : unique_ptr < NodeInspectorClient > (
new NodeInspectorClient ( parent_env_ , platform ) ) ;
platform_ = platform ;
Local < Object > process = parent_env_ - > process_object ( ) ;
Local < Object > inspector = Object : : New ( parent_env_ - > isolate ( ) ) ;
Local < String > name =
FIXED_ONE_BYTE_STRING ( parent_env_ - > isolate ( ) , " inspector " ) ;
process - > DefineOwnProperty ( parent_env_ - > context ( ) ,
name ,
inspector ,
v8 : : ReadOnly ) . FromJust ( ) ;
parent_env_ - > SetMethod ( inspector , " wrapConsoleCall " ,
InspectorWrapConsoleCall ) ;
if ( options . inspector_enabled ( ) ) {
if ( options . wait_for_connect ( ) ) {
parent_env_ - > SetMethod ( inspector , " callAndPauseOnStart " ,
CallAndPauseOnStart ) ;
}
return StartIoThread ( ) ;
} else {
CHECK_EQ ( 0 , uv_async_init ( uv_default_loop ( ) ,
@ -431,7 +400,7 @@ bool Agent::StartIoThread() {
CHECK_NE ( inspector_ , nullptr ) ;
inspector_console _ = true ;
enabled _ = true ;
io_ = std : : unique_ptr < InspectorIo > (
new InspectorIo ( parent_env_ , platform_ , path_ , debug_options_ ) ) ;
if ( ! io_ - > Start ( ) ) {
@ -469,7 +438,7 @@ void Agent::Stop() {
}
void Agent : : Connect ( InspectorSessionDelegate * delegate ) {
inspector_console _ = true ;
enabled _ = true ;
inspector_ - > connectFrontend ( delegate ) ;
}
@ -481,26 +450,6 @@ bool Agent::IsStarted() {
return ! ! inspector_ ;
}
// static
void Agent : : CallAndPauseOnStart (
const v8 : : FunctionCallbackInfo < v8 : : Value > & args ) {
Environment * env = Environment : : GetCurrent ( args ) ;
CHECK_GT ( args . Length ( ) , 1 ) ;
CHECK ( args [ 0 ] - > IsFunction ( ) ) ;
std : : vector < v8 : : Local < v8 : : Value > > call_args ;
for ( int i = 2 ; i < args . Length ( ) ; i + + ) {
call_args . push_back ( args [ i ] ) ;
}
Agent * agent = env - > inspector_agent ( ) ;
agent - > inspector_ - > schedulePauseOnNextStatement ( " Break on start " ) ;
v8 : : MaybeLocal < v8 : : Value > retval =
args [ 0 ] . As < v8 : : Function > ( ) - > Call ( env - > context ( ) , args [ 1 ] ,
call_args . size ( ) , call_args . data ( ) ) ;
args . GetReturnValue ( ) . Set ( retval . ToLocalChecked ( ) ) ;
}
void Agent : : WaitForDisconnect ( ) {
if ( io_ ! = nullptr ) {
io_ - > WaitForDisconnect ( ) ;
@ -529,5 +478,23 @@ void Agent::RunMessageLoop() {
inspector_ - > runMessageLoopOnPause ( CONTEXT_GROUP_ID ) ;
}
void Agent : : PauseOnNextJavascriptStatement ( const std : : string & reason ) {
ChannelImpl * channel = inspector_ - > channel ( ) ;
if ( channel ! = nullptr )
channel - > schedulePauseOnNextStatement ( reason ) ;
}
// static
void Agent : : InitJSBindings ( Local < Object > target , Local < Value > unused ,
Local < Context > context , void * priv ) {
Environment * env = Environment : : GetCurrent ( context ) ;
Agent * agent = env - > inspector_agent ( ) ;
env - > SetMethod ( target , " consoleCall " , InspectorConsoleCall ) ;
if ( agent - > debug_options_ . wait_for_connect ( ) )
env - > SetMethod ( target , " callAndPauseOnStart " , CallAndPauseOnStart ) ;
}
} // namespace inspector
} // namespace node
NODE_MODULE_CONTEXT_AWARE_BUILTIN ( inspector ,
node : : inspector : : Agent : : InitJSBindings ) ;