-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC 89: [testdriver] Add an execute_script function to testdriver. #89
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# RFC 89: `testdriver` Add an `execute_script` method. | ||
|
||
## Summary | ||
|
||
Add an `execute_script` method to testdriver that takes a js function, | ||
arguments to pass to the function, and the context id to execute it it | ||
in a remote context. If the function returns a promise we return the | ||
resolved value of the promise, otherwise we return the return value of | ||
the function. | ||
|
||
## Details | ||
|
||
Sometimes a test window wants to check the status of something in a | ||
remote window. It's possible to do this in a number of ways, for | ||
example by posting messages from the remote window to the test | ||
window. However in cross-origin cases messge passing on the js side | ||
can be difficult or impossible. In addition when tests are defined in | ||
the test window, it's useful to avoid putting complex logic in other | ||
browsing contexts because these won't have the same error handling | ||
properties as the test window. | ||
|
||
A simple way to solve these problems is to provide a mechansim to | ||
execute script in a different context. This isn't possible using | ||
content APIs alone, but is possible in WebDriver, and we can reuse | ||
that to define a `execute_script` function that works across contexts: | ||
|
||
``` | ||
execute_script(fn, args, context) | ||
``` | ||
|
||
`body` is a js function for the script to execute. To pass it to the | ||
remote context, this is converted to a string using | ||
`toString()`. `args` is null or an array of arguments to pass to the | ||
function on the remote side. Arguments are passed as JSON. `context` | ||
is an object that can be resolved as a testdriver context id to | ||
identify the remote context (see [RFC | ||
88](https://github.com/web-platform-tests/rfcs/pull/88). If the return | ||
value of the function when executed in the remote context is a promise | ||
the promise returned by `execute_script` resolves to the resolved | ||
value of that promise. Otherwise the `execute_script` promise resolves | ||
to the return value of the function. | ||
|
||
The wptrunner implementation uses [Execute Async | ||
Script](https://w3c.github.io/webdriver/#execute-async-script). We | ||
wrap the provided script text and arguments into an `Execute Async | ||
Script` call as: | ||
|
||
``` | ||
let callback = arguments[arguments.length - 1]; | ||
let rv = ({function_string}).apply(null, {json.dumps(args)}); | ||
return Promise.resolve(rv).then(callback) | ||
`` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. needs to be ``` |
||
|
||
## Example | ||
|
||
``` | ||
<iframe src="child.html"></iframe> | ||
<script> | ||
setup({single_test: true}); | ||
onload = { | ||
let value = test_driver.execute_script(async (elemId) => { | ||
await new Promise(resolve => onload(resolve)) | ||
return document.getElementById(elemId).textContent | ||
}, ["test"], iframe.contentWindow); | ||
assert_equals(value, "PASS"); | ||
done(); | ||
} | ||
</script> | ||
``` | ||
|
||
## Risks | ||
|
||
WebDriver is single-threaded, so all the WebDriver-based actions need | ||
to be queued. That means that waiting for a promise in a remote | ||
context blocks all testdriver functionality that uses WebDriver, and | ||
also blocks the harness from returning results. This implies a high | ||
risk of timeouts. | ||
Comment on lines
+73
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also implies that recursive calls will never work, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. |
||
|
||
## References | ||
|
||
[PR 29803](https://github.com/web-platform-tests/wpt/pull/29803) | ||
contains a prototype implementation of this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
References in
fn
are evaluated oncontext
, whileargs
are evaluated on the caller context, right?e.g.
would result in [the URL of
context
, the URL ofcontext
, the URL of the caller ofexecute_script
, the URL of the caller ofexecute_script
].There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is "body" here? Should this be "fn"?