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

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

Issue 2338413003: [inspector] change implementation file extension from cpp to cc (Closed)
Patch Set: string16 -> string-16 Created 4 years, 2 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/V8ConsoleMessage.h"
38 #include "src/inspector/V8Debugger.h"
39 #include "src/inspector/V8DebuggerAgentImpl.h"
40 #include "src/inspector/V8InspectorImpl.h"
41 #include "src/inspector/V8InspectorSessionImpl.h"
42 #include "src/inspector/V8StackTraceImpl.h"
43 #include "src/inspector/protocol/Protocol.h"
44
45 #include "include/v8-inspector.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(context, thenCallback, wrapper, 0,
91 v8::ConstructorBehavior::kThrow)
92 .ToLocalChecked();
93 if (promise->Then(context, thenCallbackFunction).IsEmpty()) {
94 rawCallback->sendFailure("Internal error");
95 return;
96 }
97 v8::Local<v8::Function> catchCallbackFunction =
98 v8::Function::New(context, catchCallback, wrapper, 0,
99 v8::ConstructorBehavior::kThrow)
100 .ToLocalChecked();
101 if (promise->Catch(context, catchCallbackFunction).IsEmpty()) {
102 rawCallback->sendFailure("Internal error");
103 return;
104 }
105 }
106
107 private:
108 static void thenCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
109 ProtocolPromiseHandler<Callback>* handler =
110 static_cast<ProtocolPromiseHandler<Callback>*>(
111 info.Data().As<v8::External>()->Value());
112 DCHECK(handler);
113 v8::Local<v8::Value> value =
114 info.Length() > 0
115 ? info[0]
116 : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()));
117 handler->m_callback->sendSuccess(
118 handler->wrapObject(value),
119 Maybe<protocol::Runtime::ExceptionDetails>());
120 }
121
122 static void catchCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
123 ProtocolPromiseHandler<Callback>* handler =
124 static_cast<ProtocolPromiseHandler<Callback>*>(
125 info.Data().As<v8::External>()->Value());
126 DCHECK(handler);
127 v8::Local<v8::Value> value =
128 info.Length() > 0
129 ? info[0]
130 : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()));
131
132 std::unique_ptr<V8StackTraceImpl> stack =
133 handler->m_inspector->debugger()->captureStackTrace(true);
134 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
135 protocol::Runtime::ExceptionDetails::create()
136 .setExceptionId(handler->m_inspector->nextExceptionId())
137 .setText("Uncaught (in promise)")
138 .setLineNumber(stack && !stack->isEmpty() ? stack->topLineNumber()
139 : 0)
140 .setColumnNumber(
141 stack && !stack->isEmpty() ? stack->topColumnNumber() : 0)
142 .setException(handler->wrapObject(value))
143 .build();
144 if (stack)
145 exceptionDetails->setStackTrace(stack->buildInspectorObjectImpl());
146 if (stack && !stack->isEmpty())
147 exceptionDetails->setScriptId(toString16(stack->topScriptId()));
148 handler->m_callback->sendSuccess(handler->wrapObject(value),
149 std::move(exceptionDetails));
150 }
151
152 ProtocolPromiseHandler(V8InspectorImpl* inspector, int contextGroupId,
153 int executionContextId, const String16& objectGroup,
154 bool returnByValue, bool generatePreview,
155 std::unique_ptr<Callback> callback)
156 : m_inspector(inspector),
157 m_contextGroupId(contextGroupId),
158 m_executionContextId(executionContextId),
159 m_objectGroup(objectGroup),
160 m_returnByValue(returnByValue),
161 m_generatePreview(generatePreview),
162 m_callback(std::move(callback)),
163 m_wrapper(inspector->isolate(),
164 v8::External::New(inspector->isolate(), this)) {
165 m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter);
166 }
167
168 static void cleanup(
169 const v8::WeakCallbackInfo<ProtocolPromiseHandler<Callback>>& data) {
170 if (!data.GetParameter()->m_wrapper.IsEmpty()) {
171 data.GetParameter()->m_wrapper.Reset();
172 data.SetSecondPassCallback(cleanup);
173 } else {
174 data.GetParameter()->m_callback->sendFailure("Promise was collected");
175 delete data.GetParameter();
176 }
177 }
178
179 std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(
180 v8::Local<v8::Value> value) {
181 ErrorString errorString;
182 InjectedScript::ContextScope scope(&errorString, m_inspector,
183 m_contextGroupId, m_executionContextId);
184 if (!scope.initialize()) {
185 m_callback->sendFailure(errorString);
186 return nullptr;
187 }
188 std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue =
189 scope.injectedScript()->wrapObject(&errorString, value, m_objectGroup,
190 m_returnByValue, m_generatePreview);
191 if (!wrappedValue) {
192 m_callback->sendFailure(errorString);
193 return nullptr;
194 }
195 return wrappedValue;
196 }
197
198 V8InspectorImpl* m_inspector;
199 int m_contextGroupId;
200 int m_executionContextId;
201 String16 m_objectGroup;
202 bool m_returnByValue;
203 bool m_generatePreview;
204 std::unique_ptr<Callback> m_callback;
205 v8::Global<v8::External> m_wrapper;
206 };
207
208 template <typename Callback>
209 bool wrapEvaluateResultAsync(InjectedScript* injectedScript,
210 v8::MaybeLocal<v8::Value> maybeResultValue,
211 const v8::TryCatch& tryCatch,
212 const String16& objectGroup, bool returnByValue,
213 bool generatePreview, Callback* callback) {
214 std::unique_ptr<RemoteObject> result;
215 Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails;
216
217 ErrorString errorString;
218 injectedScript->wrapEvaluateResult(
219 &errorString, maybeResultValue, tryCatch, objectGroup, returnByValue,
220 generatePreview, &result, &exceptionDetails);
221 if (errorString.isEmpty()) {
222 callback->sendSuccess(std::move(result), exceptionDetails);
223 return true;
224 }
225 callback->sendFailure(errorString);
226 return false;
227 }
228
229 int ensureContext(ErrorString* errorString, V8InspectorImpl* inspector,
230 int contextGroupId, const Maybe<int>& executionContextId) {
231 int contextId;
232 if (executionContextId.isJust()) {
233 contextId = executionContextId.fromJust();
234 } else {
235 v8::HandleScope handles(inspector->isolate());
236 v8::Local<v8::Context> defaultContext =
237 inspector->client()->ensureDefaultContextInGroup(contextGroupId);
238 if (defaultContext.IsEmpty()) {
239 *errorString = "Cannot find default execution context";
240 return 0;
241 }
242 contextId = V8Debugger::contextId(defaultContext);
243 }
244 return contextId;
245 }
246
247 } // namespace
248
249 V8RuntimeAgentImpl::V8RuntimeAgentImpl(
250 V8InspectorSessionImpl* session, protocol::FrontendChannel* FrontendChannel,
251 protocol::DictionaryValue* state)
252 : m_session(session),
253 m_state(state),
254 m_frontend(FrontendChannel),
255 m_inspector(session->inspector()),
256 m_enabled(false) {}
257
258 V8RuntimeAgentImpl::~V8RuntimeAgentImpl() {}
259
260 void V8RuntimeAgentImpl::evaluate(
261 const String16& expression, const Maybe<String16>& objectGroup,
262 const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& silent,
263 const Maybe<int>& executionContextId, const Maybe<bool>& returnByValue,
264 const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture,
265 const Maybe<bool>& awaitPromise,
266 std::unique_ptr<EvaluateCallback> callback) {
267 ErrorString errorString;
268 int contextId =
269 ensureContext(&errorString, m_inspector, m_session->contextGroupId(),
270 executionContextId);
271 if (!errorString.isEmpty()) {
272 callback->sendFailure(errorString);
273 return;
274 }
275
276 InjectedScript::ContextScope scope(&errorString, m_inspector,
277 m_session->contextGroupId(), contextId);
278 if (!scope.initialize()) {
279 callback->sendFailure(errorString);
280 return;
281 }
282
283 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
284 if (userGesture.fromMaybe(false)) scope.pretendUserGesture();
285
286 if (includeCommandLineAPI.fromMaybe(false) &&
287 !scope.installCommandLineAPI()) {
288 callback->sendFailure(errorString);
289 return;
290 }
291
292 bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed();
293 // Temporarily enable allow evals for inspector.
294 if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(true);
295
296 v8::MaybeLocal<v8::Value> maybeResultValue;
297 v8::Local<v8::Script> script = m_inspector->compileScript(
298 scope.context(), toV8String(m_inspector->isolate(), expression),
299 String16(), false);
300 if (!script.IsEmpty())
301 maybeResultValue = m_inspector->runCompiledScript(scope.context(), script);
302
303 if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(false);
304
305 // Re-initialize after running client's code, as it could have destroyed
306 // context or session.
307 if (!scope.initialize()) {
308 callback->sendFailure(errorString);
309 return;
310 }
311
312 if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
313 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
314 scope.tryCatch(), objectGroup.fromMaybe(""),
315 returnByValue.fromMaybe(false),
316 generatePreview.fromMaybe(false), callback.get());
317 return;
318 }
319 ProtocolPromiseHandler<EvaluateCallback>::add(
320 m_inspector, scope.context(), maybeResultValue,
321 "Result of the evaluation is not a promise", m_session->contextGroupId(),
322 scope.injectedScript()->context()->contextId(), objectGroup.fromMaybe(""),
323 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
324 std::move(callback));
325 }
326
327 void V8RuntimeAgentImpl::awaitPromise(
328 const String16& promiseObjectId, const Maybe<bool>& returnByValue,
329 const Maybe<bool>& generatePreview,
330 std::unique_ptr<AwaitPromiseCallback> callback) {
331 ErrorString errorString;
332 InjectedScript::ObjectScope scope(
333 &errorString, m_inspector, m_session->contextGroupId(), promiseObjectId);
334 if (!scope.initialize()) {
335 callback->sendFailure(errorString);
336 return;
337 }
338 ProtocolPromiseHandler<AwaitPromiseCallback>::add(
339 m_inspector, scope.context(), scope.object(),
340 "Could not find promise with given id", m_session->contextGroupId(),
341 scope.injectedScript()->context()->contextId(), scope.objectGroupName(),
342 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
343 std::move(callback));
344 }
345
346 void V8RuntimeAgentImpl::callFunctionOn(
347 const String16& objectId, const String16& expression,
348 const Maybe<protocol::Array<protocol::Runtime::CallArgument>>&
349 optionalArguments,
350 const Maybe<bool>& silent, const Maybe<bool>& returnByValue,
351 const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture,
352 const Maybe<bool>& awaitPromise,
353 std::unique_ptr<CallFunctionOnCallback> callback) {
354 ErrorString errorString;
355 InjectedScript::ObjectScope scope(&errorString, m_inspector,
356 m_session->contextGroupId(), objectId);
357 if (!scope.initialize()) {
358 callback->sendFailure(errorString);
359 return;
360 }
361
362 std::unique_ptr<v8::Local<v8::Value>[]> argv = nullptr;
363 int argc = 0;
364 if (optionalArguments.isJust()) {
365 protocol::Array<protocol::Runtime::CallArgument>* arguments =
366 optionalArguments.fromJust();
367 argc = arguments->length();
368 argv.reset(new v8::Local<v8::Value>[argc]);
369 for (int i = 0; i < argc; ++i) {
370 v8::Local<v8::Value> argumentValue;
371 if (!scope.injectedScript()
372 ->resolveCallArgument(&errorString, arguments->get(i))
373 .ToLocal(&argumentValue)) {
374 callback->sendFailure(errorString);
375 return;
376 }
377 argv[i] = argumentValue;
378 }
379 }
380
381 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
382 if (userGesture.fromMaybe(false)) scope.pretendUserGesture();
383
384 v8::MaybeLocal<v8::Value> maybeFunctionValue =
385 m_inspector->compileAndRunInternalScript(
386 scope.context(),
387 toV8String(m_inspector->isolate(), "(" + expression + ")"));
388 // Re-initialize after running client's code, as it could have destroyed
389 // context or session.
390 if (!scope.initialize()) {
391 callback->sendFailure(errorString);
392 return;
393 }
394
395 if (scope.tryCatch().HasCaught()) {
396 wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue,
397 scope.tryCatch(), scope.objectGroupName(), false,
398 false, callback.get());
399 return;
400 }
401
402 v8::Local<v8::Value> functionValue;
403 if (!maybeFunctionValue.ToLocal(&functionValue) ||
404 !functionValue->IsFunction()) {
405 callback->sendFailure("Given expression does not evaluate to a function");
406 return;
407 }
408
409 v8::MaybeLocal<v8::Value> maybeResultValue = m_inspector->callFunction(
410 functionValue.As<v8::Function>(), scope.context(), scope.object(), argc,
411 argv.get());
412 // Re-initialize after running client's code, as it could have destroyed
413 // context or session.
414 if (!scope.initialize()) {
415 callback->sendFailure(errorString);
416 return;
417 }
418
419 if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
420 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
421 scope.tryCatch(), scope.objectGroupName(),
422 returnByValue.fromMaybe(false),
423 generatePreview.fromMaybe(false), callback.get());
424 return;
425 }
426
427 ProtocolPromiseHandler<CallFunctionOnCallback>::add(
428 m_inspector, scope.context(), maybeResultValue,
429 "Result of the function call is not a promise",
430 m_session->contextGroupId(),
431 scope.injectedScript()->context()->contextId(), scope.objectGroupName(),
432 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
433 std::move(callback));
434 }
435
436 void V8RuntimeAgentImpl::getProperties(
437 ErrorString* errorString, const String16& objectId,
438 const Maybe<bool>& ownProperties, const Maybe<bool>& accessorPropertiesOnly,
439 const Maybe<bool>& generatePreview,
440 std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
441 result,
442 Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>*
443 internalProperties,
444 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
445 using protocol::Runtime::InternalPropertyDescriptor;
446
447 InjectedScript::ObjectScope scope(errorString, m_inspector,
448 m_session->contextGroupId(), objectId);
449 if (!scope.initialize()) return;
450
451 scope.ignoreExceptionsAndMuteConsole();
452 if (!scope.object()->IsObject()) {
453 *errorString = "Value with given id is not an object";
454 return;
455 }
456
457 v8::Local<v8::Object> object = scope.object().As<v8::Object>();
458 scope.injectedScript()->getProperties(
459 errorString, object, scope.objectGroupName(),
460 ownProperties.fromMaybe(false), accessorPropertiesOnly.fromMaybe(false),
461 generatePreview.fromMaybe(false), result, exceptionDetails);
462 if (!errorString->isEmpty() || exceptionDetails->isJust() ||
463 accessorPropertiesOnly.fromMaybe(false))
464 return;
465 v8::Local<v8::Array> propertiesArray;
466 if (hasInternalError(errorString, !m_inspector->debugger()
467 ->internalProperties(scope.context(),
468 scope.object())
469 .ToLocal(&propertiesArray)))
470 return;
471 std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>
472 propertiesProtocolArray =
473 protocol::Array<InternalPropertyDescriptor>::create();
474 for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) {
475 v8::Local<v8::Value> name;
476 if (hasInternalError(
477 errorString,
478 !propertiesArray->Get(scope.context(), i).ToLocal(&name)) ||
479 !name->IsString())
480 return;
481 v8::Local<v8::Value> value;
482 if (hasInternalError(
483 errorString,
484 !propertiesArray->Get(scope.context(), i + 1).ToLocal(&value)))
485 return;
486 std::unique_ptr<RemoteObject> wrappedValue =
487 scope.injectedScript()->wrapObject(errorString, value,
488 scope.objectGroupName());
489 if (!wrappedValue) return;
490 propertiesProtocolArray->addItem(
491 InternalPropertyDescriptor::create()
492 .setName(toProtocolString(name.As<v8::String>()))
493 .setValue(std::move(wrappedValue))
494 .build());
495 }
496 if (!propertiesProtocolArray->length()) return;
497 *internalProperties = std::move(propertiesProtocolArray);
498 }
499
500 void V8RuntimeAgentImpl::releaseObject(ErrorString* errorString,
501 const String16& objectId) {
502 InjectedScript::ObjectScope scope(errorString, m_inspector,
503 m_session->contextGroupId(), objectId);
504 if (!scope.initialize()) return;
505 scope.injectedScript()->releaseObject(objectId);
506 }
507
508 void V8RuntimeAgentImpl::releaseObjectGroup(ErrorString*,
509 const String16& objectGroup) {
510 m_session->releaseObjectGroup(objectGroup);
511 }
512
513 void V8RuntimeAgentImpl::runIfWaitingForDebugger(ErrorString* errorString) {
514 m_inspector->client()->runIfWaitingForDebugger(m_session->contextGroupId());
515 }
516
517 void V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(ErrorString*,
518 bool enabled) {
519 m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled,
520 enabled);
521 m_session->setCustomObjectFormatterEnabled(enabled);
522 }
523
524 void V8RuntimeAgentImpl::discardConsoleEntries(ErrorString*) {
525 V8ConsoleMessageStorage* storage =
526 m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
527 storage->clear();
528 }
529
530 void V8RuntimeAgentImpl::compileScript(
531 ErrorString* errorString, const String16& expression,
532 const String16& sourceURL, bool persistScript,
533 const Maybe<int>& executionContextId, Maybe<String16>* scriptId,
534 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
535 if (!m_enabled) {
536 *errorString = "Runtime agent is not enabled";
537 return;
538 }
539 int contextId =
540 ensureContext(errorString, m_inspector, m_session->contextGroupId(),
541 executionContextId);
542 if (!errorString->isEmpty()) return;
543 InjectedScript::ContextScope scope(errorString, m_inspector,
544 m_session->contextGroupId(), contextId);
545 if (!scope.initialize()) return;
546
547 if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents();
548 v8::Local<v8::Script> script = m_inspector->compileScript(
549 scope.context(), toV8String(m_inspector->isolate(), expression),
550 sourceURL, false);
551 if (!persistScript) m_inspector->debugger()->unmuteScriptParsedEvents();
552 if (script.IsEmpty()) {
553 if (scope.tryCatch().HasCaught())
554 *exceptionDetails = scope.injectedScript()->createExceptionDetails(
555 errorString, scope.tryCatch(), String16(), false);
556 else
557 *errorString = "Script compilation failed";
558 return;
559 }
560
561 if (!persistScript) return;
562
563 String16 scriptValueId =
564 String16::fromInteger(script->GetUnboundScript()->GetId());
565 std::unique_ptr<v8::Global<v8::Script>> global(
566 new v8::Global<v8::Script>(m_inspector->isolate(), script));
567 m_compiledScripts[scriptValueId] = std::move(global);
568 *scriptId = scriptValueId;
569 }
570
571 void V8RuntimeAgentImpl::runScript(
572 const String16& scriptId, const Maybe<int>& executionContextId,
573 const Maybe<String16>& objectGroup, const Maybe<bool>& silent,
574 const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& returnByValue,
575 const Maybe<bool>& generatePreview, const Maybe<bool>& awaitPromise,
576 std::unique_ptr<RunScriptCallback> callback) {
577 if (!m_enabled) {
578 callback->sendFailure("Runtime agent is not enabled");
579 return;
580 }
581
582 auto it = m_compiledScripts.find(scriptId);
583 if (it == m_compiledScripts.end()) {
584 callback->sendFailure("No script with given id");
585 return;
586 }
587
588 ErrorString errorString;
589 int contextId =
590 ensureContext(&errorString, m_inspector, m_session->contextGroupId(),
591 executionContextId);
592 if (!errorString.isEmpty()) {
593 callback->sendFailure(errorString);
594 return;
595 }
596
597 InjectedScript::ContextScope scope(&errorString, m_inspector,
598 m_session->contextGroupId(), contextId);
599 if (!scope.initialize()) {
600 callback->sendFailure(errorString);
601 return;
602 }
603
604 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
605
606 std::unique_ptr<v8::Global<v8::Script>> scriptWrapper = std::move(it->second);
607 m_compiledScripts.erase(it);
608 v8::Local<v8::Script> script = scriptWrapper->Get(m_inspector->isolate());
609 if (script.IsEmpty()) {
610 callback->sendFailure("Script execution failed");
611 return;
612 }
613
614 if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI())
615 return;
616
617 v8::MaybeLocal<v8::Value> maybeResultValue =
618 m_inspector->runCompiledScript(scope.context(), script);
619
620 // Re-initialize after running client's code, as it could have destroyed
621 // context or session.
622 if (!scope.initialize()) return;
623
624 if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
625 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
626 scope.tryCatch(), objectGroup.fromMaybe(""),
627 returnByValue.fromMaybe(false),
628 generatePreview.fromMaybe(false), callback.get());
629 return;
630 }
631 ProtocolPromiseHandler<RunScriptCallback>::add(
632 m_inspector, scope.context(), maybeResultValue.ToLocalChecked(),
633 "Result of the script execution is not a promise",
634 m_session->contextGroupId(),
635 scope.injectedScript()->context()->contextId(), objectGroup.fromMaybe(""),
636 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
637 std::move(callback));
638 }
639
640 void V8RuntimeAgentImpl::restore() {
641 if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
642 return;
643 m_frontend.executionContextsCleared();
644 ErrorString error;
645 enable(&error);
646 if (m_state->booleanProperty(
647 V8RuntimeAgentImplState::customObjectFormatterEnabled, false))
648 m_session->setCustomObjectFormatterEnabled(true);
649 }
650
651 void V8RuntimeAgentImpl::enable(ErrorString* errorString) {
652 if (m_enabled) return;
653 m_inspector->client()->beginEnsureAllContextsInGroup(
654 m_session->contextGroupId());
655 m_enabled = true;
656 m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, true);
657 m_inspector->enableStackCapturingIfNeeded();
658 m_session->reportAllContexts(this);
659 V8ConsoleMessageStorage* storage =
660 m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
661 for (const auto& message : storage->messages()) {
662 if (!reportMessage(message.get(), false)) return;
663 }
664 }
665
666 void V8RuntimeAgentImpl::disable(ErrorString* errorString) {
667 if (!m_enabled) return;
668 m_enabled = false;
669 m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false);
670 m_inspector->disableStackCapturingIfNeeded();
671 m_session->discardInjectedScripts();
672 reset();
673 m_inspector->client()->endEnsureAllContextsInGroup(
674 m_session->contextGroupId());
675 }
676
677 void V8RuntimeAgentImpl::reset() {
678 m_compiledScripts.clear();
679 if (m_enabled) {
680 if (const V8InspectorImpl::ContextByIdMap* contexts =
681 m_inspector->contextGroup(m_session->contextGroupId())) {
682 for (auto& idContext : *contexts) idContext.second->setReported(false);
683 }
684 m_frontend.executionContextsCleared();
685 }
686 }
687
688 void V8RuntimeAgentImpl::reportExecutionContextCreated(
689 InspectedContext* context) {
690 if (!m_enabled) return;
691 context->setReported(true);
692 std::unique_ptr<protocol::Runtime::ExecutionContextDescription> description =
693 protocol::Runtime::ExecutionContextDescription::create()
694 .setId(context->contextId())
695 .setName(context->humanReadableName())
696 .setOrigin(context->origin())
697 .build();
698 if (!context->auxData().isEmpty())
699 description->setAuxData(protocol::DictionaryValue::cast(
700 protocol::parseJSON(context->auxData())));
701 m_frontend.executionContextCreated(std::move(description));
702 }
703
704 void V8RuntimeAgentImpl::reportExecutionContextDestroyed(
705 InspectedContext* context) {
706 if (m_enabled && context->isReported()) {
707 context->setReported(false);
708 m_frontend.executionContextDestroyed(context->contextId());
709 }
710 }
711
712 void V8RuntimeAgentImpl::inspect(
713 std::unique_ptr<protocol::Runtime::RemoteObject> objectToInspect,
714 std::unique_ptr<protocol::DictionaryValue> hints) {
715 if (m_enabled)
716 m_frontend.inspectRequested(std::move(objectToInspect), std::move(hints));
717 }
718
719 void V8RuntimeAgentImpl::messageAdded(V8ConsoleMessage* message) {
720 if (m_enabled) reportMessage(message, true);
721 }
722
723 bool V8RuntimeAgentImpl::reportMessage(V8ConsoleMessage* message,
724 bool generatePreview) {
725 message->reportToFrontend(&m_frontend, m_session, generatePreview);
726 m_frontend.flush();
727 return m_inspector->hasConsoleMessageStorage(m_session->contextGroupId());
728 }
729
730 } // 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