slow_doc.sjs (3557B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 "use strict"; 8 9 // stolen from file_blocked_script.sjs 10 function setGlobalState(key, data) { 11 const x = { 12 data, 13 QueryInterface: ChromeUtils.generateQI([]), 14 }; 15 x.wrappedJSObject = x; 16 setObjectState(key, x); 17 } 18 19 function getGlobalState(key) { 20 let data; 21 getObjectState(key, function (x) { 22 data = x && x.wrappedJSObject.data; 23 }); 24 return data; 25 } 26 27 function handleRequest(request, response) { 28 const second = request.queryString == "second"; 29 const secondInContainer = request.queryString == "secondInContainer"; 30 if (second || secondInContainer) { 31 // Initial request for document. 32 response.setStatusLine(request.httpVersion, 200, "OK"); 33 response.setHeader("Cache-Control", "no-cache", false); 34 response.setHeader("Content-Type", "text/html", false); 35 response.write("<!doctype html>"); 36 response.write('<p id="first">first</p>'); 37 if (secondInContainer) { 38 response.write("<section>"); 39 } 40 // Reference a slow script which will block parsing the rest of this 41 // document. 42 response.write('<script src="?script"></script>'); 43 response.write('<p id="second">second</p>'); 44 if (secondInContainer) { 45 response.write("</section>"); 46 } 47 return; 48 } 49 50 if (request.queryString == "script") { 51 // This is the request to load the slow, blocking script. 52 response.processAsync(); 53 // Store the response in the global state. 54 setGlobalState("a11y-script-response", response); 55 const resolve = getGlobalState("a11y-script-resolve"); 56 if (resolve) { 57 // Sometimes, the request to finish loading the script can arrive before 58 // the initial request to load the script, since they are requested from 59 // different processes. Notify the finish request that the initial request 60 // has been handled. 61 resolve(); 62 } 63 return; 64 } 65 66 if (request.queryString == "scriptFinish") { 67 // This is the request to finish (unblock) the slow script. 68 response.processAsync(); 69 const finish = () => { 70 response.setStatusLine(request.httpVersion, 200, "OK"); 71 response.setHeader("Cache-Control", "no-cache", false); 72 response.setHeader("Content-Type", "application/json", false); 73 response.write("true"); // the payload doesn't matter. 74 response.finish(); 75 const blockedResponse = getGlobalState("a11y-script-response"); 76 blockedResponse.setStatusLine(request.httpVersion, 200, "OK"); 77 blockedResponse.setHeader("Cache-Control", "no-cache", false); 78 blockedResponse.setHeader("Content-Type", "text/javascript", false); 79 blockedResponse.write(";"); // the payload doesn't matter. 80 blockedResponse.finish(); 81 setGlobalState("a11y-script-response", undefined); 82 setGlobalState("a11y-script-resolve", undefined); 83 }; 84 if (getGlobalState("a11y-script-response")) { 85 // The initial script request has already been handled. 86 finish(); 87 } else { 88 // This finish request arrived before the initial request. Set up a 89 // Promise so we know when the initial request has been handled. 90 const promise = Promise.withResolvers(); 91 promise.promise.then(finish); 92 setGlobalState("a11y-script-resolve", promise.resolve); 93 } 94 } 95 }