LCOV - code coverage report
Current view: top level - src/inspector - v8-runtime-agent-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 275 322 85.4 %
Date: 2017-10-20 Functions: 38 46 82.6 %

          Line data    Source code
       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/v8-runtime-agent-impl.h"
      32             : 
      33             : #include "src/debug/debug-interface.h"
      34             : #include "src/inspector/injected-script.h"
      35             : #include "src/inspector/inspected-context.h"
      36             : #include "src/inspector/protocol/Protocol.h"
      37             : #include "src/inspector/remote-object-id.h"
      38             : #include "src/inspector/v8-console-message.h"
      39             : #include "src/inspector/v8-debugger-agent-impl.h"
      40             : #include "src/inspector/v8-debugger.h"
      41             : #include "src/inspector/v8-inspector-impl.h"
      42             : #include "src/inspector/v8-inspector-session-impl.h"
      43             : #include "src/inspector/v8-stack-trace-impl.h"
      44             : #include "src/inspector/v8-value-utils.h"
      45             : #include "src/tracing/trace-event.h"
      46             : 
      47             : #include "include/v8-inspector.h"
      48             : 
      49             : namespace v8_inspector {
      50             : 
      51             : namespace V8RuntimeAgentImplState {
      52             : static const char customObjectFormatterEnabled[] =
      53             :     "customObjectFormatterEnabled";
      54             : static const char runtimeEnabled[] = "runtimeEnabled";
      55             : };
      56             : 
      57             : using protocol::Runtime::RemoteObject;
      58             : 
      59             : namespace {
      60             : 
      61             : template <typename ProtocolCallback>
      62        1040 : class EvaluateCallbackWrapper : public EvaluateCallback {
      63             :  public:
      64             :   static std::unique_ptr<EvaluateCallback> wrap(
      65             :       std::unique_ptr<ProtocolCallback> callback) {
      66             :     return std::unique_ptr<EvaluateCallback>(
      67         520 :         new EvaluateCallbackWrapper(std::move(callback)));
      68             :   }
      69         505 :   void sendSuccess(std::unique_ptr<protocol::Runtime::RemoteObject> result,
      70             :                    protocol::Maybe<protocol::Runtime::ExceptionDetails>
      71             :                        exceptionDetails) override {
      72             :     return m_callback->sendSuccess(std::move(result),
      73        2020 :                                    std::move(exceptionDetails));
      74             :   }
      75          15 :   void sendFailure(const protocol::DispatchResponse& response) override {
      76          15 :     return m_callback->sendFailure(response);
      77             :   }
      78             : 
      79             :  private:
      80             :   explicit EvaluateCallbackWrapper(std::unique_ptr<ProtocolCallback> callback)
      81         520 :       : m_callback(std::move(callback)) {}
      82             : 
      83             :   std::unique_ptr<ProtocolCallback> m_callback;
      84             : };
      85             : 
      86             : template <typename ProtocolCallback>
      87        5599 : bool wrapEvaluateResultAsync(InjectedScript* injectedScript,
      88             :                              v8::MaybeLocal<v8::Value> maybeResultValue,
      89             :                              const v8::TryCatch& tryCatch,
      90             :                              const String16& objectGroup, bool returnByValue,
      91             :                              bool generatePreview, ProtocolCallback* callback) {
      92        5599 :   std::unique_ptr<RemoteObject> result;
      93             :   Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails;
      94             : 
      95             :   Response response = injectedScript->wrapEvaluateResult(
      96             :       maybeResultValue, tryCatch, objectGroup, returnByValue, generatePreview,
      97        5599 :       &result, &exceptionDetails);
      98        5599 :   if (response.isSuccess()) {
      99       22396 :     callback->sendSuccess(std::move(result), std::move(exceptionDetails));
     100        5599 :     return true;
     101             :   }
     102           0 :   callback->sendFailure(response);
     103           0 :   return false;
     104             : }
     105             : 
     106         495 : void innerCallFunctionOn(
     107        1050 :     V8InspectorSessionImpl* session, InjectedScript::Scope& scope,
     108             :     v8::Local<v8::Value> recv, const String16& expression,
     109             :     Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments,
     110             :     bool silent, bool returnByValue, bool generatePreview, bool userGesture,
     111             :     bool awaitPromise, const String16& objectGroup,
     112             :     std::unique_ptr<V8RuntimeAgentImpl::CallFunctionOnCallback> callback) {
     113         965 :   V8InspectorImpl* inspector = session->inspector();
     114             : 
     115             :   std::unique_ptr<v8::Local<v8::Value>[]> argv = nullptr;
     116             :   int argc = 0;
     117         495 :   if (optionalArguments.isJust()) {
     118             :     protocol::Array<protocol::Runtime::CallArgument>* arguments =
     119             :         optionalArguments.fromJust();
     120          60 :     argc = static_cast<int>(arguments->length());
     121         120 :     argv.reset(new v8::Local<v8::Value>[argc]);
     122          60 :     for (int i = 0; i < argc; ++i) {
     123             :       v8::Local<v8::Value> argumentValue;
     124             :       Response response = scope.injectedScript()->resolveCallArgument(
     125         120 :           arguments->get(i), &argumentValue);
     126          60 :       if (!response.isSuccess()) {
     127           0 :         callback->sendFailure(response);
     128             :         return;
     129             :       }
     130          60 :       argv[i] = argumentValue;
     131             :     }
     132             :   }
     133             : 
     134         495 :   if (silent) scope.ignoreExceptionsAndMuteConsole();
     135         495 :   if (userGesture) scope.pretendUserGesture();
     136             : 
     137             :   v8::MaybeLocal<v8::Value> maybeFunctionValue;
     138             :   v8::Local<v8::Script> functionScript;
     139         495 :   if (inspector
     140        2475 :           ->compileScript(scope.context(), "(" + expression + ")", String16())
     141         495 :           .ToLocal(&functionScript)) {
     142             :     v8::MicrotasksScope microtasksScope(inspector->isolate(),
     143         485 :                                         v8::MicrotasksScope::kRunMicrotasks);
     144         485 :     maybeFunctionValue = functionScript->Run(scope.context());
     145             :   }
     146             :   // Re-initialize after running client's code, as it could have destroyed
     147             :   // context or session.
     148         495 :   Response response = scope.initialize();
     149         495 :   if (!response.isSuccess()) {
     150           0 :     callback->sendFailure(response);
     151           0 :     return;
     152             :   }
     153             : 
     154         495 :   if (scope.tryCatch().HasCaught()) {
     155             :     wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue,
     156             :                             scope.tryCatch(), objectGroup, false, false,
     157          15 :                             callback.get());
     158          15 :     return;
     159             :   }
     160             : 
     161             :   v8::Local<v8::Value> functionValue;
     162         960 :   if (!maybeFunctionValue.ToLocal(&functionValue) ||
     163         480 :       !functionValue->IsFunction()) {
     164             :     callback->sendFailure(
     165           0 :         Response::Error("Given expression does not evaluate to a function"));
     166           0 :     return;
     167             :   }
     168             : 
     169             :   v8::MaybeLocal<v8::Value> maybeResultValue;
     170             :   {
     171             :     v8::MicrotasksScope microtasksScope(inspector->isolate(),
     172         480 :                                         v8::MicrotasksScope::kRunMicrotasks);
     173             :     maybeResultValue = functionValue.As<v8::Function>()->Call(
     174         480 :         scope.context(), recv, argc, argv.get());
     175             :   }
     176             :   // Re-initialize after running client's code, as it could have destroyed
     177             :   // context or session.
     178         960 :   response = scope.initialize();
     179         480 :   if (!response.isSuccess()) {
     180           0 :     callback->sendFailure(response);
     181           0 :     return;
     182             :   }
     183             : 
     184         480 :   if (!awaitPromise || scope.tryCatch().HasCaught()) {
     185             :     wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
     186             :                             scope.tryCatch(), objectGroup, returnByValue,
     187         920 :                             generatePreview, callback.get());
     188         460 :     return;
     189             :   }
     190             : 
     191             :   scope.injectedScript()->addPromiseCallback(
     192             :       session, maybeResultValue, objectGroup, returnByValue, generatePreview,
     193             :       EvaluateCallbackWrapper<V8RuntimeAgentImpl::CallFunctionOnCallback>::wrap(
     194          60 :           std::move(callback)));
     195             : }
     196             : 
     197       17682 : Response ensureContext(V8InspectorImpl* inspector, int contextGroupId,
     198             :                        Maybe<int> executionContextId, int* contextId) {
     199        5914 :   if (executionContextId.isJust()) {
     200          30 :     *contextId = executionContextId.fromJust();
     201             :   } else {
     202        5884 :     v8::HandleScope handles(inspector->isolate());
     203             :     v8::Local<v8::Context> defaultContext =
     204        5884 :         inspector->client()->ensureDefaultContextInGroup(contextGroupId);
     205        5884 :     if (defaultContext.IsEmpty())
     206           0 :       return Response::Error("Cannot find default execution context");
     207        5884 :     *contextId = InspectedContext::contextId(defaultContext);
     208             :   }
     209        5914 :   return Response::OK();
     210             : }
     211             : 
     212             : }  // namespace
     213             : 
     214        3406 : V8RuntimeAgentImpl::V8RuntimeAgentImpl(
     215        3406 :     V8InspectorSessionImpl* session, protocol::FrontendChannel* FrontendChannel,
     216             :     protocol::DictionaryValue* state)
     217             :     : m_session(session),
     218             :       m_state(state),
     219             :       m_frontend(FrontendChannel),
     220             :       m_inspector(session->inspector()),
     221       10218 :       m_enabled(false) {}
     222             : 
     223       10218 : V8RuntimeAgentImpl::~V8RuntimeAgentImpl() {}
     224             : 
     225        5419 : void V8RuntimeAgentImpl::evaluate(
     226             :     const String16& expression, Maybe<String16> objectGroup,
     227             :     Maybe<bool> includeCommandLineAPI, Maybe<bool> silent,
     228             :     Maybe<int> executionContextId, Maybe<bool> returnByValue,
     229             :     Maybe<bool> generatePreview, Maybe<bool> userGesture,
     230             :     Maybe<bool> awaitPromise, std::unique_ptr<EvaluateCallback> callback) {
     231       10838 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
     232             :                "EvaluateScript");
     233        5419 :   int contextId = 0;
     234             :   Response response = ensureContext(m_inspector, m_session->contextGroupId(),
     235       10818 :                                     std::move(executionContextId), &contextId);
     236        5419 :   if (!response.isSuccess()) {
     237           0 :     callback->sendFailure(response);
     238           0 :     return;
     239             :   }
     240             : 
     241        5869 :   InjectedScript::ContextScope scope(m_session, contextId);
     242       10838 :   response = scope.initialize();
     243        5419 :   if (!response.isSuccess()) {
     244           5 :     callback->sendFailure(response);
     245           5 :     return;
     246             :   }
     247             : 
     248        5414 :   if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
     249        5414 :   if (userGesture.fromMaybe(false)) scope.pretendUserGesture();
     250             : 
     251        5414 :   if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI();
     252             : 
     253        5414 :   bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed();
     254             :   // Temporarily enable allow evals for inspector.
     255        5414 :   if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(true);
     256             : 
     257             :   v8::MaybeLocal<v8::Value> maybeResultValue;
     258             :   v8::Local<v8::Script> script;
     259       10828 :   if (m_inspector->compileScript(scope.context(), expression, String16())
     260        5414 :           .ToLocal(&script)) {
     261             :     v8::MicrotasksScope microtasksScope(m_inspector->isolate(),
     262       10798 :                                         v8::MicrotasksScope::kRunMicrotasks);
     263        5399 :     maybeResultValue = script->Run(scope.context());
     264             :   }
     265             : 
     266        5414 :   if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(false);
     267             : 
     268             :   // Re-initialize after running client's code, as it could have destroyed
     269             :   // context or session.
     270       10828 :   response = scope.initialize();
     271        5414 :   if (!response.isSuccess()) {
     272          20 :     callback->sendFailure(response);
     273          20 :     return;
     274             :   }
     275             : 
     276        5394 :   if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
     277             :     wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
     278             :                             scope.tryCatch(), objectGroup.fromMaybe(""),
     279             :                             returnByValue.fromMaybe(false),
     280       24720 :                             generatePreview.fromMaybe(false), callback.get());
     281        4944 :     return;
     282             :   }
     283             :   scope.injectedScript()->addPromiseCallback(
     284             :       m_session, maybeResultValue, objectGroup.fromMaybe(""),
     285             :       returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
     286        3150 :       EvaluateCallbackWrapper<EvaluateCallback>::wrap(std::move(callback)));
     287             : }
     288             : 
     289          35 : void V8RuntimeAgentImpl::awaitPromise(
     290             :     const String16& promiseObjectId, Maybe<bool> returnByValue,
     291             :     Maybe<bool> generatePreview,
     292             :     std::unique_ptr<AwaitPromiseCallback> callback) {
     293          35 :   InjectedScript::ObjectScope scope(m_session, promiseObjectId);
     294          35 :   Response response = scope.initialize();
     295          35 :   if (!response.isSuccess()) {
     296           0 :     callback->sendFailure(response);
     297           0 :     return;
     298             :   }
     299          35 :   if (!scope.object()->IsPromise()) {
     300             :     callback->sendFailure(
     301           0 :         Response::Error("Could not find promise with given id"));
     302           0 :     return;
     303             :   }
     304             :   scope.injectedScript()->addPromiseCallback(
     305             :       m_session, scope.object(), scope.objectGroupName(),
     306             :       returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
     307         175 :       EvaluateCallbackWrapper<AwaitPromiseCallback>::wrap(std::move(callback)));
     308             : }
     309             : 
     310         500 : void V8RuntimeAgentImpl::callFunctionOn(
     311             :     const String16& expression, Maybe<String16> objectId,
     312             :     Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments,
     313             :     Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview,
     314             :     Maybe<bool> userGesture, Maybe<bool> awaitPromise,
     315             :     Maybe<int> executionContextId, Maybe<String16> objectGroup,
     316             :     std::unique_ptr<CallFunctionOnCallback> callback) {
     317         510 :   if (objectId.isJust() && executionContextId.isJust()) {
     318             :     callback->sendFailure(Response::Error(
     319          15 :         "ObjectId must not be specified together with executionContextId"));
     320           5 :     return;
     321             :   }
     322         500 :   if (!objectId.isJust() && !executionContextId.isJust()) {
     323             :     callback->sendFailure(Response::Error(
     324           0 :         "Either ObjectId or executionContextId must be specified"));
     325           0 :     return;
     326             :   }
     327         495 :   if (objectId.isJust()) {
     328         985 :     InjectedScript::ObjectScope scope(m_session, objectId.fromJust());
     329         490 :     Response response = scope.initialize();
     330         490 :     if (!response.isSuccess()) {
     331           0 :       callback->sendFailure(response);
     332             :       return;
     333             :     }
     334             :     innerCallFunctionOn(
     335             :         m_session, scope, scope.object(), expression,
     336             :         std::move(optionalArguments), silent.fromMaybe(false),
     337             :         returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
     338             :         userGesture.fromMaybe(false), awaitPromise.fromMaybe(false),
     339         490 :         objectGroup.isJust() ? objectGroup.fromMaybe(String16())
     340             :                              : scope.objectGroupName(),
     341        5880 :         std::move(callback));
     342             :   } else {
     343           5 :     int contextId = 0;
     344             :     Response response =
     345             :         ensureContext(m_inspector, m_session->contextGroupId(),
     346          10 :                       std::move(executionContextId.fromJust()), &contextId);
     347           5 :     if (!response.isSuccess()) {
     348           0 :       callback->sendFailure(response);
     349           0 :       return;
     350             :     }
     351          10 :     InjectedScript::ContextScope scope(m_session, contextId);
     352          10 :     response = scope.initialize();
     353           5 :     if (!response.isSuccess()) {
     354           0 :       callback->sendFailure(response);
     355           0 :       return;
     356             :     }
     357             :     innerCallFunctionOn(
     358             :         m_session, scope, scope.context()->Global(), expression,
     359             :         std::move(optionalArguments), silent.fromMaybe(false),
     360             :         returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
     361             :         userGesture.fromMaybe(false), awaitPromise.fromMaybe(false),
     362          60 :         objectGroup.fromMaybe(""), std::move(callback));
     363             :   }
     364             : }
     365             : 
     366       67096 : Response V8RuntimeAgentImpl::getProperties(
     367             :     const String16& objectId, Maybe<bool> ownProperties,
     368             :     Maybe<bool> accessorPropertiesOnly, Maybe<bool> generatePreview,
     369             :     std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
     370             :         result,
     371             :     Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>*
     372             :         internalProperties,
     373             :     Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
     374             :   using protocol::Runtime::InternalPropertyDescriptor;
     375             : 
     376       67096 :   InjectedScript::ObjectScope scope(m_session, objectId);
     377       67096 :   Response response = scope.initialize();
     378       67096 :   if (!response.isSuccess()) return response;
     379             : 
     380       67096 :   scope.ignoreExceptionsAndMuteConsole();
     381             :   v8::MicrotasksScope microtasks_scope(m_inspector->isolate(),
     382      134192 :                                        v8::MicrotasksScope::kRunMicrotasks);
     383       67096 :   if (!scope.object()->IsObject())
     384           0 :     return Response::Error("Value with given id is not an object");
     385             : 
     386       67096 :   v8::Local<v8::Object> object = scope.object().As<v8::Object>();
     387      268384 :   response = scope.injectedScript()->getProperties(
     388             :       object, scope.objectGroupName(), ownProperties.fromMaybe(false),
     389             :       accessorPropertiesOnly.fromMaybe(false), generatePreview.fromMaybe(false),
     390             :       result, exceptionDetails);
     391       67096 :   if (!response.isSuccess()) return response;
     392      134192 :   if (exceptionDetails->isJust() || accessorPropertiesOnly.fromMaybe(false))
     393           5 :     return Response::OK();
     394             :   v8::Local<v8::Array> propertiesArray;
     395       67091 :   if (!m_inspector->debugger()
     396       67091 :            ->internalProperties(scope.context(), scope.object())
     397       67091 :            .ToLocal(&propertiesArray)) {
     398           0 :     return Response::InternalError();
     399             :   }
     400             :   std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>
     401             :       propertiesProtocolArray =
     402             :           protocol::Array<InternalPropertyDescriptor>::create();
     403      135752 :   for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) {
     404             :     v8::Local<v8::Value> name;
     405        2355 :     if (!propertiesArray->Get(scope.context(), i).ToLocal(&name) ||
     406             :         !name->IsString()) {
     407           0 :       return Response::InternalError();
     408             :     }
     409             :     v8::Local<v8::Value> value;
     410        1570 :     if (!propertiesArray->Get(scope.context(), i + 1).ToLocal(&value))
     411           0 :       return Response::InternalError();
     412         785 :     std::unique_ptr<RemoteObject> wrappedValue;
     413             :     protocol::Response response = scope.injectedScript()->wrapObject(
     414         785 :         value, scope.objectGroupName(), false, false, &wrappedValue);
     415         785 :     if (!response.isSuccess()) return response;
     416             :     propertiesProtocolArray->addItem(
     417             :         InternalPropertyDescriptor::create()
     418        2355 :             .setName(toProtocolString(name.As<v8::String>()))
     419             :             .setValue(std::move(wrappedValue))
     420         785 :             .build());
     421             :   }
     422       67091 :   if (propertiesProtocolArray->length())
     423             :     *internalProperties = std::move(propertiesProtocolArray);
     424      134187 :   return Response::OK();
     425             : }
     426             : 
     427           5 : Response V8RuntimeAgentImpl::releaseObject(const String16& objectId) {
     428           5 :   InjectedScript::ObjectScope scope(m_session, objectId);
     429           5 :   Response response = scope.initialize();
     430           5 :   if (!response.isSuccess()) return response;
     431           5 :   scope.injectedScript()->releaseObject(objectId);
     432          10 :   return Response::OK();
     433             : }
     434             : 
     435           0 : Response V8RuntimeAgentImpl::releaseObjectGroup(const String16& objectGroup) {
     436           0 :   m_session->releaseObjectGroup(objectGroup);
     437           0 :   return Response::OK();
     438             : }
     439             : 
     440           0 : Response V8RuntimeAgentImpl::runIfWaitingForDebugger() {
     441           0 :   m_inspector->client()->runIfWaitingForDebugger(m_session->contextGroupId());
     442           0 :   return Response::OK();
     443             : }
     444             : 
     445           5 : Response V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(bool enabled) {
     446             :   m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled,
     447          10 :                       enabled);
     448           5 :   if (!m_enabled) return Response::Error("Runtime agent is not enabled");
     449           5 :   m_session->setCustomObjectFormatterEnabled(enabled);
     450           5 :   return Response::OK();
     451             : }
     452             : 
     453           5 : Response V8RuntimeAgentImpl::discardConsoleEntries() {
     454             :   V8ConsoleMessageStorage* storage =
     455           5 :       m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
     456           5 :   storage->clear();
     457           5 :   return Response::OK();
     458             : }
     459             : 
     460         265 : Response V8RuntimeAgentImpl::compileScript(
     461             :     const String16& expression, const String16& sourceURL, bool persistScript,
     462             :     Maybe<int> executionContextId, Maybe<String16>* scriptId,
     463             :     Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
     464         270 :   if (!m_enabled) return Response::Error("Runtime agent is not enabled");
     465             : 
     466         260 :   int contextId = 0;
     467             :   Response response = ensureContext(m_inspector, m_session->contextGroupId(),
     468         485 :                                     std::move(executionContextId), &contextId);
     469         260 :   if (!response.isSuccess()) return response;
     470         520 :   InjectedScript::ContextScope scope(m_session, contextId);
     471         520 :   response = scope.initialize();
     472         260 :   if (!response.isSuccess()) return response;
     473             : 
     474         285 :   if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents();
     475             :   v8::Local<v8::Script> script;
     476         260 :   bool isOk = m_inspector->compileScript(scope.context(), expression, sourceURL)
     477         260 :                   .ToLocal(&script);
     478         285 :   if (!persistScript) m_inspector->debugger()->unmuteScriptParsedEvents();
     479         260 :   if (!isOk) {
     480          25 :     if (scope.tryCatch().HasCaught()) {
     481          75 :       response = scope.injectedScript()->createExceptionDetails(
     482             :           scope.tryCatch(), String16(), false, exceptionDetails);
     483          25 :       if (!response.isSuccess()) return response;
     484          25 :       return Response::OK();
     485             :     } else {
     486           0 :       return Response::Error("Script compilation failed");
     487             :     }
     488             :   }
     489             : 
     490         235 :   if (!persistScript) return Response::OK();
     491             : 
     492             :   String16 scriptValueId =
     493         450 :       String16::fromInteger(script->GetUnboundScript()->GetId());
     494             :   std::unique_ptr<v8::Global<v8::Script>> global(
     495         450 :       new v8::Global<v8::Script>(m_inspector->isolate(), script));
     496             :   m_compiledScripts[scriptValueId] = std::move(global);
     497         450 :   *scriptId = scriptValueId;
     498         225 :   return Response::OK();
     499             : }
     500             : 
     501         215 : void V8RuntimeAgentImpl::runScript(
     502             :     const String16& scriptId, Maybe<int> executionContextId,
     503             :     Maybe<String16> objectGroup, Maybe<bool> silent,
     504             :     Maybe<bool> includeCommandLineAPI, Maybe<bool> returnByValue,
     505             :     Maybe<bool> generatePreview, Maybe<bool> awaitPromise,
     506             :     std::unique_ptr<RunScriptCallback> callback) {
     507         215 :   if (!m_enabled) {
     508          30 :     callback->sendFailure(Response::Error("Runtime agent is not enabled"));
     509         210 :     return;
     510             :   }
     511             : 
     512             :   auto it = m_compiledScripts.find(scriptId);
     513         205 :   if (it == m_compiledScripts.end()) {
     514          30 :     callback->sendFailure(Response::Error("No script with given id"));
     515          10 :     return;
     516             :   }
     517             : 
     518         195 :   int contextId = 0;
     519             :   Response response = ensureContext(m_inspector, m_session->contextGroupId(),
     520         585 :                                     std::move(executionContextId), &contextId);
     521         195 :   if (!response.isSuccess()) {
     522           0 :     callback->sendFailure(response);
     523           0 :     return;
     524             :   }
     525             : 
     526         210 :   InjectedScript::ContextScope scope(m_session, contextId);
     527         390 :   response = scope.initialize();
     528         195 :   if (!response.isSuccess()) {
     529           0 :     callback->sendFailure(response);
     530         180 :     return;
     531             :   }
     532             : 
     533         195 :   if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
     534             : 
     535             :   std::unique_ptr<v8::Global<v8::Script>> scriptWrapper = std::move(it->second);
     536             :   m_compiledScripts.erase(it);
     537         195 :   v8::Local<v8::Script> script = scriptWrapper->Get(m_inspector->isolate());
     538         195 :   if (script.IsEmpty()) {
     539           0 :     callback->sendFailure(Response::Error("Script execution failed"));
     540           0 :     return;
     541             :   }
     542             : 
     543         195 :   if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI();
     544             : 
     545             :   v8::MaybeLocal<v8::Value> maybeResultValue;
     546             :   {
     547             :     v8::MicrotasksScope microtasksScope(m_inspector->isolate(),
     548         390 :                                         v8::MicrotasksScope::kRunMicrotasks);
     549         195 :     maybeResultValue = script->Run(scope.context());
     550             :   }
     551             : 
     552             :   // Re-initialize after running client's code, as it could have destroyed
     553             :   // context or session.
     554         390 :   response = scope.initialize();
     555         195 :   if (!response.isSuccess()) {
     556           0 :     callback->sendFailure(response);
     557           0 :     return;
     558             :   }
     559             : 
     560         195 :   if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
     561             :     wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
     562             :                             scope.tryCatch(), objectGroup.fromMaybe(""),
     563             :                             returnByValue.fromMaybe(false),
     564         900 :                             generatePreview.fromMaybe(false), callback.get());
     565         180 :     return;
     566             :   }
     567             :   scope.injectedScript()->addPromiseCallback(
     568             :       m_session, maybeResultValue.ToLocalChecked(),
     569             :       objectGroup.fromMaybe(""), returnByValue.fromMaybe(false),
     570             :       generatePreview.fromMaybe(false),
     571          90 :       EvaluateCallbackWrapper<RunScriptCallback>::wrap(std::move(callback)));
     572             : }
     573             : 
     574          65 : Response V8RuntimeAgentImpl::queryObjects(
     575             :     const String16& prototypeObjectId,
     576             :     std::unique_ptr<protocol::Runtime::RemoteObject>* objects) {
     577          65 :   InjectedScript::ObjectScope scope(m_session, prototypeObjectId);
     578          65 :   Response response = scope.initialize();
     579          65 :   if (!response.isSuccess()) return response;
     580          65 :   if (!scope.object()->IsObject()) {
     581           0 :     return Response::Error("Prototype should be instance of Object");
     582             :   }
     583             :   v8::Local<v8::Array> resultArray = m_inspector->debugger()->queryObjects(
     584         130 :       scope.context(), v8::Local<v8::Object>::Cast(scope.object()));
     585             :   return scope.injectedScript()->wrapObject(
     586         130 :       resultArray, scope.objectGroupName(), false, false, objects);
     587             : }
     588             : 
     589          35 : Response V8RuntimeAgentImpl::globalLexicalScopeNames(
     590             :     Maybe<int> executionContextId,
     591             :     std::unique_ptr<protocol::Array<String16>>* outNames) {
     592          35 :   int contextId = 0;
     593             :   Response response = ensureContext(m_inspector, m_session->contextGroupId(),
     594          70 :                                     std::move(executionContextId), &contextId);
     595          35 :   if (!response.isSuccess()) return response;
     596             : 
     597          70 :   InjectedScript::ContextScope scope(m_session, contextId);
     598          70 :   response = scope.initialize();
     599          35 :   if (!response.isSuccess()) return response;
     600             : 
     601          70 :   v8::PersistentValueVector<v8::String> names(m_inspector->isolate());
     602          35 :   v8::debug::GlobalLexicalScopeNames(scope.context(), &names);
     603             :   *outNames = protocol::Array<String16>::create();
     604         265 :   for (size_t i = 0; i < names.Size(); ++i) {
     605         230 :     (*outNames)->addItem(toProtocolString(names.Get(i)));
     606             :   }
     607          35 :   return Response::OK();
     608             : }
     609             : 
     610          40 : void V8RuntimeAgentImpl::restore() {
     611          80 :   if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
     612          40 :     return;
     613          35 :   m_frontend.executionContextsCleared();
     614          70 :   enable();
     615          70 :   if (m_state->booleanProperty(
     616          70 :           V8RuntimeAgentImplState::customObjectFormatterEnabled, false))
     617           5 :     m_session->setCustomObjectFormatterEnabled(true);
     618             : }
     619             : 
     620         605 : Response V8RuntimeAgentImpl::enable() {
     621         605 :   if (m_enabled) return Response::OK();
     622         595 :   m_inspector->client()->beginEnsureAllContextsInGroup(
     623        1190 :       m_session->contextGroupId());
     624         595 :   m_enabled = true;
     625        1190 :   m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, true);
     626         595 :   m_inspector->enableStackCapturingIfNeeded();
     627         595 :   m_session->reportAllContexts(this);
     628             :   V8ConsoleMessageStorage* storage =
     629        1190 :       m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
     630        5915 :   for (const auto& message : storage->messages()) {
     631        5320 :     if (!reportMessage(message.get(), false)) break;
     632             :   }
     633         595 :   return Response::OK();
     634             : }
     635             : 
     636        3751 : Response V8RuntimeAgentImpl::disable() {
     637        3751 :   if (!m_enabled) return Response::OK();
     638         595 :   m_enabled = false;
     639        1190 :   m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false);
     640        1190 :   m_inspector->disableStackCapturingIfNeeded();
     641        1190 :   m_session->setCustomObjectFormatterEnabled(false);
     642         595 :   reset();
     643         595 :   m_inspector->client()->endEnsureAllContextsInGroup(
     644        1190 :       m_session->contextGroupId());
     645         595 :   return Response::OK();
     646             : }
     647             : 
     648         595 : void V8RuntimeAgentImpl::reset() {
     649             :   m_compiledScripts.clear();
     650         595 :   if (m_enabled) {
     651           0 :     int sessionId = m_session->sessionId();
     652             :     m_inspector->forEachContext(m_session->contextGroupId(),
     653             :                                 [&sessionId](InspectedContext* context) {
     654           0 :                                   context->setReported(sessionId, false);
     655           0 :                                 });
     656           0 :     m_frontend.executionContextsCleared();
     657             :   }
     658         595 : }
     659             : 
     660        3068 : void V8RuntimeAgentImpl::reportExecutionContextCreated(
     661         615 :     InspectedContext* context) {
     662        6136 :   if (!m_enabled) return;
     663         615 :   context->setReported(m_session->sessionId(), true);
     664             :   std::unique_ptr<protocol::Runtime::ExecutionContextDescription> description =
     665             :       protocol::Runtime::ExecutionContextDescription::create()
     666         615 :           .setId(context->contextId())
     667         615 :           .setName(context->humanReadableName())
     668         615 :           .setOrigin(context->origin())
     669             :           .build();
     670         615 :   if (!context->auxData().isEmpty())
     671             :     description->setAuxData(protocol::DictionaryValue::cast(
     672           0 :         protocol::StringUtil::parseJSON(context->auxData())));
     673        1230 :   m_frontend.executionContextCreated(std::move(description));
     674             : }
     675             : 
     676          30 : void V8RuntimeAgentImpl::reportExecutionContextDestroyed(
     677          25 :     InspectedContext* context) {
     678          55 :   if (m_enabled && context->isReported(m_session->sessionId())) {
     679          50 :     context->setReported(m_session->sessionId(), false);
     680          25 :     m_frontend.executionContextDestroyed(context->contextId());
     681             :   }
     682          30 : }
     683             : 
     684          80 : void V8RuntimeAgentImpl::inspect(
     685             :     std::unique_ptr<protocol::Runtime::RemoteObject> objectToInspect,
     686             :     std::unique_ptr<protocol::DictionaryValue> hints) {
     687          80 :   if (m_enabled)
     688         240 :     m_frontend.inspectRequested(std::move(objectToInspect), std::move(hints));
     689          80 : }
     690             : 
     691        6780 : void V8RuntimeAgentImpl::messageAdded(V8ConsoleMessage* message) {
     692        6780 :   if (m_enabled) reportMessage(message, true);
     693        6780 : }
     694             : 
     695        6625 : bool V8RuntimeAgentImpl::reportMessage(V8ConsoleMessage* message,
     696             :                                        bool generatePreview) {
     697       13250 :   message->reportToFrontend(&m_frontend, m_session, generatePreview);
     698        6625 :   m_frontend.flush();
     699       13250 :   return m_inspector->hasConsoleMessageStorage(m_session->contextGroupId());
     700             : }
     701             : 
     702             : }  // namespace v8_inspector

Generated by: LCOV version 1.10