LCOV - code coverage report
Current view: top level - src/inspector - v8-debugger-script.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 211 232 90.9 %
Date: 2019-03-21 Functions: 48 58 82.8 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/inspector/v8-debugger-script.h"
       6             : 
       7             : #include "src/inspector/inspected-context.h"
       8             : #include "src/inspector/string-util.h"
       9             : #include "src/inspector/v8-debugger-agent-impl.h"
      10             : #include "src/inspector/v8-inspector-impl.h"
      11             : #include "src/inspector/wasm-translation.h"
      12             : #include "src/v8memory.h"
      13             : 
      14             : namespace v8_inspector {
      15             : 
      16             : namespace {
      17             : 
      18             : const char kGlobalDebuggerScriptHandleLabel[] = "DevTools debugger";
      19             : 
      20             : // Hash algorithm for substrings is described in "Über die Komplexität der
      21             : // Multiplikation in
      22             : // eingeschränkten Branchingprogrammmodellen" by Woelfe.
      23             : // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
      24       55887 : String16 calculateHash(v8::Isolate* isolate, v8::Local<v8::String> source) {
      25             :   static uint64_t prime[] = {0x3FB75161, 0xAB1F4E4F, 0x82675BC5, 0xCD924D35,
      26             :                              0x81ABE279};
      27             :   static uint64_t random[] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476,
      28             :                               0xC3D2E1F0};
      29             :   static uint32_t randomOdd[] = {0xB4663807, 0xCC322BF5, 0xD4F91BBD, 0xA7BEA11D,
      30             :                                  0x8F462907};
      31             : 
      32       55887 :   uint64_t hashes[] = {0, 0, 0, 0, 0};
      33       55887 :   uint64_t zi[] = {1, 1, 1, 1, 1};
      34             : 
      35             :   const size_t hashesSize = arraysize(hashes);
      36             : 
      37             :   size_t current = 0;
      38             : 
      39       55887 :   std::unique_ptr<UChar[]> buffer(new UChar[source->Length()]);
      40       55887 :   int written = source->Write(
      41       55887 :       isolate, reinterpret_cast<uint16_t*>(buffer.get()), 0, source->Length());
      42             : 
      43             :   const uint32_t* data = nullptr;
      44       55887 :   size_t sizeInBytes = sizeof(UChar) * written;
      45             :   data = reinterpret_cast<const uint32_t*>(buffer.get());
      46   296109903 :   for (size_t i = 0; i < sizeInBytes / 4; ++i) {
      47             :     uint32_t d = v8::internal::ReadUnalignedUInt32(
      48   148027008 :         reinterpret_cast<v8::internal::Address>(data + i));
      49             : #if V8_TARGET_LITTLE_ENDIAN
      50             :     uint32_t v = d;
      51             : #else
      52             :     uint32_t v = (d << 16) | (d >> 16);
      53             : #endif
      54   148027008 :     uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF;
      55   148027008 :     hashes[current] = (hashes[current] + zi[current] * xi) % prime[current];
      56   148027008 :     zi[current] = (zi[current] * random[current]) % prime[current];
      57   148027008 :     current = current == hashesSize - 1 ? 0 : current + 1;
      58             :   }
      59       55887 :   if (sizeInBytes % 4) {
      60             :     uint32_t v = 0;
      61             :     const uint8_t* data_8b = reinterpret_cast<const uint8_t*>(data);
      62       82005 :     for (size_t i = sizeInBytes - sizeInBytes % 4; i < sizeInBytes; ++i) {
      63       54670 :       v <<= 8;
      64             : #if V8_TARGET_LITTLE_ENDIAN
      65       54670 :       v |= data_8b[i];
      66             : #else
      67             :       if (i % 2) {
      68             :         v |= data_8b[i - 1];
      69             :       } else {
      70             :         v |= data_8b[i + 1];
      71             :       }
      72             : #endif
      73             :     }
      74       27335 :     uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF;
      75       27335 :     hashes[current] = (hashes[current] + zi[current] * xi) % prime[current];
      76       27335 :     zi[current] = (zi[current] * random[current]) % prime[current];
      77             :     current = current == hashesSize - 1 ? 0 : current + 1;
      78             :   }
      79             : 
      80      614757 :   for (size_t i = 0; i < hashesSize; ++i)
      81      279435 :     hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i];
      82             : 
      83       55887 :   String16Builder hash;
      84      614757 :   for (size_t i = 0; i < hashesSize; ++i)
      85      279435 :     hash.appendUnsignedAsHex(static_cast<uint32_t>(hashes[i]));
      86      111774 :   return hash.toString();
      87             : }
      88             : 
      89         116 : void TranslateProtocolLocationToV8Location(WasmTranslation* wasmTranslation,
      90             :                                            v8::debug::Location* loc,
      91             :                                            const String16& scriptId,
      92             :                                            const String16& expectedV8ScriptId) {
      93         116 :   if (loc->IsEmpty()) return;
      94         116 :   int lineNumber = loc->GetLineNumber();
      95         116 :   int columnNumber = loc->GetColumnNumber();
      96             :   String16 translatedScriptId = scriptId;
      97             :   wasmTranslation->TranslateProtocolLocationToWasmScriptLocation(
      98         116 :       &translatedScriptId, &lineNumber, &columnNumber);
      99             :   DCHECK_EQ(expectedV8ScriptId.utf8(), translatedScriptId.utf8());
     100         116 :   *loc = v8::debug::Location(lineNumber, columnNumber);
     101             : }
     102             : 
     103         148 : void TranslateV8LocationToProtocolLocation(
     104             :     WasmTranslation* wasmTranslation, v8::debug::Location* loc,
     105             :     const String16& scriptId, const String16& expectedProtocolScriptId) {
     106         148 :   int lineNumber = loc->GetLineNumber();
     107         148 :   int columnNumber = loc->GetColumnNumber();
     108             :   String16 translatedScriptId = scriptId;
     109             :   wasmTranslation->TranslateWasmScriptLocationToProtocolLocation(
     110         148 :       &translatedScriptId, &lineNumber, &columnNumber);
     111             :   DCHECK_EQ(expectedProtocolScriptId.utf8(), translatedScriptId.utf8());
     112         148 :   *loc = v8::debug::Location(lineNumber, columnNumber);
     113         148 : }
     114             : 
     115      167661 : class ActualScript : public V8DebuggerScript {
     116             :   friend class V8DebuggerScript;
     117             : 
     118             :  public:
     119       55887 :   ActualScript(v8::Isolate* isolate, v8::Local<v8::debug::Script> script,
     120             :                bool isLiveEdit, V8DebuggerAgentImpl* agent,
     121             :                V8InspectorClient* client)
     122      111774 :       : V8DebuggerScript(isolate, String16::fromInteger(script->Id()),
     123      111774 :                          GetScriptURL(isolate, script, client)),
     124             :         m_agent(agent),
     125      223548 :         m_isLiveEdit(isLiveEdit) {
     126       55887 :     Initialize(script);
     127       55887 :   }
     128             : 
     129       55887 :   bool isLiveEdit() const override { return m_isLiveEdit; }
     130       55887 :   bool isModule() const override { return m_isModule; }
     131             : 
     132        1534 :   String16 source(size_t pos, size_t len) const override {
     133        3068 :     v8::HandleScope scope(m_isolate);
     134             :     v8::Local<v8::String> v8Source;
     135        3068 :     if (!script()->Source().ToLocal(&v8Source)) return String16();
     136        1534 :     if (pos >= static_cast<size_t>(v8Source->Length())) return String16();
     137             :     size_t substringLength =
     138        3040 :         std::min(len, static_cast<size_t>(v8Source->Length()) - pos);
     139        1520 :     std::unique_ptr<UChar[]> buffer(new UChar[substringLength]);
     140        1520 :     v8Source->Write(m_isolate, reinterpret_cast<uint16_t*>(buffer.get()),
     141        1520 :                     static_cast<int>(pos), static_cast<int>(substringLength));
     142        1520 :     return String16(buffer.get(), substringLength);
     143             :   }
     144       58114 :   int startLine() const override { return m_startLine; }
     145       55887 :   int startColumn() const override { return m_startColumn; }
     146       58104 :   int endLine() const override { return m_endLine; }
     147       55887 :   int endColumn() const override { return m_endColumn; }
     148       55701 :   bool isSourceLoadedLazily() const override { return false; }
     149       76866 :   int length() const override {
     150      153732 :     v8::HandleScope scope(m_isolate);
     151             :     v8::Local<v8::String> v8Source;
     152      230598 :     return script()->Source().ToLocal(&v8Source) ? v8Source->Length() : 0;
     153             :   }
     154             : 
     155       55887 :   const String16& sourceMappingURL() const override {
     156       55887 :     return m_sourceMappingURL;
     157             :   }
     158             : 
     159         186 :   void setSourceMappingURL(const String16& sourceMappingURL) override {
     160             :     m_sourceMappingURL = sourceMappingURL;
     161         186 :   }
     162             : 
     163          50 :   void setSource(const String16& newSource, bool preview,
     164             :                  v8::debug::LiveEditResult* result) override {
     165          50 :     v8::EscapableHandleScope scope(m_isolate);
     166          50 :     v8::Local<v8::String> v8Source = toV8String(m_isolate, newSource);
     167         100 :     if (!m_script.Get(m_isolate)->SetScriptSource(v8Source, preview, result)) {
     168          10 :       result->message = scope.Escape(result->message);
     169          10 :       return;
     170             :     }
     171          40 :     if (preview) return;
     172          80 :     m_hash = String16();
     173          40 :     Initialize(scope.Escape(result->script));
     174             :   }
     175             : 
     176         235 :   bool getPossibleBreakpoints(
     177             :       const v8::debug::Location& start, const v8::debug::Location& end,
     178             :       bool restrictToFunction,
     179             :       std::vector<v8::debug::BreakLocation>* locations) override {
     180         470 :     v8::HandleScope scope(m_isolate);
     181         235 :     v8::Local<v8::debug::Script> script = m_script.Get(m_isolate);
     182             :     std::vector<v8::debug::BreakLocation> allLocations;
     183         235 :     if (!script->GetPossibleBreakpoints(start, end, restrictToFunction,
     184             :                                         &allLocations)) {
     185             :       return false;
     186             :     }
     187         230 :     if (!allLocations.size()) return true;
     188         205 :     v8::debug::BreakLocation current = allLocations[0];
     189        9635 :     for (size_t i = 1; i < allLocations.size(); ++i) {
     190        7545 :       if (allLocations[i].GetLineNumber() == current.GetLineNumber() &&
     191        2830 :           allLocations[i].GetColumnNumber() == current.GetColumnNumber()) {
     192         740 :         if (allLocations[i].type() != v8::debug::kCommonBreakLocation) {
     193             :           DCHECK(allLocations[i].type() == v8::debug::kCallBreakLocation ||
     194             :                  allLocations[i].type() == v8::debug::kReturnBreakLocation);
     195             :           // debugger can returns more then one break location at the same
     196             :           // source location, e.g. foo() - in this case there are two break
     197             :           // locations before foo: for statement and for function call, we can
     198             :           // merge them for inspector and report only one with call type.
     199         435 :           current = allLocations[i];
     200             :         }
     201             :       } else {
     202             :         // we assume that returned break locations are sorted.
     203             :         DCHECK(
     204             :             allLocations[i].GetLineNumber() > current.GetLineNumber() ||
     205             :             (allLocations[i].GetColumnNumber() >= current.GetColumnNumber() &&
     206             :              allLocations[i].GetLineNumber() == current.GetLineNumber()));
     207        3975 :         locations->push_back(current);
     208        3975 :         current = allLocations[i];
     209             :       }
     210             :     }
     211         205 :     locations->push_back(current);
     212         205 :     return true;
     213             :   }
     214             : 
     215      112020 :   void resetBlackboxedStateCache() override {
     216      224040 :     v8::HandleScope scope(m_isolate);
     217      224040 :     v8::debug::ResetBlackboxedStateCache(m_isolate, m_script.Get(m_isolate));
     218      112020 :   }
     219             : 
     220         310 :   int offset(int lineNumber, int columnNumber) const override {
     221         620 :     v8::HandleScope scope(m_isolate);
     222         620 :     return m_script.Get(m_isolate)->GetSourceOffset(
     223         620 :         v8::debug::Location(lineNumber, columnNumber));
     224             :   }
     225             : 
     226          60 :   v8::debug::Location location(int offset) const override {
     227         120 :     v8::HandleScope scope(m_isolate);
     228         180 :     return m_script.Get(m_isolate)->GetSourceLocation(offset);
     229             :   }
     230             : 
     231        2062 :   bool setBreakpoint(const String16& condition, v8::debug::Location* location,
     232             :                      int* id) const override {
     233        4124 :     v8::HandleScope scope(m_isolate);
     234        2062 :     return script()->SetBreakpoint(toV8String(m_isolate, condition), location,
     235        4124 :                                    id);
     236             :   }
     237             : 
     238       55952 :   const String16& hash() const override {
     239       55952 :     if (!m_hash.isEmpty()) return m_hash;
     240      111774 :     v8::HandleScope scope(m_isolate);
     241             :     v8::Local<v8::String> v8Source;
     242      111774 :     if (script()->Source().ToLocal(&v8Source)) {
     243      111774 :       m_hash = calculateHash(m_isolate, v8Source);
     244             :     }
     245             :     DCHECK(!m_hash.isEmpty());
     246       55887 :     return m_hash;
     247             :   }
     248             : 
     249             :  private:
     250       55887 :   static String16 GetScriptURL(v8::Isolate* isolate,
     251             :                                v8::Local<v8::debug::Script> script,
     252             :                                V8InspectorClient* client) {
     253             :     v8::Local<v8::String> sourceURL;
     254      111774 :     if (script->SourceURL().ToLocal(&sourceURL) && sourceURL->Length() > 0)
     255        2195 :       return toProtocolString(isolate, sourceURL);
     256             :     v8::Local<v8::String> v8Name;
     257      107384 :     if (script->Name().ToLocal(&v8Name) && v8Name->Length() > 0) {
     258       16022 :       String16 name = toProtocolString(isolate, v8Name);
     259             :       std::unique_ptr<StringBuffer> url =
     260       16022 :           client->resourceNameToUrl(toStringView(name));
     261       16022 :       return url ? toString16(url->string()) : name;
     262             :     }
     263       37670 :     return String16();
     264             :   }
     265             : 
     266           0 :   v8::Local<v8::debug::Script> script() const override {
     267      136349 :     return m_script.Get(m_isolate);
     268             :   }
     269             : 
     270       55927 :   void Initialize(v8::Local<v8::debug::Script> script) {
     271             :     v8::Local<v8::String> tmp;
     272             :     m_hasSourceURLComment =
     273      111854 :         script->SourceURL().ToLocal(&tmp) && tmp->Length() > 0;
     274      111854 :     if (script->SourceMappingURL().ToLocal(&tmp))
     275        1052 :       m_sourceMappingURL = toProtocolString(m_isolate, tmp);
     276       55927 :     m_startLine = script->LineOffset();
     277       55927 :     m_startColumn = script->ColumnOffset();
     278       55927 :     std::vector<int> lineEnds = script->LineEnds();
     279       55927 :     CHECK(lineEnds.size());
     280      111854 :     int source_length = lineEnds[lineEnds.size() - 1];
     281       55927 :     if (lineEnds.size()) {
     282       55927 :       m_endLine = static_cast<int>(lineEnds.size()) + m_startLine - 1;
     283       55927 :       if (lineEnds.size() > 1) {
     284       42898 :         m_endColumn = source_length - lineEnds[lineEnds.size() - 2] - 1;
     285             :       } else {
     286       34478 :         m_endColumn = source_length + m_startColumn;
     287             :       }
     288             :     } else {
     289           0 :       m_endLine = m_startLine;
     290           0 :       m_endColumn = m_startColumn;
     291             :     }
     292             : 
     293      111854 :     USE(script->ContextId().To(&m_executionContextId));
     294             : 
     295       55927 :     m_isModule = script->IsModule();
     296             : 
     297       55927 :     m_script.Reset(m_isolate, script);
     298             :     m_script.AnnotateStrongRetainer(kGlobalDebuggerScriptHandleLabel);
     299       55927 :   }
     300             : 
     301       55887 :   void MakeWeak() override {
     302             :     m_script.SetWeak(
     303             :         this,
     304       20850 :         [](const v8::WeakCallbackInfo<ActualScript>& data) {
     305             :           data.GetParameter()->WeakCallback();
     306       20850 :         },
     307             :         v8::WeakCallbackType::kFinalizer);
     308       55887 :   }
     309             : 
     310             :   void WeakCallback() {
     311             :     m_script.ClearWeak();
     312       20850 :     m_agent->ScriptCollected(this);
     313             :   }
     314             : 
     315             :   V8DebuggerAgentImpl* m_agent;
     316             :   String16 m_sourceMappingURL;
     317             :   bool m_isLiveEdit = false;
     318             :   bool m_isModule = false;
     319             :   mutable String16 m_hash;
     320             :   int m_startLine = 0;
     321             :   int m_startColumn = 0;
     322             :   int m_endLine = 0;
     323             :   int m_endColumn = 0;
     324             :   v8::Global<v8::debug::Script> m_script;
     325             : };
     326             : 
     327         252 : class WasmVirtualScript : public V8DebuggerScript {
     328             :   friend class V8DebuggerScript;
     329             : 
     330             :  public:
     331          84 :   WasmVirtualScript(v8::Isolate* isolate, WasmTranslation* wasmTranslation,
     332             :                     v8::Local<v8::debug::WasmScript> script, String16 id,
     333             :                     String16 url, int functionIndex)
     334             :       : V8DebuggerScript(isolate, std::move(id), std::move(url)),
     335             :         m_script(isolate, script),
     336             :         m_wasmTranslation(wasmTranslation),
     337         336 :         m_functionIndex(functionIndex) {
     338             :     m_script.AnnotateStrongRetainer(kGlobalDebuggerScriptHandleLabel);
     339         168 :     m_executionContextId = script->ContextId().ToChecked();
     340          84 :   }
     341             : 
     342          84 :   const String16& sourceMappingURL() const override { return emptyString(); }
     343          84 :   bool isLiveEdit() const override { return false; }
     344          84 :   bool isModule() const override { return false; }
     345           0 :   void setSourceMappingURL(const String16&) override {}
     346           0 :   void setSource(const String16&, bool, v8::debug::LiveEditResult*) override {
     347           0 :     UNREACHABLE();
     348             :   }
     349          84 :   bool isSourceLoadedLazily() const override { return true; }
     350          52 :   String16 source(size_t pos, size_t len) const override {
     351          52 :     return m_wasmTranslation->GetSource(m_id, m_functionIndex)
     352          52 :         .substring(pos, len);
     353             :   }
     354          76 :   int startLine() const override {
     355          76 :     return m_wasmTranslation->GetStartLine(m_id, m_functionIndex);
     356             :   }
     357           0 :   int startColumn() const override {
     358           0 :     return m_wasmTranslation->GetStartColumn(m_id, m_functionIndex);
     359             :   }
     360          76 :   int endLine() const override {
     361          76 :     return m_wasmTranslation->GetEndLine(m_id, m_functionIndex);
     362             :   }
     363           0 :   int endColumn() const override {
     364           0 :     return m_wasmTranslation->GetEndColumn(m_id, m_functionIndex);
     365             :   }
     366           0 :   int length() const override {
     367           0 :     return static_cast<int>(source(0, UINT_MAX).length());
     368             :   }
     369             : 
     370          24 :   bool getPossibleBreakpoints(
     371             :       const v8::debug::Location& start, const v8::debug::Location& end,
     372             :       bool restrictToFunction,
     373             :       std::vector<v8::debug::BreakLocation>* locations) override {
     374          48 :     v8::HandleScope scope(m_isolate);
     375          24 :     v8::Local<v8::debug::Script> script = m_script.Get(m_isolate);
     376          24 :     String16 v8ScriptId = String16::fromInteger(script->Id());
     377             : 
     378          24 :     v8::debug::Location translatedStart = start;
     379          24 :     TranslateProtocolLocationToV8Location(m_wasmTranslation, &translatedStart,
     380          24 :                                           scriptId(), v8ScriptId);
     381             : 
     382          24 :     v8::debug::Location translatedEnd = end;
     383          24 :     if (translatedEnd.IsEmpty()) {
     384             :       // Stop before the start of the next function.
     385             :       translatedEnd =
     386           8 :           v8::debug::Location(translatedStart.GetLineNumber() + 1, 0);
     387             :     } else {
     388          16 :       TranslateProtocolLocationToV8Location(m_wasmTranslation, &translatedEnd,
     389          16 :                                             scriptId(), v8ScriptId);
     390             :     }
     391             : 
     392          24 :     bool success = script->GetPossibleBreakpoints(
     393          24 :         translatedStart, translatedEnd, restrictToFunction, locations);
     394          96 :     for (v8::debug::BreakLocation& loc : *locations) {
     395          72 :       TranslateV8LocationToProtocolLocation(m_wasmTranslation, &loc, v8ScriptId,
     396          72 :                                             scriptId());
     397             :     }
     398          24 :     return success;
     399             :   }
     400             : 
     401         168 :   void resetBlackboxedStateCache() override {}
     402             : 
     403           0 :   int offset(int lineNumber, int columnNumber) const override {
     404           0 :     return kNoOffset;
     405             :   }
     406             : 
     407           0 :   v8::debug::Location location(int offset) const override {
     408           0 :     return v8::debug::Location();
     409             :   }
     410             : 
     411          76 :   bool setBreakpoint(const String16& condition, v8::debug::Location* location,
     412             :                      int* id) const override {
     413         152 :     v8::HandleScope scope(m_isolate);
     414          76 :     v8::Local<v8::debug::Script> script = m_script.Get(m_isolate);
     415          76 :     String16 v8ScriptId = String16::fromInteger(script->Id());
     416             : 
     417          76 :     TranslateProtocolLocationToV8Location(m_wasmTranslation, location,
     418          76 :                                           scriptId(), v8ScriptId);
     419          76 :     if (location->IsEmpty()) return false;
     420          76 :     if (!script->SetBreakpoint(toV8String(m_isolate, condition), location, id))
     421             :       return false;
     422          76 :     TranslateV8LocationToProtocolLocation(m_wasmTranslation, location,
     423          76 :                                           v8ScriptId, scriptId());
     424          76 :     return true;
     425             :   }
     426             : 
     427          84 :   const String16& hash() const override {
     428          84 :     if (m_hash.isEmpty()) {
     429         168 :       m_hash = m_wasmTranslation->GetHash(m_id, m_functionIndex);
     430             :     }
     431          84 :     return m_hash;
     432             :   }
     433             : 
     434          84 :   void MakeWeak() override {}
     435             : 
     436             :  private:
     437          84 :   static const String16& emptyString() {
     438             :     // On the heap and leaked so that no destructor needs to run at exit time.
     439         124 :     static const String16* singleEmptyString = new String16;
     440          84 :     return *singleEmptyString;
     441             :   }
     442             : 
     443           0 :   v8::Local<v8::debug::Script> script() const override {
     444           0 :     return m_script.Get(m_isolate);
     445             :   }
     446             : 
     447             :   v8::Global<v8::debug::WasmScript> m_script;
     448             :   WasmTranslation* m_wasmTranslation;
     449             :   int m_functionIndex;
     450             :   mutable String16 m_hash;
     451             : };
     452             : 
     453             : }  // namespace
     454             : 
     455       55887 : std::unique_ptr<V8DebuggerScript> V8DebuggerScript::Create(
     456             :     v8::Isolate* isolate, v8::Local<v8::debug::Script> scriptObj,
     457             :     bool isLiveEdit, V8DebuggerAgentImpl* agent, V8InspectorClient* client) {
     458      111774 :   return v8::base::make_unique<ActualScript>(isolate, scriptObj, isLiveEdit,
     459       55887 :                                              agent, client);
     460             : }
     461             : 
     462          84 : std::unique_ptr<V8DebuggerScript> V8DebuggerScript::CreateWasm(
     463             :     v8::Isolate* isolate, WasmTranslation* wasmTranslation,
     464             :     v8::Local<v8::debug::WasmScript> underlyingScript, String16 id,
     465             :     String16 url, int functionIndex) {
     466         168 :   return v8::base::make_unique<WasmVirtualScript>(
     467             :       isolate, wasmTranslation, underlyingScript, std::move(id), std::move(url),
     468          84 :       functionIndex);
     469             : }
     470             : 
     471       55971 : V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, String16 id,
     472             :                                    String16 url)
     473      111942 :     : m_id(std::move(id)), m_url(std::move(url)), m_isolate(isolate) {}
     474             : 
     475             : V8DebuggerScript::~V8DebuggerScript() = default;
     476             : 
     477         186 : void V8DebuggerScript::setSourceURL(const String16& sourceURL) {
     478         186 :   if (sourceURL.length() > 0) {
     479          25 :     m_hasSourceURLComment = true;
     480             :     m_url = sourceURL;
     481             :   }
     482         186 : }
     483             : 
     484           0 : bool V8DebuggerScript::setBreakpoint(const String16& condition,
     485             :                                      v8::debug::Location* loc, int* id) const {
     486           0 :   v8::HandleScope scope(m_isolate);
     487           0 :   return script()->SetBreakpoint(toV8String(m_isolate, condition), loc, id);
     488             : }
     489             : 
     490             : }  // namespace v8_inspector

Generated by: LCOV version 1.10