@@ -50,58 +50,71 @@ void V8ProfilerConnection::DispatchMessage(Local<String> message) {
50
50
session_->Dispatch (ToProtocolString (env ()->isolate (), message)->string ());
51
51
}
52
52
53
- bool V8ProfilerConnection::WriteResult (const char * path, Local<String> result) {
54
- int ret = WriteFileSync (env ()->isolate (), path, result);
53
+ static void WriteResult (Environment* env,
54
+ const char * path,
55
+ Local<String> result) {
56
+ int ret = WriteFileSync (env->isolate (), path, result);
55
57
if (ret != 0 ) {
56
58
char err_buf[128<
8000
/span>];
57
59
uv_err_name_r (ret, err_buf, sizeof (err_buf));
58
60
fprintf (stderr, " %s: Failed to write file %s\n " , err_buf, path);
59
- return false ;
61
+ return ;
60
62
}
61
- Debug (
62
- env (), DebugCategory::INSPECTOR_PROFILER, " Written result to %s\n " , path);
63
- return true ;
63
+ Debug (env, DebugCategory::INSPECTOR_PROFILER, " Written result to %s\n " , path);
64
64
}
65
65
66
- void V8CoverageConnection::OnMessage (const v8_inspector::StringView& message) {
67
- Debug (env (),
66
+ void V8ProfilerConnection::V8ProfilerSessionDelegate::SendMessageToFrontend (
67
+ const v8_inspector::StringView& message) {
68
+ Environment* env = connection_->env ();
69
+ Isolate* isolate = env->isolate ();
70
+ HandleScope handle_scope (isolate);
71
+ Context::Scope context_scope (env->context ());
72
+
73
+ // TODO(joyeecheung): always parse the message so that we can use the id to
74
+ // identify ending messages as well as printing the message in the debug
75
+ // output when there is an error.
76
+ const char * type = connection_->type ();
77
+ Debug (env,
68
78
DebugCategory::INSPECTOR_PROFILER,
69
- " Receive coverage message, ending = %s\n " ,
70
- ending_ ? " true" : " false" );
71
- if (!ending_) {
79
+ " Receive %s profile message, ending = %s\n " ,
80
+ type,
81
+ connection_->ending () ? " true" : " false" );
82
+ if (!connection_->ending ()) {
72
83
return ;
73
84
}
74
- Isolate* isolate = env ()->isolate ();
75
- Local<Context> context = env ()->context ();
76
- HandleScope handle_scope (isolate);
77
- Context::Scope context_scope (context);
78
- Local<String> result;
85
+
86
+ // Convert StringView to a Local<String>.
87
+ Local<String> message_str;
79
88
if (!String::NewFromTwoByte (isolate,
80
89
message.characters16 (),
81
90
NewStringType::kNormal ,
82
91
message.length ())
83
- .ToLocal (&result)) {
84
- fprintf (stderr, " Failed to covert coverage message\n " );
92
+ .ToLocal (&message_str)) {
93
+ fprintf (stderr, " Failed to covert %s profile message\n " , type);
94
+ return ;
85
95
}
86
- WriteCoverage (result);
96
+
97
+ connection_->WriteProfile (message_str);
87
98
}
88
99
89
- bool V8CoverageConnection::WriteCoverage (Local<String> message) {
90
- const std::string& directory = env ()->coverage_directory ();
91
- CHECK (!directory.empty ());
100
+ static bool EnsureDirectory (const std::string& directory, const char * type) {
92
101
uv_fs_t req;
93
102
int ret = fs::MKDirpSync (nullptr , &req, directory, 0777 , nullptr );
94
103
uv_fs_req_cleanup (&req);
95
104
if (ret < 0 && ret != UV_EEXIST) {
96
105
char err_buf[128 ];
97
106
uv_err_name_r (ret, err_buf, sizeof (err_buf));
98
107
fprintf (stderr,
99
- " %s: Failed to create coverage directory %s\n " ,
108
+ " %s: Failed to create %s profile directory %s\n " ,
100
109
err_buf,
110
+ type,
101
111
directory.c_str ());
102
112
return false ;
103
113
}
114
+ return true ;
115
+ }
104
116
117
+ std::string V8CoverageConnection::GetFilename () const {
105
118
std::string thread_id = std::to_string (env ()->thread_id ());
106
119
std::string pid = std::to_string (uv_os_getpid ());
107
120
std::string timestamp = std::to_string (
@@ -113,44 +126,79 @@ bool V8CoverageConnection::WriteCoverage(Local<String> message) {
113
126
pid.c_str (),
114
127
timestamp.c_str (),
115
128
thread_id.c_str ());
116
- std::string target = directory + kPathSeparator + filename;
117
- MaybeLocal<String> result = GetResult (message);
118
- if (result.IsEmpty ()) {
119
- return false ;
120
- }
121
- return WriteResult (target.c_str (), result.ToLocalChecked ());
129
+ return filename;
122
130
}
123
131
124
- MaybeLocal<String> V8CoverageConnection::GetResult (Local<String> message) {
125
- Local<Context> context = env ()->context ();
126
- Isolate* isolate = env ()->isolate ();
132
+ static MaybeLocal<Object> ParseProfile (Environment* env,
133
+ Local<String> message,
134
+ const char * type) {
135
+ Local<Context> context = env->context ();
136
+ Isolate* isolate = env->isolate ();
137
+
138
+ // Get message.result from the response
127
139
Local<Value> parsed;
128
140
if (!v8::JSON::Parse (context, message).ToLocal (&parsed) ||
129
141
!parsed->IsObject ()) {
130
- fprintf (stderr, " Failed to parse coverage result as JSON object\n " );
131
- return MaybeLocal<String >();
142
+ fprintf (stderr, " Failed to parse %s profile result as JSON object\n " , type );
143
+ return MaybeLocal<Object >();
132
144
}
133
145
134
146
Local<Value> result_v;
135
147
if (!parsed.As <Object>()
136
148
->Get (context, FIXED_ONE_BYTE_STRING (isolate, " result" ))
137
149
.ToLocal (&result_v)) {
138
- fprintf (stderr, " Failed to get result from coverage message\n " );
139
- return MaybeLocal<String >();
150
+ fprintf (stderr, " Failed to get ' result' from %s profile message\n " , type );
151
+ return MaybeLocal<Object >();
140
152
}
141
153
142
- if (result_v->IsUndefined ()) {
143
- fprintf (stderr, " 'result' from coverage message is undefined\n " );
144
- return MaybeLocal<String>();
154
+ if (!result_v->IsObject ()) {
155
+ fprintf (
156
+ stderr, " 'result' from %s profile message is not an object\n " , type);
157
+ return MaybeLocal<Object>();
145
158
}
10000
146
159
160
+ return result_v.As <Object>();
161
+ }
162
+
163
+ void V8ProfilerConnection::WriteProfile (Local<String> message) {
164
+ Local<Context> context = env_->context ();
165
+
166
+ // Get message.result from the response.
167
+ Local<Object> result;
168
+ if (!ParseProfile (env_, message, type ()).ToLocal (&result)) {
169
+ return ;
170
+ }
171
+ // Generate the profile output from the subclass.
172
+ Local<Object> profile;
173
+ if (!GetProfile (result).ToLocal (&profile)) {
174
+ return ;
175
+ }
147
176
Local<String> result_s;
148
- if (!v8::JSON::Stringify (context, result_v ).ToLocal (&result_s)) {
149
- fprintf (stderr, " Failed to stringify coverage result\n " );
150
- return MaybeLocal<String>() ;
177
+ if (!v8::JSON::Stringify (context, profile ).ToLocal (&result_s)) {
178
+ fprintf (stderr, " Failed to stringify %s profile result\n " , type () );
179
+ return ;
151
180
}
152
181
153
- return result_s;
182
+ // Create the directory if necessary.
183
+ std::string directory = GetDirectory ();
184
+ DCHECK (!directory.empty ());
185
+ if (!EnsureDirectory (directory, type ())) {
186
+ return ;
187
+ }
188
+
189
+ std::string filename = GetFilename ();
190
+ DCHECK (!filename.empty ());
191
+ std::string path = directory + kPathSeparator + filename;
192
+
193
+ WriteResult (env_, path.c_str (), result_s);
194
+ }
195
+
196
+ MaybeLocal<Object> V8CoverageConnection::GetProfile (Local<Object> result) {
197
+ return result;
198
+ }
199
+
200
+ std::string V8CoverageConnection::GetDirectory () const {
201
+ return env ()->coverage_directory ();
154
202
}
155
203
156
204
void V8CoverageConnection::Start () {
@@ -184,92 +232,28 @@ void V8CoverageConnection::End() {
184
232
DispatchMessage (end);
185
233
}
186
234
187
- void V8CpuProfilerConnection::OnMessage (
188
- const v8_inspector::StringView& message) {
189
- Debug (env (),
190
- DebugCategory::INSPECTOR_PROFILER,
191
- " Receive cpu profiling message, ending = %s\n " ,
192
- ending_ ? " true" : " false" );
193
- if (!ending_) {
194
- return ;
195
- }
196
- Isolate* isolate = env ()->isolate ();
197
- HandleScope handle_scope (isolate);
198
- Local<Context> context = env ()->context ();
199
- Context::Scope context_scope (context);
200
- Local<String> result;
201
- if (!String::NewFromTwoByte (isolate,
202
- message.characters16 (),
203
- NewStringType::kNormal ,
204
- message.length ())
205
- .ToLocal (&result)) {
206
- fprintf (stderr, " Failed to convert profiling message\n " );
207
- }
208
- WriteCpuProfile (result);
235
+ std::string V8CpuProfilerConnection::GetDirectory () const {
236
+ return env ()->cpu_prof_dir ();
209
237
}
210
238
211
- void V8CpuProfilerConnection::WriteCpuProfile (Local<String> message) {
212
- const std::string& filename = env ()->cpu_prof_name ();
213
- const std::string& directory = env ()->cpu_prof_dir ();
214
- CHECK (!filename.empty ());
215
- CHECK (!directory.empty ());
216
- uv_fs_t req;
217
- int ret = fs::MKDirpSync (nullptr , &req, directory, 0777 , nullptr );
218
- uv_fs_req_cleanup (&req);
219
- if (ret < 0 && ret != UV_EEXIST) {
220
- char err_buf[128 ];
221
- uv_err_name_r (ret, err_buf, sizeof (err_buf));
222
- fprintf (stderr,
223
- " %s: Failed to create cpu profile directory %s\n " ,
224
- err_buf,
225
- directory.c_str ());
226
- return ;
227
- }
228
- MaybeLocal<String> result = GetResult (message);
229
- std::string target = directory + kPathSeparator + filename;
230
- if (!result.IsEmpty ()) {
231
- WriteResult (target.c_str (), result.ToLocalChecked ());
232
- }
239
+ std::string V8CpuProfilerConnection::GetFilename () const {
240
+ return env ()->cpu_prof_name ();
233
241
}
234
242
235
- MaybeLocal<String> V8CpuProfilerConnection::GetResult (Local<String> message) {
236
- Local<Context> context = env ()->context ();
237
- Isolate* isolate = env ()->isolate ();
238
- Local<Value> parsed;
239
- if (!v8::JSON::Parse (context, message).ToLocal (&parsed) ||
240
- !parsed->IsObject ()) {
241
- fprintf (stderr, " Failed to parse CPU profile result as JSON object\n " );
242
- return MaybeLocal<String>();
243
- }
244
-
245
- Local<Value> result_v;
246
- if (!parsed.As <Object>()
247
- ->Get (context, FIXED_ONE_BYTE_STRING (isolate, " result" ))
248
- .ToLocal (&result_v)) {
249
- fprintf (stderr, " Failed to get result from CPU profile message\n " );
250
- return MaybeLocal<String>();
251
- }
252
-
253
- if (!result_v->IsObject ()) {
254
- fprintf (stderr, " 'result' from CPU profile message is not an object\n " );
255
- return MaybeLocal<String>();
256
- }
257
-
243
+ MaybeLocal<Object> V8CpuProfilerConnection::GetProfile (Local<Object> result) {
258
244
Local<Value> profile_v;
259
- if (!result_v.As <Object>()
260
- ->Get (context, FIXED_ONE_BYTE_STRING (isolate, " profile" ))
245
+ if (!result
246
+ ->Get (env ()->context (),
247
+ FIXED_ONE_BYTE_STRING (env ()->isolate (), " profile" ))
261
248
.ToLocal (&profile_v)) {
262
249
fprintf (stderr, " 'profile' from CPU profile result is undefined\n " );
263
- return MaybeLocal<String >();
250
+ return MaybeLocal<Object >();
264
251
}
265
-
266
- Local<String> result_s;
267
- if (!v8::JSON::Stringify (context, profile_v).ToLocal (&result_s)) {
268
- fprintf (stderr, " Failed to stringify CPU profile result\n " );
269
- return MaybeLocal<String>();
252
+ if (!profile_v->IsObject ()) {
253
+ fprintf (stderr, " 'profile' from CPU profile result is not an Object\n " );
254
+ return MaybeLocal<Object>();
270
255
}
271
-
272
- return result_s;
256
+ return profile_v.As <Object>();
273
257
}
274
258
275
259
void V8CpuProfilerConnection::Start () {
@@ -298,16 +282,16 @@ void V8CpuProfilerConnection::End() {
298
282
// in the future.
299
283
void EndStartedProfilers (Environment* env) {
300
284
Debug (env, DebugCategory::INSPECTOR_PROFILER, " EndStartedProfilers\n " );
301
- V8ProfilerConnection* connection = env->coverage_connection ();
285
+ V8ProfilerConnection* connection = env->cpu_profiler_connection ();
302
286
if (connection != nullptr && !connection->ending ()) {
303
- Debug (
304
- env, DebugCategory::INSPECTOR_PROFILER, " Ending coverage collection\n " );
287
+ Debug (env, DebugCategory::INSPECTOR_PROFILER, " Ending cpu profiling\n " );
305
288
connection->End ();
306
289
}
307
290
308
- connection = env->cpu_profiler_connection ();
291
+ connection = env->coverage_connection ();
309
292
if (connection != nullptr && !connection->ending ()) {
310
- Debug (env, DebugCategory::INSPECTOR_PROFILER, " Ending cpu profiling\n " );
293
+ Debug (
294
+ env, DebugCategory::INSPECTOR_PROFILER, " Ending coverage collection\n " );
311
295
connection->End ();
312
296
}
313
297
}
0 commit comments