diff --git a/rfcs/execute_script.md b/rfcs/execute_script.md new file mode 100644 index 00000000..7ce0bc8d --- /dev/null +++ b/rfcs/execute_script.md @@ -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) +`` + +## Example + +``` + + +``` + +## 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. + +## References + +[PR 29803](https://github.com/web-platform-tests/wpt/pull/29803) +contains a prototype implementation of this.