Commit f656eab5 authored by Andrey Kosyakov's avatar Andrey Kosyakov Committed by Commit Bot

DevTools: add support for system-unique execution context ids

This adds ExecutionContextDescription.uniqueId for a system-unique
way to identify an execution context and supports it in Runtime.evaluate.
This allows a client to avoid accidentally executing an expression
in a context different from that originally intended if a navigation
occurs while Runtime.evaluate is in flight.

Design doc: https://docs.google.com/document/d/1vGVWvKP9FTTX6kimcUJR_PAfVgDeIzXXITFpl0SyghQ

Bug: v8:11268, chromium:1101897
Change-Id: I4c6bec562ffc85312559316f639d641780144039
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2594538
Commit-Queue: Andrey Kosyakov <caseq@chromium.org>
Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71869}
parent e51dcc52
...@@ -1226,6 +1226,10 @@ domain Runtime ...@@ -1226,6 +1226,10 @@ domain Runtime
string origin string origin
# Human readable name describing given context. # Human readable name describing given context.
string name string name
# A system-unique execution context identifier. Unlike the id, this is unique accross
# multiple processes, so can be reliably used to identify specific context while backend
# performs a cross-process navigation.
experimental string uniqueId
# Embedder-specific auxiliary data. # Embedder-specific auxiliary data.
optional object auxData optional object auxData
...@@ -1389,6 +1393,9 @@ domain Runtime ...@@ -1389,6 +1393,9 @@ domain Runtime
optional boolean silent optional boolean silent
# Specifies in which execution context to perform evaluation. If the parameter is omitted the # Specifies in which execution context to perform evaluation. If the parameter is omitted the
# evaluation will be performed in the context of the inspected page. # evaluation will be performed in the context of the inspected page.
# This is mutually exclusive with `uniqueContextId`, which offers an
# alternative way to identify the execution context that is more reliable
# in a multi-process environment.
optional ExecutionContextId contextId optional ExecutionContextId contextId
# Whether the result is expected to be a JSON object that should be sent by value. # Whether the result is expected to be a JSON object that should be sent by value.
optional boolean returnByValue optional boolean returnByValue
...@@ -1415,6 +1422,13 @@ domain Runtime ...@@ -1415,6 +1422,13 @@ domain Runtime
# when called with non-callable arguments. This flag bypasses CSP for this # when called with non-callable arguments. This flag bypasses CSP for this
# evaluation and allows unsafe-eval. Defaults to true. # evaluation and allows unsafe-eval. Defaults to true.
experimental optional boolean allowUnsafeEvalBlockedByCSP experimental optional boolean allowUnsafeEvalBlockedByCSP
# An alternative way to specify the execution context to evaluate in.
# Compared to contextId that may be reused accross processes, this is guaranteed to be
# system-unique, so it can be used to prevent accidental evaluation of the expression
# in context different than intended (e.g. as a result of navigation accross process
# boundaries).
# This is mutually exclusive with `contextId`.
experimental optional string uniqueContextId
returns returns
# Evaluation result. # Evaluation result.
RemoteObject result RemoteObject result
......
...@@ -124,6 +124,8 @@ v8_source_set("inspector") { ...@@ -124,6 +124,8 @@ v8_source_set("inspector") {
"v8-console.h", "v8-console.h",
"v8-debugger-agent-impl.cc", "v8-debugger-agent-impl.cc",
"v8-debugger-agent-impl.h", "v8-debugger-agent-impl.h",
"v8-debugger-id.cc",
"v8-debugger-id.h",
"v8-debugger-script.cc", "v8-debugger-script.cc",
"v8-debugger-script.h", "v8-debugger-script.h",
"v8-debugger.cc", "v8-debugger.cc",
......
...@@ -55,7 +55,8 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector, ...@@ -55,7 +55,8 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector,
m_contextGroupId(info.contextGroupId), m_contextGroupId(info.contextGroupId),
m_origin(toString16(info.origin)), m_origin(toString16(info.origin)),
m_humanReadableName(toString16(info.humanReadableName)), m_humanReadableName(toString16(info.humanReadableName)),
m_auxData(toString16(info.auxData)) { m_auxData(toString16(info.auxData)),
m_uniqueId(V8DebuggerId::generate(inspector)) {
v8::debug::SetContextId(info.context, contextId); v8::debug::SetContextId(info.context, contextId);
m_weakCallbackData = m_weakCallbackData =
new WeakCallbackData(this, m_inspector, m_contextGroupId, m_contextId); new WeakCallbackData(this, m_inspector, m_contextGroupId, m_contextId);
......
...@@ -9,11 +9,11 @@ ...@@ -9,11 +9,11 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include "include/v8.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/debug/debug-interface.h" #include "src/debug/debug-interface.h"
#include "src/inspector/string-16.h" #include "src/inspector/string-16.h"
#include "src/inspector/v8-debugger-id.h"
#include "include/v8.h"
namespace v8_inspector { namespace v8_inspector {
...@@ -37,6 +37,7 @@ class InspectedContext { ...@@ -37,6 +37,7 @@ class InspectedContext {
int contextGroupId() const { return m_contextGroupId; } int contextGroupId() const { return m_contextGroupId; }
String16 origin() const { return m_origin; } String16 origin() const { return m_origin; }
String16 humanReadableName() const { return m_humanReadableName; } String16 humanReadableName() const { return m_humanReadableName; }
V8DebuggerId uniqueId() const { return m_uniqueId; }
String16 auxData() const { return m_auxData; } String16 auxData() const { return m_auxData; }
bool isReported(int sessionId) const; bool isReported(int sessionId) const;
...@@ -66,6 +67,7 @@ class InspectedContext { ...@@ -66,6 +67,7 @@ class InspectedContext {
const String16 m_origin; const String16 m_origin;
const String16 m_humanReadableName; const String16 m_humanReadableName;
const String16 m_auxData; const String16 m_auxData;
const V8DebuggerId m_uniqueId;
std::unordered_set<int> m_reportedSessionIds; std::unordered_set<int> m_reportedSessionIds;
std::unordered_map<int, std::unique_ptr<InjectedScript>> m_injectedScripts; std::unordered_map<int, std::unique_ptr<InjectedScript>> m_injectedScripts;
WeakCallbackData* m_weakCallbackData; WeakCallbackData* m_weakCallbackData;
......
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/inspector/v8-debugger-id.h"
#include "src/debug/debug-interface.h"
#include "src/inspector/v8-inspector-impl.h"
namespace v8_inspector {
V8DebuggerId::V8DebuggerId(std::pair<int64_t, int64_t> pair)
: m_first(pair.first), m_second(pair.second) {}
// static
V8DebuggerId V8DebuggerId::generate(V8InspectorImpl* inspector) {
return V8DebuggerId(std::make_pair(inspector->generateUniqueId(),
inspector->generateUniqueId()));
}
V8DebuggerId::V8DebuggerId(const String16& debuggerId) {
const UChar dot = '.';
size_t pos = debuggerId.find(dot);
if (pos == String16::kNotFound) return;
bool ok = false;
int64_t first = debuggerId.substring(0, pos).toInteger64(&ok);
if (!ok) return;
int64_t second = debuggerId.substring(pos + 1).toInteger64(&ok);
if (!ok) return;
m_first = first;
m_second = second;
}
String16 V8DebuggerId::toString() const {
return String16::fromInteger64(m_first) + "." +
String16::fromInteger64(m_second);
}
bool V8DebuggerId::isValid() const { return m_first || m_second; }
std::pair<int64_t, int64_t> V8DebuggerId::pair() const {
return std::make_pair(m_first, m_second);
}
} // namespace v8_inspector
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_INSPECTOR_V8_DEBUGGER_ID_H_
#define V8_INSPECTOR_V8_DEBUGGER_ID_H_
#include <utility>
#include "src/base/macros.h"
#include "src/inspector/protocol/Forward.h"
namespace v8_inspector {
class V8InspectorImpl;
// This debugger id tries to be unique by generating two random
// numbers, which should most likely avoid collisions.
// Debugger id has a 1:1 mapping to context group. It is used to
// attribute stack traces to a particular debugging, when doing any
// cross-debugger operations (e.g. async step in).
// See also Runtime.UniqueDebuggerId in the protocol.
class V8DebuggerId {
public:
V8DebuggerId() = default;
explicit V8DebuggerId(std::pair<int64_t, int64_t>);
explicit V8DebuggerId(const String16&);
V8DebuggerId(const V8DebuggerId&) V8_NOEXCEPT = default;
~V8DebuggerId() = default;
static V8DebuggerId generate(V8InspectorImpl*);
String16 toString() const;
bool isValid() const;
std::pair<int64_t, int64_t> pair() const;
private:
int64_t m_first = 0;
int64_t m_second = 0;
};
} // namespace v8_inspector
#endif // V8_INSPECTOR_V8_DEBUGGER_ID_H_
...@@ -64,39 +64,6 @@ class MatchPrototypePredicate : public v8::debug::QueryObjectPredicate { ...@@ -64,39 +64,6 @@ class MatchPrototypePredicate : public v8::debug::QueryObjectPredicate {
} // namespace } // namespace
V8DebuggerId::V8DebuggerId(std::pair<int64_t, int64_t> pair)
: m_first(pair.first), m_second(pair.second) {}
// static
V8DebuggerId V8DebuggerId::generate(V8InspectorImpl* inspector) {
return V8DebuggerId(std::make_pair(inspector->generateUniqueId(),
inspector->generateUniqueId()));
}
V8DebuggerId::V8DebuggerId(const String16& debuggerId) {
const UChar dot = '.';
size_t pos = debuggerId.find(dot);
if (pos == String16::kNotFound) return;
bool ok = false;
int64_t first = debuggerId.substring(0, pos).toInteger64(&ok);
if (!ok) return;
int64_t second = debuggerId.substring(pos + 1).toInteger64(&ok);
if (!ok) return;
m_first = first;
m_second = second;
}
String16 V8DebuggerId::toString() const {
return String16::fromInteger64(m_first) + "." +
String16::fromInteger64(m_second);
}
bool V8DebuggerId::isValid() const { return m_first || m_second; }
std::pair<int64_t, int64_t> V8DebuggerId::pair() const {
return std::make_pair(m_first, m_second);
}
V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector)
: m_isolate(isolate), : m_isolate(isolate),
m_inspector(inspector), m_inspector(inspector),
......
...@@ -11,15 +11,15 @@ ...@@ -11,15 +11,15 @@
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
#include "include/v8-inspector.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/inspector/inspected-context.h" #include "src/inspector/inspected-context.h"
#include "src/inspector/protocol/Debugger.h" #include "src/inspector/protocol/Debugger.h"
#include "src/inspector/protocol/Forward.h" #include "src/inspector/protocol/Forward.h"
#include "src/inspector/protocol/Runtime.h" #include "src/inspector/protocol/Runtime.h"
#include "src/inspector/v8-debugger-id.h"
#include "src/inspector/v8-debugger-script.h" #include "src/inspector/v8-debugger-script.h"
#include "include/v8-inspector.h"
namespace v8_inspector { namespace v8_inspector {
class AsyncStackTrace; class AsyncStackTrace;
...@@ -36,31 +36,6 @@ using protocol::Response; ...@@ -36,31 +36,6 @@ using protocol::Response;
using TerminateExecutionCallback = using TerminateExecutionCallback =
protocol::Runtime::Backend::TerminateExecutionCallback; protocol::Runtime::Backend::TerminateExecutionCallback;
// This debugger id tries to be unique by generating two random
// numbers, which should most likely avoid collisions.
// Debugger id has a 1:1 mapping to context group. It is used to
// attribute stack traces to a particular debugging, when doing any
// cross-debugger operations (e.g. async step in).
// See also Runtime.UniqueDebuggerId in the protocol.
class V8DebuggerId {
public:
V8DebuggerId() = default;
explicit V8DebuggerId(std::pair<int64_t, int64_t>);
explicit V8DebuggerId(const String16&);
V8DebuggerId(const V8DebuggerId&) V8_NOEXCEPT = default;
~V8DebuggerId() = default;
static V8DebuggerId generate(V8InspectorImpl*);
String16 toString() const;
bool isValid() const;
std::pair<int64_t, int64_t> pair() const;
private:
int64_t m_first = 0;
int64_t m_second = 0;
};
class V8Debugger : public v8::debug::DebugDelegate, class V8Debugger : public v8::debug::DebugDelegate,
public v8::debug::AsyncEventDelegate { public v8::debug::AsyncEventDelegate {
public: public:
......
...@@ -81,6 +81,11 @@ int V8InspectorImpl::contextGroupId(int contextId) const { ...@@ -81,6 +81,11 @@ int V8InspectorImpl::contextGroupId(int contextId) const {
return it != m_contextIdToGroupIdMap.end() ? it->second : 0; return it != m_contextIdToGroupIdMap.end() ? it->second : 0;
} }
int V8InspectorImpl::resolveUniqueContextId(V8DebuggerId uniqueId) const {
auto it = m_uniqueIdToContextId.find(uniqueId.pair());
return it == m_uniqueIdToContextId.end() ? 0 : it->second;
}
v8::MaybeLocal<v8::Value> V8InspectorImpl::compileAndRunInternalScript( v8::MaybeLocal<v8::Value> V8InspectorImpl::compileAndRunInternalScript(
v8::Local<v8::Context> context, v8::Local<v8::String> source) { v8::Local<v8::Context> context, v8::Local<v8::String> source) {
v8::Local<v8::UnboundScript> unboundScript; v8::Local<v8::UnboundScript> unboundScript;
...@@ -190,6 +195,11 @@ void V8InspectorImpl::contextCreated(const V8ContextInfo& info) { ...@@ -190,6 +195,11 @@ void V8InspectorImpl::contextCreated(const V8ContextInfo& info) {
auto* context = new InspectedContext(this, info, contextId); auto* context = new InspectedContext(this, info, contextId);
m_contextIdToGroupIdMap[contextId] = info.contextGroupId; m_contextIdToGroupIdMap[contextId] = info.contextGroupId;
DCHECK(m_uniqueIdToContextId.find(context->uniqueId().pair()) ==
m_uniqueIdToContextId.end());
m_uniqueIdToContextId.insert(
std::make_pair(context->uniqueId().pair(), contextId));
auto contextIt = m_contexts.find(info.contextGroupId); auto contextIt = m_contexts.find(info.contextGroupId);
if (contextIt == m_contexts.end()) if (contextIt == m_contexts.end())
contextIt = m_contexts contextIt = m_contexts
...@@ -233,14 +243,15 @@ void V8InspectorImpl::contextCollected(int groupId, int contextId) { ...@@ -233,14 +243,15 @@ void V8InspectorImpl::contextCollected(int groupId, int contextId) {
void V8InspectorImpl::resetContextGroup(int contextGroupId) { void V8InspectorImpl::resetContextGroup(int contextGroupId) {
m_consoleStorageMap.erase(contextGroupId); m_consoleStorageMap.erase(contextGroupId);
m_muteExceptionsMap.erase(contextGroupId); m_muteExceptionsMap.erase(contextGroupId);
std::vector<int> contextIdsToClear; auto contextsIt = m_contexts.find(contextGroupId);
forEachContext(contextGroupId, // Context might have been removed already by discardContextScript()
[&contextIdsToClear](InspectedContext* context) { if (contextsIt != m_contexts.end()) {
contextIdsToClear.push_back(context->contextId()); for (const auto& map_entry : *contextsIt->second)
}); m_uniqueIdToContextId.erase(map_entry.second->uniqueId().pair());
m_contexts.erase(contextsIt);
}
forEachSession(contextGroupId, forEachSession(contextGroupId,
[](V8InspectorSessionImpl* session) { session->reset(); }); [](V8InspectorSessionImpl* session) { session->reset(); });
m_contexts.erase(contextGroupId);
} }
void V8InspectorImpl::idleStarted() { m_isolate->SetIdle(true); } void V8InspectorImpl::idleStarted() { m_isolate->SetIdle(true); }
...@@ -362,7 +373,9 @@ v8::Local<v8::Context> V8InspectorImpl::regexContext() { ...@@ -362,7 +373,9 @@ v8::Local<v8::Context> V8InspectorImpl::regexContext() {
void V8InspectorImpl::discardInspectedContext(int contextGroupId, void V8InspectorImpl::discardInspectedContext(int contextGroupId,
int contextId) { int contextId) {
if (!getContext(contextGroupId, contextId)) return; auto* context = getContext(contextGroupId, contextId);
if (!context) return;
m_uniqueIdToContextId.erase(context->uniqueId().pair());
m_contexts[contextGroupId]->erase(contextId); m_contexts[contextGroupId]->erase(contextId);
if (m_contexts[contextGroupId]->empty()) m_contexts.erase(contextGroupId); if (m_contexts[contextGroupId]->empty()) m_contexts.erase(contextGroupId);
} }
......
...@@ -68,6 +68,7 @@ class V8InspectorImpl : public V8Inspector { ...@@ -68,6 +68,7 @@ class V8InspectorImpl : public V8Inspector {
int contextGroupId(v8::Local<v8::Context>) const; int contextGroupId(v8::Local<v8::Context>) const;
int contextGroupId(int contextId) const; int contextGroupId(int contextId) const;
uint64_t isolateId() const { return m_isolateId; } uint64_t isolateId() const { return m_isolateId; }
int resolveUniqueContextId(V8DebuggerId uniqueId) const;
v8::MaybeLocal<v8::Value> compileAndRunInternalScript(v8::Local<v8::Context>, v8::MaybeLocal<v8::Value> compileAndRunInternalScript(v8::Local<v8::Context>,
v8::Local<v8::String>); v8::Local<v8::String>);
...@@ -178,6 +179,7 @@ class V8InspectorImpl : public V8Inspector { ...@@ -178,6 +179,7 @@ class V8InspectorImpl : public V8Inspector {
ConsoleStorageMap m_consoleStorageMap; ConsoleStorageMap m_consoleStorageMap;
std::unordered_map<int, int> m_contextIdToGroupIdMap; std::unordered_map<int, int> m_contextIdToGroupIdMap;
std::map<std::pair<int64_t, int64_t>, int> m_uniqueIdToContextId;
std::unique_ptr<V8Console> m_console; std::unique_ptr<V8Console> m_console;
......
...@@ -204,9 +204,21 @@ void innerCallFunctionOn( ...@@ -204,9 +204,21 @@ void innerCallFunctionOn(
} }
Response ensureContext(V8InspectorImpl* inspector, int contextGroupId, Response ensureContext(V8InspectorImpl* inspector, int contextGroupId,
Maybe<int> executionContextId, int* contextId) { Maybe<int> executionContextId,
Maybe<String16> uniqueContextId, int* contextId) {
if (executionContextId.isJust()) { if (executionContextId.isJust()) {
if (uniqueContextId.isJust()) {
return Response::InvalidParams(
"contextId and uniqueContextId are mutually exclusive");
}
*contextId = executionContextId.fromJust(); *contextId = executionContextId.fromJust();
} else if (uniqueContextId.isJust()) {
V8DebuggerId uniqueId(uniqueContextId.fromJust());
if (!uniqueId.isValid())
return Response::InvalidParams("invalid uniqueContextId");
int id = inspector->resolveUniqueContextId(uniqueId);
if (!id) return Response::InvalidParams("uniqueContextId not found");
*contextId = id;
} else { } else {
v8::HandleScope handles(inspector->isolate()); v8::HandleScope handles(inspector->isolate());
v8::Local<v8::Context> defaultContext = v8::Local<v8::Context> defaultContext =
...@@ -215,6 +227,7 @@ Response ensureContext(V8InspectorImpl* inspector, int contextGroupId, ...@@ -215,6 +227,7 @@ Response ensureContext(V8InspectorImpl* inspector, int contextGroupId,
return Response::ServerError("Cannot find default execution context"); return Response::ServerError("Cannot find default execution context");
*contextId = InspectedContext::contextId(defaultContext); *contextId = InspectedContext::contextId(defaultContext);
} }
return Response::Success(); return Response::Success();
} }
...@@ -238,13 +251,14 @@ void V8RuntimeAgentImpl::evaluate( ...@@ -238,13 +251,14 @@ void V8RuntimeAgentImpl::evaluate(
Maybe<bool> generatePreview, Maybe<bool> userGesture, Maybe<bool> generatePreview, Maybe<bool> userGesture,
Maybe<bool> maybeAwaitPromise, Maybe<bool> throwOnSideEffect, Maybe<bool> maybeAwaitPromise, Maybe<bool> throwOnSideEffect,
Maybe<double> timeout, Maybe<bool> disableBreaks, Maybe<bool> maybeReplMode, Maybe<double> timeout, Maybe<bool> disableBreaks, Maybe<bool> maybeReplMode,
Maybe<bool> allowUnsafeEvalBlockedByCSP, Maybe<bool> allowUnsafeEvalBlockedByCSP, Maybe<String16> uniqueContextId,
std::unique_ptr<EvaluateCallback> callback) { std::unique_ptr<EvaluateCallback> callback) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
"EvaluateScript"); "EvaluateScript");
int contextId = 0; int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(), Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId), &contextId); std::move(executionContextId),
std::move(uniqueContextId), &contextId);
if (!response.IsSuccess()) { if (!response.IsSuccess()) {
callback->sendFailure(response); callback->sendFailure(response);
return; return;
...@@ -378,9 +392,9 @@ void V8RuntimeAgentImpl::callFunctionOn( ...@@ -378,9 +392,9 @@ void V8RuntimeAgentImpl::callFunctionOn(
std::move(callback)); std::move(callback));
} else { } else {
int contextId = 0; int contextId = 0;
Response response = Response response = ensureContext(m_inspector, m_session->contextGroupId(),
ensureContext(m_inspector, m_session->contextGroupId(), std::move(executionContextId.fromJust()),
std::move(executionContextId.fromJust()), &contextId); /* uniqueContextId */ {}, &contextId);
if (!response.IsSuccess()) { if (!response.IsSuccess()) {
callback->sendFailure(response); callback->sendFailure(response);
return; return;
...@@ -497,7 +511,8 @@ Response V8RuntimeAgentImpl::compileScript( ...@@ -497,7 +511,8 @@ Response V8RuntimeAgentImpl::compileScript(
int contextId = 0; int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(), Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId), &contextId); std::move(executionContextId),
/*uniqueContextId*/ {}, &contextId);
if (!response.IsSuccess()) return response; if (!response.IsSuccess()) return response;
InjectedScript::ContextScope scope(m_session, contextId); InjectedScript::ContextScope scope(m_session, contextId);
response = scope.initialize(); response = scope.initialize();
...@@ -550,7 +565,8 @@ void V8RuntimeAgentImpl::runScript( ...@@ -550,7 +565,8 @@ void V8RuntimeAgentImpl::runScript(
int contextId = 0; int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(), Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId), &contextId); std::move(executionContextId),
/*uniqueContextId*/ {}, &contextId);
if (!response.IsSuccess()) { if (!response.IsSuccess()) {
callback->sendFailure(response); callback->sendFailure(response);
return; return;
...@@ -626,7 +642,8 @@ Response V8RuntimeAgentImpl::globalLexicalScopeNames( ...@@ -626,7 +642,8 @@ Response V8RuntimeAgentImpl::globalLexicalScopeNames(
std::unique_ptr<protocol::Array<String16>>* outNames) { std::unique_ptr<protocol::Array<String16>>* outNames) {
int contextId = 0; int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(), Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId), &contextId); std::move(executionContextId),
/*uniqueContextId*/ {}, &contextId);
if (!response.IsSuccess()) return response; if (!response.IsSuccess()) return response;
InjectedScript::ContextScope scope(m_session, contextId); InjectedScript::ContextScope scope(m_session, contextId);
...@@ -864,6 +881,7 @@ void V8RuntimeAgentImpl::reportExecutionContextCreated( ...@@ -864,6 +881,7 @@ void V8RuntimeAgentImpl::reportExecutionContextCreated(
.setId(context->contextId()) .setId(context->contextId())
.setName(context->humanReadableName()) .setName(context->humanReadableName())
.setOrigin(context->origin()) .setOrigin(context->origin())
.setUniqueId(context->uniqueId().toString())
.build(); .build();
const String16& aux = context->auxData(); const String16& aux = context->auxData();
if (!aux.isEmpty()) { if (!aux.isEmpty()) {
......
...@@ -71,6 +71,7 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend { ...@@ -71,6 +71,7 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend {
Maybe<bool> awaitPromise, Maybe<bool> throwOnSideEffect, Maybe<bool> awaitPromise, Maybe<bool> throwOnSideEffect,
Maybe<double> timeout, Maybe<bool> disableBreaks, Maybe<double> timeout, Maybe<bool> disableBreaks,
Maybe<bool> replMode, Maybe<bool> allowUnsafeEvalBlockedByCSP, Maybe<bool> replMode, Maybe<bool> allowUnsafeEvalBlockedByCSP,
Maybe<String16> uniqueContextId,
std::unique_ptr<EvaluateCallback>) override; std::unique_ptr<EvaluateCallback>) override;
void awaitPromise(const String16& promiseObjectId, Maybe<bool> returnByValue, void awaitPromise(const String16& promiseObjectId, Maybe<bool> returnByValue,
Maybe<bool> generatePreview, Maybe<bool> generatePreview,
......
...@@ -36,7 +36,7 @@ InspectorTest.logMessage = function(originalMessage) { ...@@ -36,7 +36,7 @@ InspectorTest.logMessage = function(originalMessage) {
const nonStableFields = new Set([ const nonStableFields = new Set([
'objectId', 'scriptId', 'exceptionId', 'timestamp', 'executionContextId', 'objectId', 'scriptId', 'exceptionId', 'timestamp', 'executionContextId',
'callFrameId', 'breakpointId', 'bindRemoteObjectFunctionId', 'callFrameId', 'breakpointId', 'bindRemoteObjectFunctionId',
'formatterObjectId', 'debuggerId', 'bodyGetterId' 'formatterObjectId', 'debuggerId', 'bodyGetterId', 'uniqueId'
]); ]);
const message = JSON.parse(JSON.stringify(originalMessage, replacer.bind(null, Symbol(), nonStableFields))); const message = JSON.parse(JSON.stringify(originalMessage, replacer.bind(null, Symbol(), nonStableFields)));
if (message.id) if (message.id)
......
...@@ -6,6 +6,7 @@ Checks createContext(). ...@@ -6,6 +6,7 @@ Checks createContext().
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -16,6 +17,7 @@ Checks createContext(). ...@@ -16,6 +17,7 @@ Checks createContext().
id : 2 id : 2
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -37,6 +39,7 @@ Reported script's execution id: 2 ...@@ -37,6 +39,7 @@ Reported script's execution id: 2
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -47,6 +50,7 @@ Reported script's execution id: 2 ...@@ -47,6 +50,7 @@ Reported script's execution id: 2
id : 2 id : 2
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
......
Tests how Runtime.evaluate handles uniqueContextId argument
token in context 1: context 1
token in context 2: context 2
{
error : {
code : -32602
message : contextId and uniqueContextId are mutually exclusive
}
id : <messageId>
}
{
error : {
code : -32602
message : invalid uniqueContextId
}
id : <messageId>
}
{
error : {
code : -32602
message : uniqueContextId not found
}
id : <messageId>
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const {Protocol, contextGroup} = InspectorTest.start(
`Tests how Runtime.evaluate handles uniqueContextId argument`);
(async function test(){
Protocol.Runtime.enable();
const context1 = (await Protocol.Runtime.onceExecutionContextCreated()).params.context;
contextGroup.createContext();
const context2 = (await Protocol.Runtime.onceExecutionContextCreated()).params.context;
Protocol.Runtime.evaluate({
expression: 'token = "context 1";',
contextId: context1.id
});
Protocol.Runtime.evaluate({
expression: 'token = "context 2";',
contextId: context2.id
});
{
const response = (await Protocol.Runtime.evaluate({
expression: 'token',
uniqueContextId: context1.uniqueId,
returnByValue: true
})).result.result.value;
InspectorTest.logMessage(`token in context 1: ${response}`);
}
{
const response = (await Protocol.Runtime.evaluate({
expression: 'token',
uniqueContextId: context2.uniqueId,
returnByValue: true
})).result.result.value;
InspectorTest.logMessage(`token in context 2: ${response}`);
}
// The following tests are for error handling.
{
const response = (await Protocol.Runtime.evaluate({
expression: 'token',
uniqueContextId: context1.uniqueId,
contextId: context1.id
}));
InspectorTest.logMessage(response);
}
{
const response = (await Protocol.Runtime.evaluate({
expression: 'token',
uniqueContextId: 'fubar',
}));
InspectorTest.logMessage(response);
}
{
const response = (await Protocol.Runtime.evaluate({
expression: 'token',
uniqueContextId: context1.uniqueId + 1,
}));
InspectorTest.logMessage(response);
}
InspectorTest.completeTest();
})();
...@@ -8,6 +8,7 @@ Running test: testExecutionContextsNotificationsOnRestore ...@@ -8,6 +8,7 @@ Running test: testExecutionContextsNotificationsOnRestore
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -24,6 +25,7 @@ will reconnect.. ...@@ -24,6 +25,7 @@ will reconnect..
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
......
...@@ -8,6 +8,7 @@ From session 1 ...@@ -8,6 +8,7 @@ From session 1
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -20,6 +21,7 @@ From session 2 ...@@ -20,6 +21,7 @@ From session 2
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -32,6 +34,7 @@ From session 2 ...@@ -32,6 +34,7 @@ From session 2
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -44,6 +47,7 @@ From session 1 ...@@ -44,6 +47,7 @@ From session 1
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -56,6 +60,7 @@ From session 3 ...@@ -56,6 +60,7 @@ From session 3
id : 1 id : 1
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -92,6 +97,7 @@ From session 2 ...@@ -92,6 +97,7 @@ From session 2
id : 2 id : 2
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -103,6 +109,7 @@ From session 1 ...@@ -103,6 +109,7 @@ From session 1
id : 2 id : 2
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -114,6 +121,7 @@ From session 3 ...@@ -114,6 +121,7 @@ From session 3
id : 2 id : 2
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
...@@ -127,6 +135,7 @@ From session 4 ...@@ -127,6 +135,7 @@ From session 4
id : 2 id : 2
name : name :
origin : origin :
uniqueId : <uniqueId>
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment