• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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/inspected-context.h"
6 
7 #include "include/v8-context.h"
8 #include "include/v8-inspector.h"
9 #include "src/debug/debug-interface.h"
10 #include "src/inspector/injected-script.h"
11 #include "src/inspector/string-util.h"
12 #include "src/inspector/v8-console.h"
13 #include "src/inspector/v8-inspector-impl.h"
14 
15 namespace v8_inspector {
16 
17 class InspectedContext::WeakCallbackData {
18  public:
WeakCallbackData(InspectedContext * context,V8InspectorImpl * inspector,int groupId,int contextId)19   WeakCallbackData(InspectedContext* context, V8InspectorImpl* inspector,
20                    int groupId, int contextId)
21       : m_context(context),
22         m_inspector(inspector),
23         m_groupId(groupId),
24         m_contextId(contextId) {}
25 
resetContext(const v8::WeakCallbackInfo<WeakCallbackData> & data)26   static void resetContext(const v8::WeakCallbackInfo<WeakCallbackData>& data) {
27     // InspectedContext is alive here because weak handler is still alive.
28     data.GetParameter()->m_context->m_weakCallbackData = nullptr;
29     data.GetParameter()->m_context->m_context.Reset();
30     data.SetSecondPassCallback(&callContextCollected);
31   }
32 
callContextCollected(const v8::WeakCallbackInfo<WeakCallbackData> & data)33   static void callContextCollected(
34       const v8::WeakCallbackInfo<WeakCallbackData>& data) {
35     // InspectedContext can be dead here since anything can happen between first
36     // and second pass callback.
37     WeakCallbackData* callbackData = data.GetParameter();
38     callbackData->m_inspector->contextCollected(callbackData->m_groupId,
39                                                 callbackData->m_contextId);
40     delete callbackData;
41   }
42 
43  private:
44   InspectedContext* m_context;
45   V8InspectorImpl* m_inspector;
46   int m_groupId;
47   int m_contextId;
48 };
49 
InspectedContext(V8InspectorImpl * inspector,const V8ContextInfo & info,int contextId)50 InspectedContext::InspectedContext(V8InspectorImpl* inspector,
51                                    const V8ContextInfo& info, int contextId)
52     : m_inspector(inspector),
53       m_context(info.context->GetIsolate(), info.context),
54       m_contextId(contextId),
55       m_contextGroupId(info.contextGroupId),
56       m_origin(toString16(info.origin)),
57       m_humanReadableName(toString16(info.humanReadableName)),
58       m_auxData(toString16(info.auxData)),
59       m_uniqueId(internal::V8DebuggerId::generate(inspector)) {
60   v8::debug::SetContextId(info.context, contextId);
61   m_weakCallbackData =
62       new WeakCallbackData(this, m_inspector, m_contextGroupId, m_contextId);
63   m_context.SetWeak(m_weakCallbackData,
64                     &InspectedContext::WeakCallbackData::resetContext,
65                     v8::WeakCallbackType::kParameter);
66 
67   v8::Context::Scope contextScope(info.context);
68   v8::HandleScope handleScope(info.context->GetIsolate());
69   v8::Local<v8::Object> global = info.context->Global();
70   v8::Local<v8::Value> console;
71   if (!global
72            ->Get(info.context,
73                  toV8String(info.context->GetIsolate(), "console"))
74            .ToLocal(&console) ||
75       !console->IsObject()) {
76     return;
77   }
78 
79   if (v8::debug::isExperimentalAsyncStackTaggingApiEnabled()) {
80     m_inspector->console()->installAsyncStackTaggingAPI(
81         info.context, console.As<v8::Object>());
82   }
83 
84   if (info.hasMemoryOnConsole) {
85     m_inspector->console()->installMemoryGetter(info.context,
86                                                 console.As<v8::Object>());
87   }
88 }
89 
~InspectedContext()90 InspectedContext::~InspectedContext() {
91   // If we destory InspectedContext before weak callback is invoked then we need
92   // to delete data here.
93   if (!m_context.IsEmpty()) delete m_weakCallbackData;
94 }
95 
96 // static
contextId(v8::Local<v8::Context> context)97 int InspectedContext::contextId(v8::Local<v8::Context> context) {
98   return v8::debug::GetContextId(context);
99 }
100 
context() const101 v8::Local<v8::Context> InspectedContext::context() const {
102   return m_context.Get(isolate());
103 }
104 
isolate() const105 v8::Isolate* InspectedContext::isolate() const {
106   return m_inspector->isolate();
107 }
108 
isReported(int sessionId) const109 bool InspectedContext::isReported(int sessionId) const {
110   return m_reportedSessionIds.find(sessionId) != m_reportedSessionIds.cend();
111 }
112 
setReported(int sessionId,bool reported)113 void InspectedContext::setReported(int sessionId, bool reported) {
114   if (reported)
115     m_reportedSessionIds.insert(sessionId);
116   else
117     m_reportedSessionIds.erase(sessionId);
118 }
119 
getInjectedScript(int sessionId)120 InjectedScript* InspectedContext::getInjectedScript(int sessionId) {
121   auto it = m_injectedScripts.find(sessionId);
122   return it == m_injectedScripts.end() ? nullptr : it->second.get();
123 }
124 
createInjectedScript(int sessionId)125 InjectedScript* InspectedContext::createInjectedScript(int sessionId) {
126   std::unique_ptr<InjectedScript> injectedScript =
127       std::make_unique<InjectedScript>(this, sessionId);
128   CHECK(m_injectedScripts.find(sessionId) == m_injectedScripts.end());
129   m_injectedScripts[sessionId] = std::move(injectedScript);
130   return getInjectedScript(sessionId);
131 }
132 
discardInjectedScript(int sessionId)133 void InspectedContext::discardInjectedScript(int sessionId) {
134   m_injectedScripts.erase(sessionId);
135 }
136 
addInternalObject(v8::Local<v8::Object> object,V8InternalValueType type)137 bool InspectedContext::addInternalObject(v8::Local<v8::Object> object,
138                                          V8InternalValueType type) {
139   if (m_internalObjects.IsEmpty()) {
140     m_internalObjects.Reset(isolate(),
141                             v8::debug::EphemeronTable::New(isolate()));
142   }
143   v8::Local<v8::debug::EphemeronTable> new_map =
144       m_internalObjects.Get(isolate())->Set(
145           isolate(), object,
146           v8::Integer::New(isolate(), static_cast<int>(type)));
147   m_internalObjects.Reset(isolate(), new_map);
148   return true;
149 }
150 
getInternalType(v8::Local<v8::Object> object)151 V8InternalValueType InspectedContext::getInternalType(
152     v8::Local<v8::Object> object) {
153   if (m_internalObjects.IsEmpty()) return V8InternalValueType::kNone;
154   v8::Local<v8::Value> typeValue;
155   if (!m_internalObjects.Get(isolate())
156            ->Get(isolate(), object)
157            .ToLocal(&typeValue) ||
158       !typeValue->IsUint32()) {
159     return V8InternalValueType::kNone;
160   }
161   return static_cast<V8InternalValueType>(typeValue.As<v8::Int32>()->Value());
162 }
163 
164 }  // namespace v8_inspector
165