|
| 1 | +# RFC 177: `fetch_json` and other `ShadowRealm` facilities |
| 2 | + |
| 3 | +## Summary |
| 4 | + |
| 5 | +This follows up [RFC 107][rfc-107]. |
| 6 | +[`ShadowRealm`s][proposal] are a new sandboxing primitive, currently in |
| 7 | +the process of being integrated into relevant Web specifications. |
| 8 | +`ShadowRealm` environments resemble vanilla JS shell environments, but |
| 9 | +do have some Web interfaces available, such as `URL`. |
| 10 | + |
| 11 | +I've submitted a [pull request][pr] with some changes to the |
| 12 | +test harness. |
| 13 | +The goal is to more easily allow existing WPT test files to run in |
| 14 | +`ShadowRealm` contexts, without writing separate duplicated tests for |
| 15 | +`ShadowRealm`. |
| 16 | + |
| 17 | +The most notable change is a `fetch_json` function to allow importing |
| 18 | +test data from JSON files across the sandboxing boundary. |
| 19 | + |
| 20 | +## Details |
| 21 | + |
| 22 | +The [pull request][pr] comprises four commits, which I'll explain in |
| 23 | +detail in this section. |
| 24 | + |
| 25 | +### Document self.GLOBAL.isShadowRealm() |
| 26 | + |
| 27 | +This commit is just an improvement to the documentation. |
| 28 | + |
| 29 | +### Add fetch_json() test harness API |
| 30 | + |
| 31 | +A common pattern for importing additional test data from a JSON file |
| 32 | +looks like this: |
| 33 | + |
| 34 | +```js |
| 35 | +promise_test(() => fetch("resources/mydata.json").then(res => res.json()).then(run_tests), "Loading data…"); |
| 36 | +``` |
| 37 | + |
| 38 | +`ShadowRealm` scopes do not have the `fetch()` API available. |
| 39 | +Additionally, the sandboxing only allows primitive or callable values |
| 40 | +to be passed into or out of the sandbox, not other objects. |
| 41 | +Therefore, this approach isn't feasible for `ShadowRealm` scopes. |
| 42 | + |
| 43 | +The proposed `fetch_json()`, in non-`ShadowRealm` scopes, is just a |
| 44 | +shorthand for the above: call `fetch()`, and then call the returned |
| 45 | +`Response` object's `json()` method. |
| 46 | + |
| 47 | +Inside `ShadowRealm` scopes, it is overwritten by a function that calls |
| 48 | +the host realm's `fetch()`, passes the response in string form across |
| 49 | +the sandbox boundary, and then inside the sandbox turns it into an |
| 50 | +object using `JSON.parse()`. |
| 51 | + |
| 52 | +The previous pattern described above will continue to work in |
| 53 | +non-`ShadowRealm` scopes, but if a test is to be executed inside a |
| 54 | +`ShadowRealm` scope, it will need to change to a pattern like the |
| 55 | +following: |
| 56 | + |
| 57 | +```js |
| 58 | +promise_test(() => fetch_json("resources/mydata.json").then(run_tests), "Loading data…"); |
| 59 | +``` |
| 60 | + |
| 61 | +### Expose location.search in ShadowRealm scopes |
| 62 | + |
| 63 | +Browser-specifc APIs such as `location` are not available in |
| 64 | +`ShadowRealm` scopes. |
| 65 | +However, the [mechanism for variant tests][variant] relies on |
| 66 | +`location.search`. |
| 67 | + |
| 68 | +This proposed change would expose a fake `location.search`, with the |
| 69 | +same value as the host realm's `location.search`, inside `ShadowRealm` |
| 70 | +scopes. |
| 71 | +This would allow test variants to be executed in `ShadowRealm` scopes. |
| 72 | + |
| 73 | +### Use fake setTimeout in ShadowRealm scopes |
| 74 | + |
| 75 | +`ShadowRealm` scopes also do not have timer-related APIs such as |
| 76 | +`setTimeout` and friends. |
| 77 | +However, several facilities from `testharness.js`, namely |
| 78 | +[`Test.step_timeout`][step_timeout], [`Test.step_wait`][step_wait], and |
| 79 | +[`Test.step_wait_func`][step_wait_func], rely on the global `setTimeout` |
| 80 | +being present. |
| 81 | + |
| 82 | +This proposed change adds a fallback version of `setTimeout` which is |
| 83 | +used by the test harness when the global one is not present, i.e. in |
| 84 | +`ShadowRealm` scopes. |
| 85 | +The fallback is not exposed directly to test code. |
| 86 | + |
| 87 | +## Risks |
| 88 | + |
| 89 | +The documentation commit carries no risk. |
| 90 | + |
| 91 | +The `fetch_json()` API doesn't change how any existing APIs work. |
| 92 | +Existing tests would have to opt-in to it by replacing their use of |
| 93 | +`fetch()` to import JSON test data, with `fetch_json()`. |
| 94 | +A natural time to make this change is when enabling a test to run in a |
| 95 | +`ShadowRealm` global scope; otherwise the test won't pass. |
| 96 | +Therefore, I think the potential risk is low. |
| 97 | + |
| 98 | +Of the four proposed changes, the fake `location.search` has the biggest |
| 99 | +potential risk. |
| 100 | +It's possible that future `ShadowRealm`-scope tests might depend on the |
| 101 | +`location` object not being present. |
| 102 | +This seems acceptable for the time being. |
| 103 | +But if that changes, the variant mechanism in files such as |
| 104 | +`common/subset-tests.js` and `common/subset-tests-by-key.js` would need |
| 105 | +to be rewritten to indicate which variant to run using a different |
| 106 | +mechanism than the URL search parameters. |
| 107 | + |
| 108 | +The fake `setTimeout` should not affect any existing tests. |
| 109 | +In non-`ShadowRealm` scopes, the behaviour should remain the same, |
| 110 | +because `setTimeout` is available. |
| 111 | +In `ShadowRealm` scopes, use of test harness APIs such as `step_timeout` |
| 112 | +would previously fail due to the missing `setTimeout`; now they can be |
| 113 | +used. |
| 114 | +Therefore, I think the potential risk is low. |
| 115 | + |
| 116 | +[rfc-107]: https://github.com/web-platform-tests/rfcs/blob/master/rfcs/shadowrealm-global.md |
| 117 | +[proposal]: https://github.com/tc39/proposal-shadowrealm |
| 118 | +[pr]: https://github.com/web-platform-tests/wpt/pull/43639 |
| 119 | +[variant]: https://web-platform-tests.org/writing-tests/testharness.html#variants |
| 120 | +[step_timeout]: https://web-platform-tests.org/writing-tests/testharness-api.html#Test.step_timeout |
| 121 | +[step_wait]: https://web-platform-tests.org/writing-tests/testharness-api.html#Test.step_wait |
| 122 | +[step_wait_func]: https://web-platform-tests.org/writing-tests/testharness-api.html#Test.step_wait_func |
0 commit comments