1// TODO: it would be nice to support `idl_array.add_objects`
2function fetch_text(url) {
3    return fetch(url).then(function (r) {
4        if (!r.ok) {
5            throw new Error("Error fetching " + url + ".");
6        }
7        return r.text();
8    });
9}
10
11/**
12 * idl_test_shadowrealm is a promise_test wrapper that handles the fetching of the IDL, and
13 * running the code in a `ShadowRealm`, avoiding repetitive boilerplate.
14 *
15 * @see https://github.com/tc39/proposal-shadowrealm
16 * @param {String[]} srcs Spec name(s) for source idl files (fetched from
17 *      /interfaces/{name}.idl).
18 * @param {String[]} deps Spec name(s) for dependency idl files (fetched
19 *      from /interfaces/{name}.idl). Order is important - dependencies from
20 *      each source will only be included if they're already know to be a
21 *      dependency (i.e. have already been seen).
22 */
23function idl_test_shadowrealm(srcs, deps) {
24    const script_urls = [
25        "/resources/testharness.js",
26        "/resources/WebIDLParser.js",
27        "/resources/idlharness.js",
28    ];
29    promise_setup(async t => {
30        const realm = new ShadowRealm();
31        // https://github.com/web-platform-tests/wpt/issues/31996
32        realm.evaluate("globalThis.self = globalThis; undefined;");
33
34        realm.evaluate(`
35            globalThis.self.GLOBAL = {
36                isWindow: function() { return false; },
37                isWorker: function() { return false; },
38                isShadowRealm: function() { return true; },
39            }; undefined;
40        `);
41
42        const ss = await Promise.all(script_urls.map(url => fetch_text(url)));
43        for (const s of ss) {
44            realm.evaluate(s);
45        }
46        const specs = await Promise.all(srcs.concat(deps).map(spec => {
47            return fetch_text("/interfaces/" + spec + ".idl");
48        }));
49        const idls = JSON.stringify(specs);
50
51        const results = JSON.parse(await new Promise(
52          realm.evaluate(`(resolve,reject) => {
53              const idls = ${idls};
54              add_completion_callback(function (tests, harness_status, asserts_run) {
55                resolve(JSON.stringify(tests));
56              });
57
58              // Without the wrapping test, testharness.js will think it's done after it has run
59              // the first idlharness test.
60              test(() => {
61                  const idl_array = new IdlArray();
62                  for (let i = 0; i < ${srcs.length}; i++) {
63                      idl_array.add_idls(idls[i]);
64                  }
65                  for (let i = ${srcs.length}; i < ${srcs.length + deps.length}; i++) {
66                      idl_array.add_dependency_idls(idls[i]);
67                  }
68                  idl_array.test();
69              }, "setup");
70          }`)
71        ));
72
73        // We ran the tests in the ShadowRealm and gathered the results. Now treat them as if
74        // we'd run them directly here, so we can see them.
75        for (const {name, status, message} of results) {
76            // TODO: make this an API in testharness.js - needs RFC?
77            promise_test(t => {t.set_status(status, message); t.phase = t.phases.HAS_RESULT; t.done()}, name);
78        }
79    }, "outer setup");
80}
81// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
82