tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

web-platform-test-shims.js (2693B)


      1 // This is used when jstests.py runs web-platform-tests in the shell.
      2 // Some tests require browser features that the shell doesn't have built-in.
      3 
      4 // window.self
      5 // <https://html.spec.whatwg.org/multipage/window-object.html#dom-self>
      6 if (!("self" in this)) {
      7  this.self = this;
      8 }
      9 
     10 // window.setTimeout, clearTimeout, setInterval, clearInterval
     11 // <https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout>
     12 if (!("setTimeout" in this)) {
     13  // Not-very-compliant polyfill for setTimeout, based on Promise.
     14 
     15  // When this array becomes non-empty, call scheduleWork.
     16  let timeouts = [];
     17 
     18  // Fake clock used to order timeouts.
     19  let now = 0;
     20 
     21  // Least positive integer not yet used as a timer id.
     22  let next_id = 1;
     23 
     24  // Add an active timer record to timeouts.
     25  function enqueue(id, t, cb) {
     26    if (typeof cb !== 'function') {
     27      let code = "" + cb;
     28      cb = () => eval(code);
     29    }
     30    t += now;
     31    timeouts.push({id, t, cb});
     32    timeouts.sort((a, b) => a.t - b.t);
     33    if (timeouts.length === 1) {
     34      scheduleWork();
     35    }
     36  }
     37 
     38  // Register a microtask to make sure timers are actually processed. There
     39  // should be at most one of these microtasks pending at a time.
     40  function scheduleWork() {
     41    // Number of times to let the microtask queue spin before running a
     42    // timeout. The idea is to let all Promises resolve between consecutive
     43    // timer callbacks. Of course, this is a hack; whatever number is used
     44    // here, an async function can simply await that many times plus one to
     45    // observe that timeouts are being handled as microtasks, not events.
     46    let delay = 10;
     47 
     48    function handleTimeouts() {
     49      if (--delay > 0) {
     50        Promise.resolve().then(handleTimeouts);
     51        return;
     52      }
     53      if (timeouts.length > 0) {
     54        let {t, cb} = timeouts.shift();
     55        if (now < t) {
     56          now = t;
     57        }
     58        if (timeouts.length > 0) {
     59          scheduleWork();  // There's more to do after this.
     60        }
     61        cb();
     62      }
     63    }
     64    Promise.resolve().then(handleTimeouts);
     65  }
     66 
     67  this.setTimeout = function (cb, t, ...args) {
     68    let id = next_id++;
     69    enqueue(id, t, () => cb(...args));
     70    return id;
     71  };
     72 
     73  this.clearTimeout = function (id) {
     74    timeouts = timeouts.filter(obj => obj.id !== id);
     75  };
     76 
     77  this.setInterval = function (cb, t, ...args) {
     78    let id = next_id++;
     79    let func = () => {
     80      enqueue(id, t, func);
     81      cb(...args);
     82    };
     83    enqueue(id, t, func);
     84    return id;
     85  };
     86 
     87  this.clearInterval = this.clearTimeout;
     88 }
     89 
     90 // Some tests in web platform tests leave promise rejections unhandled.
     91 if ("ignoreUnhandledRejections" in this) {
     92  ignoreUnhandledRejections();
     93 }