Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: src/inspector/V8RuntimeAgentImpl.cpp

Issue 2292573002: [inspector] Initial import of v8_inspector. (Closed)
Patch Set: format the code, disable cpplint Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/inspector/V8RuntimeAgentImpl.h ('k') | src/inspector/V8SchemaAgentImpl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "src/inspector/V8RuntimeAgentImpl.h"
32
33 #include "src/inspector/InjectedScript.h"
34 #include "src/inspector/InspectedContext.h"
35 #include "src/inspector/RemoteObjectId.h"
36 #include "src/inspector/StringUtil.h"
37 #include "src/inspector/V8Compat.h"
38 #include "src/inspector/V8ConsoleMessage.h"
39 #include "src/inspector/V8Debugger.h"
40 #include "src/inspector/V8DebuggerAgentImpl.h"
41 #include "src/inspector/V8InspectorImpl.h"
42 #include "src/inspector/V8InspectorSessionImpl.h"
43 #include "src/inspector/V8StackTraceImpl.h"
44 #include "src/inspector/protocol/Protocol.h"
45 #include "src/inspector/public/V8InspectorClient.h"
46
47 namespace v8_inspector {
48
49 namespace V8RuntimeAgentImplState {
50 static const char customObjectFormatterEnabled[] =
51 "customObjectFormatterEnabled";
52 static const char runtimeEnabled[] = "runtimeEnabled";
53 };
54
55 using protocol::Runtime::RemoteObject;
56
57 static bool hasInternalError(ErrorString* errorString, bool hasError) {
58 if (hasError) *errorString = "Internal error";
59 return hasError;
60 }
61
62 namespace {
63
64 template <typename Callback>
65 class ProtocolPromiseHandler {
66 public:
67 static void add(V8InspectorImpl* inspector, v8::Local<v8::Context> context,
68 v8::MaybeLocal<v8::Value> value,
69 const String16& notPromiseError, int contextGroupId,
70 int executionContextId, const String16& objectGroup,
71 bool returnByValue, bool generatePreview,
72 std::unique_ptr<Callback> callback) {
73 if (value.IsEmpty()) {
74 callback->sendFailure("Internal error");
75 return;
76 }
77 if (!value.ToLocalChecked()->IsPromise()) {
78 callback->sendFailure(notPromiseError);
79 return;
80 }
81 v8::Local<v8::Promise> promise =
82 v8::Local<v8::Promise>::Cast(value.ToLocalChecked());
83 Callback* rawCallback = callback.get();
84 ProtocolPromiseHandler<Callback>* handler = new ProtocolPromiseHandler(
85 inspector, contextGroupId, executionContextId, objectGroup,
86 returnByValue, generatePreview, std::move(callback));
87 v8::Local<v8::Value> wrapper = handler->m_wrapper.Get(inspector->isolate());
88
89 v8::Local<v8::Function> thenCallbackFunction =
90 V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, thenCallback, wrapper, 0)
91 .ToLocalChecked();
92 if (promise->Then(context, thenCallbackFunction).IsEmpty()) {
93 rawCallback->sendFailure("Internal error");
94 return;
95 }
96 v8::Local<v8::Function> catchCallbackFunction =
97 V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, catchCallback, wrapper, 0)
98 .ToLocalChecked();
99 if (promise->Catch(context, catchCallbackFunction).IsEmpty()) {
100 rawCallback->sendFailure("Internal error");
101 return;
102 }
103 }
104
105 private:
106 static void thenCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
107 ProtocolPromiseHandler<Callback>* handler =
108 static_cast<ProtocolPromiseHandler<Callback>*>(
109 info.Data().As<v8::External>()->Value());
110 DCHECK(handler);
111 v8::Local<v8::Value> value =
112 info.Length() > 0
113 ? info[0]
114 : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()));
115 handler->m_callback->sendSuccess(
116 handler->wrapObject(value),
117 Maybe<protocol::Runtime::ExceptionDetails>());
118 }
119
120 static void catchCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
121 ProtocolPromiseHandler<Callback>* handler =
122 static_cast<ProtocolPromiseHandler<Callback>*>(
123 info.Data().As<v8::External>()->Value());
124 DCHECK(handler);
125 v8::Local<v8::Value> value =
126 info.Length() > 0
127 ? info[0]
128 : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()));
129
130 std::unique_ptr<V8StackTraceImpl> stack =
131 handler->m_inspector->debugger()->captureStackTrace(true);
132 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
133 protocol::Runtime::ExceptionDetails::create()
134 .setExceptionId(handler->m_inspector->nextExceptionId())
135 .setText("Uncaught (in promise)")
136 .setLineNumber(stack && !stack->isEmpty() ? stack->topLineNumber()
137 : 0)
138 .setColumnNumber(
139 stack && !stack->isEmpty() ? stack->topColumnNumber() : 0)
140 .setException(handler->wrapObject(value))
141 .build();
142 if (stack)
143 exceptionDetails->setStackTrace(stack->buildInspectorObjectImpl());
144 if (stack && !stack->isEmpty())
145 exceptionDetails->setScriptId(toString16(stack->topScriptId()));
146 handler->m_callback->sendSuccess(handler->wrapObject(value),
147 std::move(exceptionDetails));
148 }
149
150 ProtocolPromiseHandler(V8InspectorImpl* inspector, int contextGroupId,
151 int executionContextId, const String16& objectGroup,
152 bool returnByValue, bool generatePreview,
153 std::unique_ptr<Callback> callback)
154 : m_inspector(inspector),
155 m_contextGroupId(contextGroupId),
156 m_executionContextId(executionContextId),
157 m_objectGroup(objectGroup),
158 m_returnByValue(returnByValue),
159 m_generatePreview(generatePreview),
160 m_callback(std::move(callback)),
161 m_wrapper(inspector->isolate(),
162 v8::External::New(inspector->isolate(), this)) {
163 m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter);
164 }
165
166 static void cleanup(
167 const v8::WeakCallbackInfo<ProtocolPromiseHandler<Callback>>& data) {
168 if (!data.GetParameter()->m_wrapper.IsEmpty()) {
169 data.GetParameter()->m_wrapper.Reset();
170 data.SetSecondPassCallback(cleanup);
171 } else {
172 data.GetParameter()->m_callback->sendFailure("Promise was collected");
173 delete data.GetParameter();
174 }
175 }
176
177 std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(
178 v8::Local<v8::Value> value) {
179 ErrorString errorString;
180 InjectedScript::ContextScope scope(&errorString, m_inspector,
181 m_contextGroupId, m_executionContextId);
182 if (!scope.initialize()) {
183 m_callback->sendFailure(errorString);
184 return nullptr;
185 }
186 std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue =
187 scope.injectedScript()->wrapObject(&errorString, value, m_objectGroup,
188 m_returnByValue, m_generatePreview);
189 if (!wrappedValue) {
190 m_callback->sendFailure(errorString);
191 return nullptr;
192 }
193 return wrappedValue;
194 }
195
196 V8InspectorImpl* m_inspector;
197 int m_contextGroupId;
198 int m_executionContextId;
199 String16 m_objectGroup;
200 bool m_returnByValue;
201 bool m_generatePreview;
202 std::unique_ptr<Callback> m_callback;
203 v8::Global<v8::External> m_wrapper;
204 };
205
206 template <typename Callback>
207 bool wrapEvaluateResultAsync(InjectedScript* injectedScript,
208 v8::MaybeLocal<v8::Value> maybeResultValue,
209 const v8::TryCatch& tryCatch,
210 const String16& objectGroup, bool returnByValue,
211 bool generatePreview, Callback* callback) {
212 std::unique_ptr<RemoteObject> result;
213 Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails;
214
215 ErrorString errorString;
216 injectedScript->wrapEvaluateResult(
217 &errorString, maybeResultValue, tryCatch, objectGroup, returnByValue,
218 generatePreview, &result, &exceptionDetails);
219 if (errorString.isEmpty()) {
220 callback->sendSuccess(std::move(result), exceptionDetails);
221 return true;
222 }
223 callback->sendFailure(errorString);
224 return false;
225 }
226
227 int ensureContext(ErrorString* errorString, V8InspectorImpl* inspector,
228 int contextGroupId, const Maybe<int>& executionContextId) {
229 int contextId;
230 if (executionContextId.isJust()) {
231 contextId = executionContextId.fromJust();
232 } else {
233 v8::HandleScope handles(inspector->isolate());
234 v8::Local<v8::Context> defaultContext =
235 inspector->client()->ensureDefaultContextInGroup(contextGroupId);
236 if (defaultContext.IsEmpty()) {
237 *errorString = "Cannot find default execution context";
238 return 0;
239 }
240 contextId = V8Debugger::contextId(defaultContext);
241 }
242 return contextId;
243 }
244
245 } // namespace
246
247 V8RuntimeAgentImpl::V8RuntimeAgentImpl(
248 V8InspectorSessionImpl* session, protocol::FrontendChannel* FrontendChannel,
249 protocol::DictionaryValue* state)
250 : m_session(session),
251 m_state(state),
252 m_frontend(FrontendChannel),
253 m_inspector(session->inspector()),
254 m_enabled(false) {}
255
256 V8RuntimeAgentImpl::~V8RuntimeAgentImpl() {}
257
258 void V8RuntimeAgentImpl::evaluate(
259 const String16& expression, const Maybe<String16>& objectGroup,
260 const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& silent,
261 const Maybe<int>& executionContextId, const Maybe<bool>& returnByValue,
262 const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture,
263 const Maybe<bool>& awaitPromise,
264 std::unique_ptr<EvaluateCallback> callback) {
265 ErrorString errorString;
266 int contextId =
267 ensureContext(&errorString, m_inspector, m_session->contextGroupId(),
268 executionContextId);
269 if (!errorString.isEmpty()) {
270 callback->sendFailure(errorString);
271 return;
272 }
273
274 InjectedScript::ContextScope scope(&errorString, m_inspector,
275 m_session->contextGroupId(), contextId);
276 if (!scope.initialize()) {
277 callback->sendFailure(errorString);
278 return;
279 }
280
281 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
282 if (userGesture.fromMaybe(false)) scope.pretendUserGesture();
283
284 if (includeCommandLineAPI.fromMaybe(false) &&
285 !scope.installCommandLineAPI()) {
286 callback->sendFailure(errorString);
287 return;
288 }
289
290 bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed();
291 // Temporarily enable allow evals for inspector.
292 if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(true);
293
294 v8::MaybeLocal<v8::Value> maybeResultValue;
295 v8::Local<v8::Script> script = m_inspector->compileScript(
296 scope.context(), toV8String(m_inspector->isolate(), expression),
297 String16(), false);
298 if (!script.IsEmpty())
299 maybeResultValue = m_inspector->runCompiledScript(scope.context(), script);
300
301 if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(false);
302
303 // Re-initialize after running client's code, as it could have destroyed
304 // context or session.
305 if (!scope.initialize()) {
306 callback->sendFailure(errorString);
307 return;
308 }
309
310 if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
311 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
312 scope.tryCatch(), objectGroup.fromMaybe(""),
313 returnByValue.fromMaybe(false),
314 generatePreview.fromMaybe(false), callback.get());
315 return;
316 }
317 ProtocolPromiseHandler<EvaluateCallback>::add(
318 m_inspector, scope.context(), maybeResultValue,
319 "Result of the evaluation is not a promise", m_session->contextGroupId(),
320 scope.injectedScript()->context()->contextId(), objectGroup.fromMaybe(""),
321 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
322 std::move(callback));
323 }
324
325 void V8RuntimeAgentImpl::awaitPromise(
326 const String16& promiseObjectId, const Maybe<bool>& returnByValue,
327 const Maybe<bool>& generatePreview,
328 std::unique_ptr<AwaitPromiseCallback> callback) {
329 ErrorString errorString;
330 InjectedScript::ObjectScope scope(
331 &errorString, m_inspector, m_session->contextGroupId(), promiseObjectId);
332 if (!scope.initialize()) {
333 callback->sendFailure(errorString);
334 return;
335 }
336 ProtocolPromiseHandler<AwaitPromiseCallback>::add(
337 m_inspector, scope.context(), scope.object(),
338 "Could not find promise with given id", m_session->contextGroupId(),
339 scope.injectedScript()->context()->contextId(), scope.objectGroupName(),
340 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
341 std::move(callback));
342 }
343
344 void V8RuntimeAgentImpl::callFunctionOn(
345 const String16& objectId, const String16& expression,
346 const Maybe<protocol::Array<protocol::Runtime::CallArgument>>&
347 optionalArguments,
348 const Maybe<bool>& silent, const Maybe<bool>& returnByValue,
349 const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture,
350 const Maybe<bool>& awaitPromise,
351 std::unique_ptr<CallFunctionOnCallback> callback) {
352 ErrorString errorString;
353 InjectedScript::ObjectScope scope(&errorString, m_inspector,
354 m_session->contextGroupId(), objectId);
355 if (!scope.initialize()) {
356 callback->sendFailure(errorString);
357 return;
358 }
359
360 std::unique_ptr<v8::Local<v8::Value>[]> argv = nullptr;
361 int argc = 0;
362 if (optionalArguments.isJust()) {
363 protocol::Array<protocol::Runtime::CallArgument>* arguments =
364 optionalArguments.fromJust();
365 argc = arguments->length();
366 argv.reset(new v8::Local<v8::Value>[argc]);
367 for (int i = 0; i < argc; ++i) {
368 v8::Local<v8::Value> argumentValue;
369 if (!scope.injectedScript()
370 ->resolveCallArgument(&errorString, arguments->get(i))
371 .ToLocal(&argumentValue)) {
372 callback->sendFailure(errorString);
373 return;
374 }
375 argv[i] = argumentValue;
376 }
377 }
378
379 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
380 if (userGesture.fromMaybe(false)) scope.pretendUserGesture();
381
382 v8::MaybeLocal<v8::Value> maybeFunctionValue =
383 m_inspector->compileAndRunInternalScript(
384 scope.context(),
385 toV8String(m_inspector->isolate(), "(" + expression + ")"));
386 // Re-initialize after running client's code, as it could have destroyed
387 // context or session.
388 if (!scope.initialize()) {
389 callback->sendFailure(errorString);
390 return;
391 }
392
393 if (scope.tryCatch().HasCaught()) {
394 wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue,
395 scope.tryCatch(), scope.objectGroupName(), false,
396 false, callback.get());
397 return;
398 }
399
400 v8::Local<v8::Value> functionValue;
401 if (!maybeFunctionValue.ToLocal(&functionValue) ||
402 !functionValue->IsFunction()) {
403 callback->sendFailure("Given expression does not evaluate to a function");
404 return;
405 }
406
407 v8::MaybeLocal<v8::Value> maybeResultValue = m_inspector->callFunction(
408 functionValue.As<v8::Function>(), scope.context(), scope.object(), argc,
409 argv.get());
410 // Re-initialize after running client's code, as it could have destroyed
411 // context or session.
412 if (!scope.initialize()) {
413 callback->sendFailure(errorString);
414 return;
415 }
416
417 if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
418 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
419 scope.tryCatch(), scope.objectGroupName(),
420 returnByValue.fromMaybe(false),
421 generatePreview.fromMaybe(false), callback.get());
422 return;
423 }
424
425 ProtocolPromiseHandler<CallFunctionOnCallback>::add(
426 m_inspector, scope.context(), maybeResultValue,
427 "Result of the function call is not a promise",
428 m_session->contextGroupId(),
429 scope.injectedScript()->context()->contextId(), scope.objectGroupName(),
430 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
431 std::move(callback));
432 }
433
434 void V8RuntimeAgentImpl::getProperties(
435 ErrorString* errorString, const String16& objectId,
436 const Maybe<bool>& ownProperties, const Maybe<bool>& accessorPropertiesOnly,
437 const Maybe<bool>& generatePreview,
438 std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
439 result,
440 Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>*
441 internalProperties,
442 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
443 using protocol::Runtime::InternalPropertyDescriptor;
444
445 InjectedScript::ObjectScope scope(errorString, m_inspector,
446 m_session->contextGroupId(), objectId);
447 if (!scope.initialize()) return;
448
449 scope.ignoreExceptionsAndMuteConsole();
450 if (!scope.object()->IsObject()) {
451 *errorString = "Value with given id is not an object";
452 return;
453 }
454
455 v8::Local<v8::Object> object = scope.object().As<v8::Object>();
456 scope.injectedScript()->getProperties(
457 errorString, object, scope.objectGroupName(),
458 ownProperties.fromMaybe(false), accessorPropertiesOnly.fromMaybe(false),
459 generatePreview.fromMaybe(false), result, exceptionDetails);
460 if (!errorString->isEmpty() || exceptionDetails->isJust() ||
461 accessorPropertiesOnly.fromMaybe(false))
462 return;
463 v8::Local<v8::Array> propertiesArray;
464 if (hasInternalError(errorString, !m_inspector->debugger()
465 ->internalProperties(scope.context(),
466 scope.object())
467 .ToLocal(&propertiesArray)))
468 return;
469 std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>
470 propertiesProtocolArray =
471 protocol::Array<InternalPropertyDescriptor>::create();
472 for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) {
473 v8::Local<v8::Value> name;
474 if (hasInternalError(
475 errorString,
476 !propertiesArray->Get(scope.context(), i).ToLocal(&name)) ||
477 !name->IsString())
478 return;
479 v8::Local<v8::Value> value;
480 if (hasInternalError(
481 errorString,
482 !propertiesArray->Get(scope.context(), i + 1).ToLocal(&value)))
483 return;
484 std::unique_ptr<RemoteObject> wrappedValue =
485 scope.injectedScript()->wrapObject(errorString, value,
486 scope.objectGroupName());
487 if (!wrappedValue) return;
488 propertiesProtocolArray->addItem(
489 InternalPropertyDescriptor::create()
490 .setName(toProtocolString(name.As<v8::String>()))
491 .setValue(std::move(wrappedValue))
492 .build());
493 }
494 if (!propertiesProtocolArray->length()) return;
495 *internalProperties = std::move(propertiesProtocolArray);
496 }
497
498 void V8RuntimeAgentImpl::releaseObject(ErrorString* errorString,
499 const String16& objectId) {
500 InjectedScript::ObjectScope scope(errorString, m_inspector,
501 m_session->contextGroupId(), objectId);
502 if (!scope.initialize()) return;
503 scope.injectedScript()->releaseObject(objectId);
504 }
505
506 void V8RuntimeAgentImpl::releaseObjectGroup(ErrorString*,
507 const String16& objectGroup) {
508 m_session->releaseObjectGroup(objectGroup);
509 }
510
511 void V8RuntimeAgentImpl::runIfWaitingForDebugger(ErrorString* errorString) {
512 m_inspector->client()->runIfWaitingForDebugger(m_session->contextGroupId());
513 }
514
515 void V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(ErrorString*,
516 bool enabled) {
517 m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled,
518 enabled);
519 m_session->setCustomObjectFormatterEnabled(enabled);
520 }
521
522 void V8RuntimeAgentImpl::discardConsoleEntries(ErrorString*) {
523 V8ConsoleMessageStorage* storage =
524 m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
525 storage->clear();
526 }
527
528 void V8RuntimeAgentImpl::compileScript(
529 ErrorString* errorString, const String16& expression,
530 const String16& sourceURL, bool persistScript,
531 const Maybe<int>& executionContextId, Maybe<String16>* scriptId,
532 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
533 if (!m_enabled) {
534 *errorString = "Runtime agent is not enabled";
535 return;
536 }
537 int contextId =
538 ensureContext(errorString, m_inspector, m_session->contextGroupId(),
539 executionContextId);
540 if (!errorString->isEmpty()) return;
541 InjectedScript::ContextScope scope(errorString, m_inspector,
542 m_session->contextGroupId(), contextId);
543 if (!scope.initialize()) return;
544
545 if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents();
546 v8::Local<v8::Script> script = m_inspector->compileScript(
547 scope.context(), toV8String(m_inspector->isolate(), expression),
548 sourceURL, false);
549 if (!persistScript) m_inspector->debugger()->unmuteScriptParsedEvents();
550 if (script.IsEmpty()) {
551 if (scope.tryCatch().HasCaught())
552 *exceptionDetails = scope.injectedScript()->createExceptionDetails(
553 errorString, scope.tryCatch(), String16(), false);
554 else
555 *errorString = "Script compilation failed";
556 return;
557 }
558
559 if (!persistScript) return;
560
561 String16 scriptValueId =
562 String16::fromInteger(script->GetUnboundScript()->GetId());
563 std::unique_ptr<v8::Global<v8::Script>> global(
564 new v8::Global<v8::Script>(m_inspector->isolate(), script));
565 m_compiledScripts[scriptValueId] = std::move(global);
566 *scriptId = scriptValueId;
567 }
568
569 void V8RuntimeAgentImpl::runScript(
570 const String16& scriptId, const Maybe<int>& executionContextId,
571 const Maybe<String16>& objectGroup, const Maybe<bool>& silent,
572 const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& returnByValue,
573 const Maybe<bool>& generatePreview, const Maybe<bool>& awaitPromise,
574 std::unique_ptr<RunScriptCallback> callback) {
575 if (!m_enabled) {
576 callback->sendFailure("Runtime agent is not enabled");
577 return;
578 }
579
580 auto it = m_compiledScripts.find(scriptId);
581 if (it == m_compiledScripts.end()) {
582 callback->sendFailure("No script with given id");
583 return;
584 }
585
586 ErrorString errorString;
587 int contextId =
588 ensureContext(&errorString, m_inspector, m_session->contextGroupId(),
589 executionContextId);
590 if (!errorString.isEmpty()) {
591 callback->sendFailure(errorString);
592 return;
593 }
594
595 InjectedScript::ContextScope scope(&errorString, m_inspector,
596 m_session->contextGroupId(), contextId);
597 if (!scope.initialize()) {
598 callback->sendFailure(errorString);
599 return;
600 }
601
602 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
603
604 std::unique_ptr<v8::Global<v8::Script>> scriptWrapper = std::move(it->second);
605 m_compiledScripts.erase(it);
606 v8::Local<v8::Script> script = scriptWrapper->Get(m_inspector->isolate());
607 if (script.IsEmpty()) {
608 callback->sendFailure("Script execution failed");
609 return;
610 }
611
612 if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI())
613 return;
614
615 v8::MaybeLocal<v8::Value> maybeResultValue =
616 m_inspector->runCompiledScript(scope.context(), script);
617
618 // Re-initialize after running client's code, as it could have destroyed
619 // context or session.
620 if (!scope.initialize()) return;
621
622 if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
623 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
624 scope.tryCatch(), objectGroup.fromMaybe(""),
625 returnByValue.fromMaybe(false),
626 generatePreview.fromMaybe(false), callback.get());
627 return;
628 }
629 ProtocolPromiseHandler<RunScriptCallback>::add(
630 m_inspector, scope.context(), maybeResultValue.ToLocalChecked(),
631 "Result of the script execution is not a promise",
632 m_session->contextGroupId(),
633 scope.injectedScript()->context()->contextId(), objectGroup.fromMaybe(""),
634 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
635 std::move(callback));
636 }
637
638 void V8RuntimeAgentImpl::restore() {
639 if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
640 return;
641 m_frontend.executionContextsCleared();
642 ErrorString error;
643 enable(&error);
644 if (m_state->booleanProperty(
645 V8RuntimeAgentImplState::customObjectFormatterEnabled, false))
646 m_session->setCustomObjectFormatterEnabled(true);
647 }
648
649 void V8RuntimeAgentImpl::enable(ErrorString* errorString) {
650 if (m_enabled) return;
651 m_inspector->client()->beginEnsureAllContextsInGroup(
652 m_session->contextGroupId());
653 m_enabled = true;
654 m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, true);
655 m_inspector->enableStackCapturingIfNeeded();
656 m_session->reportAllContexts(this);
657 V8ConsoleMessageStorage* storage =
658 m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
659 for (const auto& message : storage->messages())
660 reportMessage(message.get(), false);
661 }
662
663 void V8RuntimeAgentImpl::disable(ErrorString* errorString) {
664 if (!m_enabled) return;
665 m_enabled = false;
666 m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false);
667 m_inspector->disableStackCapturingIfNeeded();
668 m_session->discardInjectedScripts();
669 reset();
670 m_inspector->client()->endEnsureAllContextsInGroup(
671 m_session->contextGroupId());
672 }
673
674 void V8RuntimeAgentImpl::reset() {
675 m_compiledScripts.clear();
676 if (m_enabled) {
677 if (const V8InspectorImpl::ContextByIdMap* contexts =
678 m_inspector->contextGroup(m_session->contextGroupId())) {
679 for (auto& idContext : *contexts) idContext.second->setReported(false);
680 }
681 m_frontend.executionContextsCleared();
682 }
683 }
684
685 void V8RuntimeAgentImpl::reportExecutionContextCreated(
686 InspectedContext* context) {
687 if (!m_enabled) return;
688 context->setReported(true);
689 std::unique_ptr<protocol::Runtime::ExecutionContextDescription> description =
690 protocol::Runtime::ExecutionContextDescription::create()
691 .setId(context->contextId())
692 .setName(context->humanReadableName())
693 .setOrigin(context->origin())
694 .build();
695 if (!context->auxData().isEmpty())
696 description->setAuxData(protocol::DictionaryValue::cast(
697 protocol::parseJSON(context->auxData())));
698 m_frontend.executionContextCreated(std::move(description));
699 }
700
701 void V8RuntimeAgentImpl::reportExecutionContextDestroyed(
702 InspectedContext* context) {
703 if (m_enabled && context->isReported()) {
704 context->setReported(false);
705 m_frontend.executionContextDestroyed(context->contextId());
706 }
707 }
708
709 void V8RuntimeAgentImpl::inspect(
710 std::unique_ptr<protocol::Runtime::RemoteObject> objectToInspect,
711 std::unique_ptr<protocol::DictionaryValue> hints) {
712 if (m_enabled)
713 m_frontend.inspectRequested(std::move(objectToInspect), std::move(hints));
714 }
715
716 void V8RuntimeAgentImpl::messageAdded(V8ConsoleMessage* message) {
717 if (m_enabled) reportMessage(message, true);
718 }
719
720 void V8RuntimeAgentImpl::reportMessage(V8ConsoleMessage* message,
721 bool generatePreview) {
722 message->reportToFrontend(&m_frontend, m_session, generatePreview);
723 m_frontend.flush();
724 }
725
726 } // namespace v8_inspector
OLDNEW
« no previous file with comments | « src/inspector/V8RuntimeAgentImpl.h ('k') | src/inspector/V8SchemaAgentImpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698