Runtime.callFunctionOn supports uniqueContextId

Bug: v8:13620
Change-Id: I802deb3325a5c8ac9e7e378d60be591af66e6fee
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4126215
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Vladimir Nechaev <nechaev@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85027}
This commit is contained in:
Vladimir Nechaev 2022-12-28 10:03:56 +00:00 committed by V8 LUCI CQ
parent dff5fc1b23
commit 28cb67cdec
5 changed files with 106 additions and 15 deletions

View File

@ -1402,6 +1402,13 @@ domain Runtime
optional string objectGroup
# Whether to throw an exception if side effect cannot be ruled out during evaluation.
experimental optional boolean throwOnSideEffect
# An alternative way to specify the execution context to call function on.
# Compared to contextId that may be reused across processes, this is guaranteed to be
# system-unique, so it can be used to prevent accidental function call
# in context different than intended (e.g. as a result of navigation across process
# boundaries).
# This is mutually exclusive with `executionContextId`.
experimental optional string uniqueContextId
# Whether the result should contain `webDriverValue`, serialized according to
# https://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but
# resulting `objectId` is still provided.

View File

@ -375,16 +375,22 @@ void V8RuntimeAgentImpl::callFunctionOn(
Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview,
Maybe<bool> userGesture, Maybe<bool> awaitPromise,
Maybe<int> executionContextId, Maybe<String16> objectGroup,
Maybe<bool> throwOnSideEffect, Maybe<bool> generateWebDriverValue,
Maybe<bool> throwOnSideEffect, Maybe<String16> uniqueContextId,
Maybe<bool> generateWebDriverValue,
std::unique_ptr<CallFunctionOnCallback> callback) {
if (objectId.isJust() && executionContextId.isJust()) {
callback->sendFailure(Response::ServerError(
"ObjectId must not be specified together with executionContextId"));
int justCount = (objectId.isJust() ? 1 : 0) +
(executionContextId.isJust() ? 1 : 0) +
(uniqueContextId.isJust() ? 1 : 0);
if (justCount > 1) {
callback->sendFailure(Response::InvalidParams(
"ObjectId, executionContextId and uniqueContextId must mutually "
"exclude each other"));
return;
}
if (!objectId.isJust() && !executionContextId.isJust()) {
callback->sendFailure(Response::ServerError(
"Either ObjectId or executionContextId must be specified"));
if (justCount < 1) {
callback->sendFailure(
Response::InvalidParams("Either objectId or executionContextId or "
"uniqueContextId must be specified"));
return;
}
WrapMode wrap_mode = generatePreview.fromMaybe(false) ? WrapMode::kWithPreview
@ -409,8 +415,8 @@ void V8RuntimeAgentImpl::callFunctionOn(
} else {
int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId.fromJust()),
/* uniqueContextId */ {}, &contextId);
std::move(executionContextId),
std::move(uniqueContextId), &contextId);
if (!response.IsSuccess()) {
callback->sendFailure(response);
return;

View File

@ -89,7 +89,7 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend {
Maybe<bool> generatePreview, Maybe<bool> userGesture,
Maybe<bool> awaitPromise, Maybe<int> executionContextId,
Maybe<String16> objectGroup, Maybe<bool> throwOnSideEffect,
Maybe<bool> generateWebDriverValue,
Maybe<String16> uniqueContextId, Maybe<bool> generateWebDriverValue,
std::unique_ptr<CallFunctionOnCallback>) override;
Response releaseObject(const String16& objectId) override;
Response getProperties(

View File

@ -208,11 +208,50 @@ Running test: testEvaluateOnExecutionContext
}
}
Running test: testEvaluateOnUniqueExecutionContext
{
id : <messageId>
result : {
result : {
description : 70
type : number
value : 70
}
}
}
Running test: testPassingBothObjectIdAndExecutionContextId
{
error : {
code : -32000
message : ObjectId must not be specified together with executionContextId
code : -32602
message : ObjectId, executionContextId and uniqueContextId must mutually exclude each other
}
id : <messageId>
}
Running test: testPassingBothObjectIdAndExecutionContextUniqueId
{
error : {
code : -32602
message : ObjectId, executionContextId and uniqueContextId must mutually exclude each other
}
id : <messageId>
}
Running test: testPassingTwoExecutionContextIds
{
error : {
code : -32602
message : ObjectId, executionContextId and uniqueContextId must mutually exclude each other
}
id : <messageId>
}
Running test: testPassingNeitherContextIdNorObjectId
{
error : {
code : -32602
message : Either objectId or executionContextId or uniqueContextId must be specified
}
id : <messageId>
}

View File

@ -8,10 +8,12 @@ let callFunctionOn = Protocol.Runtime.callFunctionOn.bind(Protocol.Runtime);
let remoteObject1;
let remoteObject2;
let executionContextId;
let executionContextUniqueId;
Protocol.Runtime.enable();
Protocol.Runtime.onExecutionContextCreated(messageObject => {
executionContextId = messageObject.params.context.id;
executionContextUniqueId = messageObject.params.context.uniqueId;
InspectorTest.runAsyncTestSuite(testSuite);
});
@ -135,15 +137,52 @@ let testSuite = [
}));
},
async function testEvaluateOnUniqueExecutionContext() {
InspectorTest.logMessage(await callFunctionOn({
uniqueContextId: executionContextUniqueId,
functionDeclaration: '(function(arg) { return this.globalObjectProperty + arg; })',
arguments: prepareArguments([ 28 ]),
returnByValue: true,
generatePreview: false,
awaitPromise: false
}));
},
async function testPassingBothObjectIdAndExecutionContextId() {
InspectorTest.logMessage(await callFunctionOn({
executionContextId,
objectId: remoteObject1.objectId,
functionDeclaration: '(function() { return 42; })',
arguments: prepareArguments([]),
returnByValue: true,
generatePreview: false,
awaitPromise: false
returnByValue: true
}));
},
async function testPassingBothObjectIdAndExecutionContextUniqueId() {
InspectorTest.logMessage(await callFunctionOn({
uniqueContextId: executionContextUniqueId,
objectId: remoteObject1.objectId,
functionDeclaration: '(function() { return 42; })',
arguments: prepareArguments([]),
returnByValue: true
}));
},
async function testPassingTwoExecutionContextIds() {
InspectorTest.logMessage(await callFunctionOn({
executionContextId,
uniqueContextId: executionContextUniqueId,
functionDeclaration: '(function() { return 42; })',
arguments: prepareArguments([]),
returnByValue: true
}));
},
async function testPassingNeitherContextIdNorObjectId() {
InspectorTest.logMessage(await callFunctionOn({
functionDeclaration: '(function() { return 42; })',
arguments: prepareArguments([]),
returnByValue: true
}));
},