mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1750541 - [bidi] Implement basic support for "script.callFunction" command r=webdriver-reviewers,whimboo
Depends on D150245 Differential Revision: https://phabricator.services.mozilla.com/D150822
This commit is contained in:
parent
25cf447901
commit
87ebacdf14
@ -121,6 +121,90 @@ class ScriptModule extends Module {
|
||||
* @property {RemoteValue} result
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calls a provided function with given arguments and scope in the provided
|
||||
* target, which is either a realm or a browsing context.
|
||||
*
|
||||
* @param {Object=} options
|
||||
* @param {Array<RemoteValue>=} arguments
|
||||
* The arguments to pass to the function call. [unsupported]
|
||||
* @param {boolean} awaitPromise
|
||||
* Determines if the command should wait for the return value of the
|
||||
* expression to resolve, if this return value is a Promise.
|
||||
* @param {string} functionDeclaration
|
||||
* The expression to evaluate.
|
||||
* @param {OwnershipModel=} resultOwnership [unsupported]
|
||||
* The ownership model to use for the results of this evaluation.
|
||||
* @param {Object} target
|
||||
* The target for the evaluation, which either matches the definition for
|
||||
* a RealmTarget or for ContextTarget.
|
||||
* @param {RemoteValue=} this
|
||||
* The value of the this keyword for the function call. [unsupported]
|
||||
*
|
||||
* @returns {ScriptEvaluateResult}
|
||||
*
|
||||
* @throws {InvalidArgumentError}
|
||||
* If any of the arguments has not the expected type.
|
||||
* @throws {NoSuchFrameError}
|
||||
* If the target cannot be found.
|
||||
*/
|
||||
async callFunction(options = {}) {
|
||||
const {
|
||||
arguments: commandArguments = null,
|
||||
awaitPromise,
|
||||
functionDeclaration,
|
||||
resultOwnership = OwnershipModel.None,
|
||||
target = {},
|
||||
this: thisParameter = null,
|
||||
} = options;
|
||||
|
||||
lazy.assert.string(
|
||||
functionDeclaration,
|
||||
`Expected "functionDeclaration" to be a string, got ${functionDeclaration}`
|
||||
);
|
||||
|
||||
lazy.assert.boolean(
|
||||
awaitPromise,
|
||||
`Expected "awaitPromise" to be a boolean, got ${awaitPromise}`
|
||||
);
|
||||
|
||||
this.#assertResultOwnership(resultOwnership);
|
||||
|
||||
if (commandArguments != null) {
|
||||
lazy.assert.array(
|
||||
commandArguments,
|
||||
`Expected "arguments" to be an array, got ${commandArguments}`
|
||||
);
|
||||
throw new lazy.error.UnsupportedOperationError(
|
||||
`"arguments" parameter is not supported yet`
|
||||
);
|
||||
}
|
||||
|
||||
if (thisParameter != null) {
|
||||
throw new lazy.error.UnsupportedOperationError(
|
||||
`"this" parameter is not supported yet`
|
||||
);
|
||||
}
|
||||
|
||||
const { contextId, realmId, sandbox } = this.#assertTarget(target);
|
||||
const realm = this.#getRealmInfoFromTarget({ contextId, realmId, sandbox });
|
||||
const evaluationResult = await this.messageHandler.forwardCommand({
|
||||
moduleName: "script",
|
||||
commandName: "callFunctionDeclaration",
|
||||
destination: {
|
||||
type: lazy.WindowGlobalMessageHandler.type,
|
||||
id: realm.context.id,
|
||||
},
|
||||
params: {
|
||||
awaitPromise,
|
||||
commandArguments,
|
||||
functionDeclaration,
|
||||
},
|
||||
});
|
||||
|
||||
return this.#buildReturnValue(evaluationResult, realm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a provided expression in the provided target, which is either a
|
||||
* realm or a browsing context.
|
||||
@ -162,6 +246,27 @@ class ScriptModule extends Module {
|
||||
`Expected "awaitPromise" to be a boolean, got ${awaitPromise}`
|
||||
);
|
||||
|
||||
this.#assertResultOwnership(resultOwnership);
|
||||
|
||||
const { contextId, realmId, sandbox } = this.#assertTarget(target);
|
||||
const realm = this.#getRealmInfoFromTarget({ contextId, realmId, sandbox });
|
||||
const evaluationResult = await this.messageHandler.forwardCommand({
|
||||
moduleName: "script",
|
||||
commandName: "evaluateExpression",
|
||||
destination: {
|
||||
type: lazy.WindowGlobalMessageHandler.type,
|
||||
id: realm.context.id,
|
||||
},
|
||||
params: {
|
||||
awaitPromise,
|
||||
expression: source,
|
||||
},
|
||||
});
|
||||
|
||||
return this.#buildReturnValue(evaluationResult, realm);
|
||||
}
|
||||
|
||||
#assertResultOwnership(resultOwnership) {
|
||||
if (![OwnershipModel.None, OwnershipModel.Root].includes(resultOwnership)) {
|
||||
throw new lazy.error.InvalidArgumentError(
|
||||
`Expected "resultOwnership" to be one of ${Object.values(
|
||||
@ -169,7 +274,9 @@ class ScriptModule extends Module {
|
||||
)}, got ${resultOwnership}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#assertTarget(target) {
|
||||
lazy.assert.object(
|
||||
target,
|
||||
`Expected "target" to be an object, got ${target}`
|
||||
@ -180,6 +287,7 @@ class ScriptModule extends Module {
|
||||
realm: realmId = null,
|
||||
sandbox = null,
|
||||
} = target;
|
||||
|
||||
if (contextId != null) {
|
||||
lazy.assert.string(
|
||||
contextId,
|
||||
@ -207,20 +315,10 @@ class ScriptModule extends Module {
|
||||
throw new lazy.error.InvalidArgumentError(`No context or realm provided`);
|
||||
}
|
||||
|
||||
const realm = this.#getRealmInfoFromTarget({ contextId, realmId, sandbox });
|
||||
const evaluationResult = await this.messageHandler.forwardCommand({
|
||||
moduleName: "script",
|
||||
commandName: "evaluateExpression",
|
||||
destination: {
|
||||
type: lazy.WindowGlobalMessageHandler.type,
|
||||
id: realm.context.id,
|
||||
},
|
||||
params: {
|
||||
awaitPromise,
|
||||
expression: source,
|
||||
},
|
||||
});
|
||||
return { contextId, realmId, sandbox };
|
||||
}
|
||||
|
||||
#buildReturnValue(evaluationResult, realm) {
|
||||
const rv = { realm: realm.realm };
|
||||
switch (evaluationResult.evaluationStatus) {
|
||||
// TODO: Compare with EvaluationStatus.Normal after Bug 1774444 is fixed.
|
||||
|
@ -94,48 +94,7 @@ class ScriptModule extends Module {
|
||||
};
|
||||
}
|
||||
|
||||
#toRawObject(maybeDebuggerObject) {
|
||||
if (maybeDebuggerObject instanceof Debugger.Object) {
|
||||
// Retrieve the referent for the provided Debugger.object.
|
||||
// See https://firefox-source-docs.mozilla.org/devtools-user/debugger-api/debugger.object/index.html
|
||||
const rawObject = maybeDebuggerObject.unsafeDereference();
|
||||
|
||||
// TODO: Getters for Maps and Sets iterators return "Opaque" objects and
|
||||
// are not iterable. RemoteValue.jsm' serializer should handle calling
|
||||
// waiveXrays on Maps/Sets/... and then unwaiveXrays on entries but since
|
||||
// we serialize with maxDepth=1, calling waiveXrays once on the root
|
||||
// object allows to return correctly serialized values.
|
||||
return Cu.waiveXrays(rawObject);
|
||||
}
|
||||
|
||||
// If maybeDebuggerObject was not a Debugger.Object, it is a primitive value
|
||||
// which can be used as is.
|
||||
return maybeDebuggerObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a provided expression in the current window global.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {boolean} awaitPromise
|
||||
* Determines if the command should wait for the return value of the
|
||||
* expression to resolve, if this return value is a Promise.
|
||||
* @param {string} expression
|
||||
* The expression to evaluate.
|
||||
*
|
||||
* @return {Object}
|
||||
* - evaluationStatus {EvaluationStatus} One of "normal", "throw".
|
||||
* - exceptionDetails {ExceptionDetails=} the details of the exception if
|
||||
* the evaluation status was "throw".
|
||||
* - result {RemoteValue=} the result of the evaluation serialized as a
|
||||
* RemoteValue if the evaluation status was "normal".
|
||||
*/
|
||||
async evaluateExpression(options) {
|
||||
const { awaitPromise, expression } = options;
|
||||
const rv = this.#global.executeInGlobal(expression, {
|
||||
url: this.messageHandler.window.document.baseURI,
|
||||
});
|
||||
|
||||
async #buildReturnValue(rv, awaitPromise) {
|
||||
let evaluationStatus, exception, result, stack;
|
||||
if ("return" in rv) {
|
||||
evaluationStatus = EvaluationStatus.Normal;
|
||||
@ -184,6 +143,78 @@ class ScriptModule extends Module {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#toRawObject(maybeDebuggerObject) {
|
||||
if (maybeDebuggerObject instanceof Debugger.Object) {
|
||||
// Retrieve the referent for the provided Debugger.object.
|
||||
// See https://firefox-source-docs.mozilla.org/devtools-user/debugger-api/debugger.object/index.html
|
||||
const rawObject = maybeDebuggerObject.unsafeDereference();
|
||||
|
||||
// TODO: Getters for Maps and Sets iterators return "Opaque" objects and
|
||||
// are not iterable. RemoteValue.jsm' serializer should handle calling
|
||||
// waiveXrays on Maps/Sets/... and then unwaiveXrays on entries but since
|
||||
// we serialize with maxDepth=1, calling waiveXrays once on the root
|
||||
// object allows to return correctly serialized values.
|
||||
return Cu.waiveXrays(rawObject);
|
||||
}
|
||||
|
||||
// If maybeDebuggerObject was not a Debugger.Object, it is a primitive value
|
||||
// which can be used as is.
|
||||
return maybeDebuggerObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function in the current window global.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {boolean} awaitPromise
|
||||
* Determines if the command should wait for the return value of the
|
||||
* expression to resolve, if this return value is a Promise.
|
||||
* @param {Array<RemoteValue>} commandArguments
|
||||
* The arguments to pass to the function call.
|
||||
* @param {string} functionDeclaration
|
||||
* The body of the function to call.
|
||||
*
|
||||
* @return {Object}
|
||||
* - evaluationStatus {EvaluationStatus} One of "normal", "throw".
|
||||
* - exceptionDetails {ExceptionDetails=} the details of the exception if
|
||||
* the evaluation status was "throw".
|
||||
* - result {RemoteValue=} the result of the evaluation serialized as a
|
||||
* RemoteValue if the evaluation status was "normal".
|
||||
*/
|
||||
async callFunctionDeclaration(options) {
|
||||
const { awaitPromise, functionDeclaration } = options;
|
||||
const rv = this.#global.executeInGlobal(`(${functionDeclaration})()`, {
|
||||
url: this.messageHandler.window.document.baseURI,
|
||||
});
|
||||
return this.#buildReturnValue(rv, awaitPromise);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a provided expression in the current window global.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {boolean} awaitPromise
|
||||
* Determines if the command should wait for the return value of the
|
||||
* expression to resolve, if this return value is a Promise.
|
||||
* @param {string} expression
|
||||
* The expression to evaluate.
|
||||
*
|
||||
* @return {Object}
|
||||
* - evaluationStatus {EvaluationStatus} One of "normal", "throw".
|
||||
* - exceptionDetails {ExceptionDetails=} the details of the exception if
|
||||
* the evaluation status was "throw".
|
||||
* - result {RemoteValue=} the result of the evaluation serialized as a
|
||||
* RemoteValue if the evaluation status was "normal".
|
||||
*/
|
||||
async evaluateExpression(options) {
|
||||
const { awaitPromise, expression } = options;
|
||||
const rv = this.#global.executeInGlobal(expression, {
|
||||
url: this.messageHandler.window.document.baseURI,
|
||||
});
|
||||
|
||||
return this.#buildReturnValue(rv, awaitPromise);
|
||||
}
|
||||
}
|
||||
|
||||
const script = ScriptModule;
|
||||
|
@ -1,13 +1,7 @@
|
||||
[call_function.py]
|
||||
[test_exception]
|
||||
expected: FAIL
|
||||
|
||||
[test_invalid_function]
|
||||
expected: FAIL
|
||||
|
||||
[test_arrow_function]
|
||||
expected: FAIL
|
||||
|
||||
[test_arguments]
|
||||
expected: FAIL
|
||||
|
||||
@ -23,14 +17,8 @@
|
||||
[test_remote_value_argument]
|
||||
expected: FAIL
|
||||
|
||||
[test_async_arrow_await_promise[True\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_async_arrow_await_promise[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_async_classic_await_promise[True\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_async_classic_await_promise[False\]]
|
||||
expected: FAIL
|
||||
|
@ -1,82 +1,7 @@
|
||||
[invalid.py]
|
||||
[test_params_target_invalid_type[None\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_target_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_target_invalid_type[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_target_invalid_type[target3\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_target_invalid_type[target4\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_context_invalid_type[None\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_context_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_context_invalid_type[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_context_invalid_type[context3\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_context_invalid_type[context4\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_sandbox_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_sandbox_invalid_type[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_sandbox_invalid_type[sandbox2\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_sandbox_invalid_type[sandbox3\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_context_unknown]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_realm_invalid_type[None\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_realm_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_realm_invalid_type[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_realm_invalid_type[realm3\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_realm_invalid_type[realm4\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_realm_unknown]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_function_declaration_invalid_type[None\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_function_declaration_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_function_declaration_invalid_type[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_function_declaration_invalid_type[function_declaration3\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_function_declaration_invalid_type[function_declaration4\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_this_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
@ -92,18 +17,6 @@
|
||||
[test_params_this_invalid_type[this4\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_arguments_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_arguments_invalid_type[SOME_STRING\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_arguments_invalid_type[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_arguments_invalid_type[arguments3\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_single_argument_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
@ -118,36 +31,3 @@
|
||||
|
||||
[test_params_single_argument_invalid_type[argument4\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_await_promise_invalid_type[None\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_await_promise_invalid_type[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_await_promise_invalid_type[0\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_await_promise_invalid_type[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_await_promise_invalid_type[await_promise4\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_await_promise_invalid_type[await_promise5\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_result_ownership_invalid_value[False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_result_ownership_invalid_value[_UNKNOWN_\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_result_ownership_invalid_value[42\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_result_ownership_invalid_value[result_ownership3\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_params_result_ownership_invalid_value[result_ownership4\]]
|
||||
expected: FAIL
|
||||
|
Loading…
Reference in New Issue
Block a user