v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8-inspector-impl.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-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
32
33#include <vector>
34
35#include "include/v8-context.h"
38#include "include/v8-platform.h"
55
56namespace v8_inspector {
57
58std::unique_ptr<V8Inspector> V8Inspector::create(v8::Isolate* isolate,
59 V8InspectorClient* client) {
60 return std::unique_ptr<V8Inspector>(new V8InspectorImpl(isolate, client));
61}
62
64 V8InspectorClient* client)
65 : m_isolate(isolate),
66 m_client(client),
67 m_debugger(new V8Debugger(isolate, this)),
68 m_lastExceptionId(0),
69 m_lastContextId(0) {
73}
74
79
83
84int V8InspectorImpl::contextGroupId(int contextId) const {
85 auto it = m_contextIdToGroupIdMap.find(contextId);
86 return it != m_contextIdToGroupIdMap.end() ? it->second : 0;
87}
88
90 internal::V8DebuggerId uniqueId) const {
91 auto it = m_uniqueIdToContextId.find(uniqueId.pair());
92 return it == m_uniqueIdToContextId.end() ? 0 : it->second;
93}
94
97 v8::Local<v8::UnboundScript> unboundScript;
99 .ToLocal(&unboundScript))
101 v8::MicrotasksScope microtasksScope(context,
103 v8::Context::Scope contextScope(context);
104 return unboundScript->BindToCurrentContext()->Run(context);
105}
106
115
119
123
125 int contextGroupId) {
126 auto storageIt = m_consoleStorageMap.find(contextGroupId);
127 if (storageIt == m_consoleStorageMap.end())
128 storageIt = m_consoleStorageMap
129 .insert(std::make_pair(
131 std::unique_ptr<V8ConsoleMessageStorage>(
133 .first;
134 return storageIt->second.get();
135}
136
138 auto storageIt = m_consoleStorageMap.find(contextGroupId);
139 return storageIt != m_consoleStorageMap.end();
140}
141
142std::unique_ptr<V8StackTrace> V8InspectorImpl::createStackTrace(
143 v8::Local<v8::StackTrace> stackTrace) {
144 return m_debugger->createStackTrace(stackTrace);
145}
146
147std::unique_ptr<V8InspectorSession> V8InspectorImpl::connect(
148 int contextGroupId, V8Inspector::Channel* channel, StringView state,
149 ClientTrustLevel client_trust_level, SessionPauseState pause_state) {
150 int sessionId = ++m_lastSessionId;
151 std::shared_ptr<V8DebuggerBarrier> debuggerBarrier;
152 if (pause_state == kWaitingForDebugger) {
153 auto it = m_debuggerBarriers.find(contextGroupId);
154 if (it != m_debuggerBarriers.end()) {
155 // Note this will be empty in case a pre-existent barrier is already
156 // released. This is by design, as a released throttle is no longer
157 // efficient.
158 debuggerBarrier = it->second.lock();
159 } else {
160 debuggerBarrier =
161 std::make_shared<V8DebuggerBarrier>(m_client, contextGroupId);
162 m_debuggerBarriers.insert(it, {contextGroupId, debuggerBarrier});
163 }
164 }
165 std::unique_ptr<V8InspectorSessionImpl> session =
166 V8InspectorSessionImpl::create(this, contextGroupId, sessionId, channel,
167 state, client_trust_level,
168 std::move(debuggerBarrier));
169 m_sessions[contextGroupId][sessionId] = session.get();
170 return std::move(session);
171}
172
174 auto& map = m_sessions[session->contextGroupId()];
175 map.erase(session->sessionId());
176 if (map.empty()) {
177 m_sessions.erase(session->contextGroupId());
178 m_debuggerBarriers.erase(session->contextGroupId());
179 }
180}
181
183 int contextId) const {
184 if (!groupId || !contextId) return nullptr;
185
186 auto contextGroupIt = m_contexts.find(groupId);
187 if (contextGroupIt == m_contexts.end()) return nullptr;
188
189 auto contextIt = contextGroupIt->second->find(contextId);
190 if (contextIt == contextGroupIt->second->end()) return nullptr;
191
192 return contextIt->second.get();
193}
194
196 return getContext(contextGroupId(contextId), contextId);
197}
198
200 InspectedContext* context = getContext(contextId);
201 return context ? context->context() : v8::MaybeLocal<v8::Context>();
202}
203
205 InspectedContext* context = getContext(contextId);
206 internal::V8DebuggerId unique_id;
207 if (context) unique_id = m_debugger->debuggerIdFor(context->contextGroupId());
208
209 return unique_id.toV8DebuggerId();
210}
211
215
217 int contextId = ++m_lastContextId;
218 auto* context = new InspectedContext(this, info, contextId);
219 m_contextIdToGroupIdMap[contextId] = info.contextGroupId;
220
221 DCHECK(m_uniqueIdToContextId.find(context->uniqueId().pair()) ==
224 std::make_pair(context->uniqueId().pair(), contextId));
225
226 auto contextIt = m_contexts.find(info.contextGroupId);
227 if (contextIt == m_contexts.end())
228 contextIt = m_contexts
229 .insert(std::make_pair(
230 info.contextGroupId,
231 std::unique_ptr<ContextByIdMap>(new ContextByIdMap())))
232 .first;
233 const auto& contextById = contextIt->second;
234
235 DCHECK(contextById->find(contextId) == contextById->cend());
236 (*contextById)[contextId].reset(context);
238 info.contextGroupId, [&context](V8InspectorSessionImpl* session) {
239 session->runtimeAgent()->addBindings(context);
240 session->runtimeAgent()->reportExecutionContextCreated(context);
241 });
242}
243
245 int contextId = InspectedContext::contextId(context);
246 int groupId = contextGroupId(context);
247 contextCollected(groupId, contextId);
248}
249
250void V8InspectorImpl::contextCollected(int groupId, int contextId) {
251 m_contextIdToGroupIdMap.erase(contextId);
252
253 auto storageIt = m_consoleStorageMap.find(groupId);
254 if (storageIt != m_consoleStorageMap.end())
255 storageIt->second->contextDestroyed(contextId);
256
257 InspectedContext* inspectedContext = getContext(groupId, contextId);
258 if (!inspectedContext) return;
259
260 forEachSession(groupId, [&inspectedContext](V8InspectorSessionImpl* session) {
261 session->runtimeAgent()->reportExecutionContextDestroyed(inspectedContext);
262 });
263 discardInspectedContext(groupId, contextId);
264}
265
266void V8InspectorImpl::resetContextGroup(int contextGroupId) {
269 auto contextsIt = m_contexts.find(contextGroupId);
270 // Context might have been removed already by discardContextScript()
271 if (contextsIt != m_contexts.end()) {
272 for (const auto& map_entry : *contextsIt->second)
273 m_uniqueIdToContextId.erase(map_entry.second->uniqueId().pair());
274 m_contexts.erase(contextsIt);
275 }
277 [](V8InspectorSessionImpl* session) { session->reset(); });
278}
279
281
283
285 v8::Local<v8::Context> context, StringView message,
286 v8::Local<v8::Value> exception, StringView detailedMessage, StringView url,
287 unsigned lineNumber, unsigned columnNumber,
288 std::unique_ptr<V8StackTrace> stackTrace, int scriptId) {
289 int groupId = contextGroupId(context);
290 if (!groupId || m_muteExceptionsMap[groupId]) return 0;
291 std::unique_ptr<V8StackTraceImpl> stackTraceImpl(
292 static_cast<V8StackTraceImpl*>(stackTrace.release()));
293 unsigned exceptionId = nextExceptionId();
294 std::unique_ptr<V8ConsoleMessage> consoleMessage =
296 m_client->currentTimeMS(), toString16(detailedMessage),
297 toString16(url), lineNumber, columnNumber, std::move(stackTraceImpl),
298 scriptId, m_isolate, toString16(message),
299 InspectedContext::contextId(context), exception, exceptionId);
300 ensureConsoleMessageStorage(groupId)->addMessage(std::move(consoleMessage));
301 return exceptionId;
302}
303
305 unsigned exceptionId,
306 StringView message) {
307 int groupId = contextGroupId(context);
308 if (!groupId) return;
309
310 std::unique_ptr<V8ConsoleMessage> consoleMessage =
312 m_client->currentTimeMS(), toString16(message), exceptionId);
313 ensureConsoleMessageStorage(groupId)->addMessage(std::move(consoleMessage));
314}
315
316std::unique_ptr<V8StackTrace> V8InspectorImpl::captureStackTrace(
317 bool fullStack) {
318 return m_debugger->captureStackTrace(fullStack);
319}
320
322 return m_debugger->storeCurrentStackTrace(description);
323}
324
326 m_debugger->externalAsyncTaskStarted(parent);
327}
328
330 m_debugger->externalAsyncTaskFinished(parent);
331}
332
334 bool recurring) {
335 if (!task) return;
336 m_debugger->asyncTaskScheduled(taskName, task, recurring);
337}
338
340 if (!task) return;
341 m_debugger->asyncTaskCanceled(task);
342}
343
345 if (!task) return;
346 m_debugger->asyncTaskStarted(task);
347}
348
350 if (!task) return;
351 m_debugger->asyncTaskFinished(task);
352}
353
355 m_debugger->allAsyncTasksCanceled();
356}
357
368
379
381 int contextId) {
382 auto* context = getContext(contextGroupId, contextId);
383 if (!context) return;
384 m_uniqueIdToContextId.erase(context->uniqueId().pair());
385 m_contexts[contextGroupId]->erase(contextId);
387}
388
390 int sessionId) {
391 auto it = m_sessions.find(contextGroupId);
392 if (it == m_sessions.end()) return nullptr;
393 auto it2 = it->second.find(sessionId);
394 return it2 == it->second.end() ? nullptr : it2->second;
395}
396
398 if (!m_console) m_console.reset(new V8Console(this));
399 return m_console.get();
400}
401
403 int contextGroupId,
404 const std::function<void(InspectedContext*)>& callback) {
405 auto it = m_contexts.find(contextGroupId);
406 if (it == m_contexts.end()) return;
407 std::vector<int> ids;
408 ids.reserve(it->second->size());
409 for (auto& contextIt : *(it->second)) ids.push_back(contextIt.first);
410
411 // Retrieve by ids each time since |callback| may destroy some contexts.
412 for (auto& contextId : ids) {
413 it = m_contexts.find(contextGroupId);
414 if (it == m_contexts.end()) continue;
415 auto contextIt = it->second->find(contextId);
416 if (contextIt != it->second->end()) callback(contextIt->second.get());
417 }
418}
419
421 int contextGroupId,
422 const std::function<void(V8InspectorSessionImpl*)>& callback) {
423 auto it = m_sessions.find(contextGroupId);
424 if (it == m_sessions.end()) return;
425 std::vector<int> ids;
426 ids.reserve(it->second.size());
427 for (auto& sessionIt : it->second) ids.push_back(sessionIt.first);
428
429 // Retrieve by ids each time since |callback| may destroy some contexts.
430 for (auto& sessionId : ids) {
431 it = m_sessions.find(contextGroupId);
432 if (it == m_sessions.end()) continue;
433 auto sessionIt = it->second.find(sessionId);
434 if (sessionIt != it->second.end()) callback(sessionIt->second);
435 }
436}
437
439 int64_t id = m_client->generateUniqueId();
441 if (!id) id = 1;
442 return id;
443}
444
446 const InjectedScript::Scope& scope)
447 : m_scope(scope), m_isolate(scope.inspector()->isolate()) {}
448
453
455 if (m_scope.tryCatch().HasTerminated()) {
456 m_scope.inspector()->debugger()->reportTermination();
457 }
458 if (m_cancelToken) {
459 v8::base::MutexGuard lock(&m_cancelToken->m_mutex);
460 m_cancelToken->m_canceled = true;
462 }
463}
464
466 public:
467 TerminateTask(v8::Isolate* isolate, std::shared_ptr<CancelToken> token)
468 : m_isolate(isolate), m_token(std::move(token)) {}
469
470 void Run() override {
471 // CancelToken contains m_canceled bool which may be changed from main
472 // thread, so lock mutex first.
473 v8::base::MutexGuard lock(&m_token->m_mutex);
474 if (m_token->m_canceled) return;
476 }
477
478 private:
480 std::shared_ptr<CancelToken> m_token;
481};
482
483protocol::Response V8InspectorImpl::EvaluateScope::setTimeout(double timeout) {
485 return protocol::Response::ServerError("Execution was terminated");
486 }
487 m_cancelToken.reset(new CancelToken());
490 std::make_unique<TerminateTask>(m_isolate, m_cancelToken), timeout);
491 return protocol::Response::Success();
492}
493
495 v8::Local<v8::Value> exception,
497 v8::Local<v8::Value> value) {
498 if (!exception->IsObject()) {
499 return false;
500 }
502 if (!exceptionMetaDataContext().ToLocal(&context)) return false;
503 v8::TryCatch tryCatch(m_isolate);
504 v8::Context::Scope contextScope(context);
505 v8::HandleScope handles(m_isolate);
509
511 v8::MaybeLocal<v8::Value> entry = map->Get(m_isolate, exception);
513 if (entry.IsEmpty() || !entry.ToLocalChecked()->IsObject()) {
514 object =
515 v8::Object::New(m_isolate, v8::Null(m_isolate), nullptr, nullptr, 0);
517 map->Set(m_isolate, exception, object));
518 } else {
519 object = entry.ToLocalChecked().As<v8::Object>();
520 }
521 CHECK(object->IsObject());
522 v8::Maybe<bool> result = object->CreateDataProperty(context, key, value);
523 return result.FromMaybe(false);
524}
525
527 v8::Local<v8::Value> exception) {
528 if (!exception->IsObject()) {
530 }
534 !exceptionMetaDataContext().ToLocal(&context)) {
536 }
538 auto entry = map->Get(m_isolate, exception);
540 if (!entry.ToLocal(&object) || !object->IsObject())
542 return scope.Escape(object.As<v8::Object>());
543}
544
545std::unique_ptr<protocol::DictionaryValue>
547 v8::Local<v8::Value> exception) {
550 if (!maybeData.ToLocal(&data)) return nullptr;
551
553 if (!exceptionMetaDataContext().ToLocal(&context)) return nullptr;
554
555 v8::TryCatch tryCatch(m_isolate);
556 v8::MicrotasksScope microtasksScope(context,
558 v8::Context::Scope contextScope(context);
559 std::unique_ptr<protocol::DictionaryValue> jsonObject;
560 objectToProtocolValue(context, data, 2, &jsonObject);
561 return jsonObject;
562}
563
564} // namespace v8_inspector
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=nullptr, MaybeLocal< ObjectTemplate > global_template=MaybeLocal< ObjectTemplate >(), MaybeLocal< Value > global_object=MaybeLocal< Value >(), DeserializeInternalFieldsCallback internal_fields_deserializer=DeserializeInternalFieldsCallback(), MicrotaskQueue *microtask_queue=nullptr, DeserializeContextDataCallback context_data_deserializer=DeserializeContextDataCallback(), DeserializeAPIWrapperCallback api_wrapper_deserializer=DeserializeAPIWrapperCallback())
Definition api.cc:6778
V8_INLINE Local< T > Escape(Local< T > value)
void CancelTerminateExecution()
Definition api.cc:9898
void SetIdle(bool is_idle)
Definition api.cc:9736
void TerminateExecution()
Definition api.cc:9888
bool IsExecutionTerminating()
Definition api.cc:9893
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local< S > *out) const
V8_INLINE Local< T > ToLocalChecked()
V8_INLINE bool IsEmpty() const
V8_INLINE T FromMaybe(const T &default_value) const
Definition v8-maybe.h:82
static Local< Object > New(Isolate *isolate)
Definition api.cc:7756
V8_INLINE Local< T > Get(Isolate *isolate) const
void PostDelayedTaskOnWorkerThread(TaskPriority priority, std::unique_ptr< Task > task, double delay_in_seconds, const SourceLocation &location=SourceLocation::Current())
static V8_WARN_UNUSED_RESULT MaybeLocal< Script > Compile(Local< Context > context, Source *source, CompileOptions options=kNoCompileOptions, NoCacheReason no_cache_reason=kNoCacheNoReason)
Definition api.cc:2438
static V8_EXPORT_PRIVATE Local< EphemeronTable > New(v8::Isolate *isolate)
void addMessage(std::unique_ptr< V8ConsoleMessage >)
static std::unique_ptr< V8ConsoleMessage > createForRevokedException(double timestamp, const String16 &message, unsigned revokedExceptionId)
static std::unique_ptr< V8ConsoleMessage > createForException(double timestamp, const String16 &detailedMessage, const String16 &url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr< V8StackTraceImpl >, int scriptId, v8::Isolate *, const String16 &message, int contextId, v8::Local< v8::Value > exception, unsigned exceptionId)
virtual int64_t generateUniqueId()
TerminateTask(v8::Isolate *isolate, std::shared_ptr< CancelToken > token)
EvaluateScope(const InjectedScript::Scope &scope)
protocol::Response setTimeout(double timeout)
void externalAsyncTaskFinished(const V8StackTraceId &parent) override
V8_EXPORT_PRIVATE V8InspectorImpl(v8::Isolate *, V8InspectorClient *)
void asyncTaskStarted(void *task) override
std::unique_ptr< V8Console > m_console
V8ConsoleMessageStorage * ensureConsoleMessageStorage(int contextGroupId)
void disconnect(V8InspectorSessionImpl *)
v8::MaybeLocal< v8::Context > contextById(int contextId) override
std::unique_ptr< V8InspectorSession > connect(int contextGroupId, V8Inspector::Channel *, StringView state, ClientTrustLevel, SessionPauseState) override
std::unique_ptr< protocol::DictionaryValue > getAssociatedExceptionDataForProtocol(v8::Local< v8::Value > exception)
v8::MaybeLocal< v8::Value > compileAndRunInternalScript(v8::Local< v8::Context >, v8::Local< v8::String >)
v8::MaybeLocal< v8::Script > compileScript(v8::Local< v8::Context >, const String16 &code, const String16 &fileName)
void contextCollected(int contextGroupId, int contextId)
V8DebuggerId uniqueDebuggerId(int contextId) override
std::unique_ptr< V8StackTrace > createStackTrace(v8::Local< v8::StackTrace >) override
v8::Global< v8::Context > m_regexContext
void asyncTaskScheduled(StringView taskName, void *task, bool recurring) override
v8::MaybeLocal< v8::Context > regexContext()
InspectedContext * getContext(int groupId, int contextId) const
void contextCreated(const V8ContextInfo &) override
V8_EXPORT_PRIVATE bool associateExceptionData(v8::Local< v8::Context >, v8::Local< v8::Value > exception, v8::Local< v8::Name > key, v8::Local< v8::Value > value) override
void discardInspectedContext(int contextGroupId, int contextId)
void unmuteExceptions(int contextGroupId)
bool hasConsoleMessageStorage(int contextGroupId)
V8_EXPORT_PRIVATE V8Console * console()
int resolveUniqueContextId(internal::V8DebuggerId uniqueId) const
std::unordered_map< int, int > m_contextIdToGroupIdMap
v8::Global< v8::debug::EphemeronTable > m_exceptionMetaData
std::unordered_map< int, std::weak_ptr< V8DebuggerBarrier > > m_debuggerBarriers
V8_EXPORT_PRIVATE v8::MaybeLocal< v8::Object > getAssociatedExceptionData(v8::Local< v8::Value > exception)
void resetContextGroup(int contextGroupId) override
V8StackTraceId storeCurrentStackTrace(StringView description) override
v8::MaybeLocal< v8::Context > exceptionMetaDataContext()
std::unique_ptr< V8StackTrace > captureStackTrace(bool fullStack) override
v8::Global< v8::Context > m_exceptionMetaDataContext
void forEachSession(int contextGroupId, const std::function< void(V8InspectorSessionImpl *)> &callback)
std::map< std::pair< int64_t, int64_t >, int > m_uniqueIdToContextId
void asyncTaskFinished(void *task) override
void exceptionRevoked(v8::Local< v8::Context >, unsigned exceptionId, StringView message) override
void externalAsyncTaskStarted(const V8StackTraceId &parent) override
int contextGroupId(v8::Local< v8::Context >) const
V8InspectorSessionImpl * sessionById(int contextGroupId, int sessionId)
void contextDestroyed(v8::Local< v8::Context >) override
void forEachContext(int contextGroupId, const std::function< void(InspectedContext *)> &callback)
void muteExceptions(int contextGroupId)
unsigned exceptionThrown(v8::Local< v8::Context >, StringView message, v8::Local< v8::Value > exception, StringView detailedMessage, StringView url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr< V8StackTrace >, int scriptId) override
std::unordered_map< int, std::map< int, V8InspectorSessionImpl * > > m_sessions
void asyncTaskCanceled(void *task) override
std::unordered_map< int, std::unique_ptr< InspectedContext > > ContextByIdMap
std::unique_ptr< V8Debugger > m_debugger
static std::unique_ptr< V8InspectorSessionImpl > create(V8InspectorImpl *, int contextGroupId, int sessionId, V8Inspector::Channel *, StringView state, v8_inspector::V8Inspector::ClientTrustLevel, std::shared_ptr< V8DebuggerBarrier >)
static std::unique_ptr< V8Inspector > create(v8::Isolate *, V8InspectorClient *)
void reportExecutionContextDestroyed(InspectedContext *)
std::pair< int64_t, int64_t > pair() const
v8_inspector::V8DebuggerId toV8DebuggerId() const
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation nullptr
TNode< Context > context
TNode< Object > callback
ZoneVector< RpoNumber > & result
InstructionOperand source
STL namespace.
MaybeLocal< UnboundScript > CompileInspectorScript(Isolate *v8_isolate, Local< String > source)
void SetConsoleDelegate(Isolate *v8_isolate, ConsoleDelegate *delegate)
void SetIsolateId(v8::Isolate *v8_isolate, uint64_t id)
int64_t GetNextRandomInt64(v8::Isolate *v8_isolate)
Platform * GetCurrentPlatform()
void SetInspector(Isolate *isolate, v8_inspector::V8Inspector *inspector)
uint64_t GetIsolateId(v8::Isolate *v8_isolate)
Response objectToProtocolValue(v8::Local< v8::Context > context, v8::Local< v8::Object > object, int maxDepth, std::unique_ptr< protocol::DictionaryValue > *result)
v8::Local< v8::String > toV8String(v8::Isolate *isolate, const String16 &string)
String16 toString16(const StringView &string)
V8_INLINE Local< Primitive > Null(Isolate *isolate)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
v8::Isolate * m_isolate
std::unique_ptr< ValueMirror > key