Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / serviceworkers / test / utils.js
blob28be239593e52d02380e81c79c118152918ecd30
1 function waitForState(worker, state, context) {
2   return new Promise(resolve => {
3     function onStateChange() {
4       if (worker.state === state) {
5         worker.removeEventListener("statechange", onStateChange);
6         resolve(context);
7       }
8     }
10     // First add an event listener, so we won't miss any change that happens
11     // before we check the current state.
12     worker.addEventListener("statechange", onStateChange);
14     // Now check if the worker is already in the desired state.
15     onStateChange();
16   });
19 /**
20  * Helper for browser tests to issue register calls from the content global and
21  * wait for the SW to progress to the active state, as most tests desire.
22  * From the ContentTask.spawn, use via
23  * `content.wrappedJSObject.registerAndWaitForActive`.
24  */
25 async function registerAndWaitForActive(script, maybeScope) {
26   console.log("...calling register");
27   let opts = undefined;
28   if (maybeScope) {
29     opts = { scope: maybeScope };
30   }
31   const reg = await navigator.serviceWorker.register(script, opts);
32   // Unless registration resurrection happens, the SW should be in the
33   // installing slot.
34   console.log("...waiting for activation");
35   await waitForState(reg.installing, "activated", reg);
36   console.log("...activated!");
37   return reg;
40 /**
41  * Helper to create an iframe with the given URL and return the first
42  * postMessage payload received.  This is intended to be used when creating
43  * cross-origin iframes.
44  *
45  * A promise will be returned that resolves with the payload of the postMessage
46  * call.
47  */
48 function createIframeAndWaitForMessage(url) {
49   const iframe = document.createElement("iframe");
50   document.body.appendChild(iframe);
51   return new Promise(resolve => {
52     window.addEventListener(
53       "message",
54       event => {
55         resolve(event.data);
56       },
57       { once: true }
58     );
59     iframe.src = url;
60   });
63 /**
64  * Helper to create a nested iframe into the iframe created by
65  * createIframeAndWaitForMessage().
66  *
67  * A promise will be returned that resolves with the payload of the postMessage
68  * call.
69  */
70 function createNestedIframeAndWaitForMessage(url) {
71   const iframe = document.getElementsByTagName("iframe")[0];
72   iframe.contentWindow.postMessage("create nested iframe", "*");
73   return new Promise(resolve => {
74     window.addEventListener(
75       "message",
76       event => {
77         resolve(event.data);
78       },
79       { once: true }
80     );
81   });
84 async function unregisterAll() {
85   const registrations = await navigator.serviceWorker.getRegistrations();
86   for (const reg of registrations) {
87     await reg.unregister();
88   }
91 /**
92  * Make a blob that contains random data and therefore shouldn't compress all
93  * that well.
94  */
95 function makeRandomBlob(size) {
96   const arr = new Uint8Array(size);
97   let offset = 0;
98   /**
99    * getRandomValues will only provide a maximum of 64k of data at a time and
100    * will error if we ask for more, so using a while loop for get a random value
101    * which much larger than 64k.
102    * https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#exceptions
103    */
104   while (offset < size) {
105     const nextSize = Math.min(size - offset, 65536);
106     window.crypto.getRandomValues(new Uint8Array(arr.buffer, offset, nextSize));
107     offset += nextSize;
108   }
109   return new Blob([arr], { type: "application/octet-stream" });
112 async function fillStorage(cacheBytes, idbBytes) {
113   // ## Fill Cache API Storage
114   const cache = await caches.open("filler");
115   await cache.put("fill", new Response(makeRandomBlob(cacheBytes)));
117   // ## Fill IDB
118   const storeName = "filler";
119   let db = await new Promise((resolve, reject) => {
120     let openReq = indexedDB.open("filler", 1);
121     openReq.onerror = event => {
122       reject(event.target.error);
123     };
124     openReq.onsuccess = event => {
125       resolve(event.target.result);
126     };
127     openReq.onupgradeneeded = event => {
128       const useDB = event.target.result;
129       useDB.onerror = error => {
130         reject(error);
131       };
132       const store = useDB.createObjectStore(storeName);
133       store.put({ blob: makeRandomBlob(idbBytes) }, "filler-blob");
134     };
135   });