tor-browser

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

patched-global.any.js (4562B)


      1 // META: global=window,worker,shadowrealm
      2 'use strict';
      3 
      4 // Tests which patch the global environment are kept separate to avoid
      5 // interfering with other tests.
      6 
      7 const ReadableStream_prototype_locked_get =
      8      Object.getOwnPropertyDescriptor(ReadableStream.prototype, 'locked').get;
      9 
     10 // Verify that |rs| passes the brand check as a readable stream.
     11 function isReadableStream(rs) {
     12  try {
     13    ReadableStream_prototype_locked_get.call(rs);
     14    return true;
     15  } catch (e) {
     16    return false;
     17  }
     18 }
     19 
     20 test(t => {
     21  const rs = new ReadableStream();
     22 
     23  const trappedProperties = ['highWaterMark', 'size', 'start', 'type', 'mode'];
     24  for (const property of trappedProperties) {
     25    // eslint-disable-next-line no-extend-native, accessor-pairs
     26    Object.defineProperty(Object.prototype, property, {
     27      get() { throw new Error(`${property} getter called`); },
     28      configurable: true
     29    });
     30  }
     31  t.add_cleanup(() => {
     32    for (const property of trappedProperties) {
     33      delete Object.prototype[property];
     34    }
     35  });
     36 
     37  const [branch1, branch2] = rs.tee();
     38  assert_true(isReadableStream(branch1), 'branch1 should be a ReadableStream');
     39  assert_true(isReadableStream(branch2), 'branch2 should be a ReadableStream');
     40 }, 'ReadableStream tee() should not touch Object.prototype properties');
     41 
     42 test(t => {
     43  const rs = new ReadableStream();
     44 
     45  const oldReadableStream = self.ReadableStream;
     46 
     47  self.ReadableStream = function() {
     48    throw new Error('ReadableStream called on global object');
     49  };
     50 
     51  t.add_cleanup(() => {
     52    self.ReadableStream = oldReadableStream;
     53  });
     54 
     55  const [branch1, branch2] = rs.tee();
     56 
     57  assert_true(isReadableStream(branch1), 'branch1 should be a ReadableStream');
     58  assert_true(isReadableStream(branch2), 'branch2 should be a ReadableStream');
     59 }, 'ReadableStream tee() should not call the global ReadableStream');
     60 
     61 promise_test(async t => {
     62  const rs = new ReadableStream({
     63    start(c) {
     64      c.enqueue(1);
     65      c.enqueue(2);
     66      c.enqueue(3);
     67      c.close();
     68    }
     69  });
     70 
     71  const oldReadableStreamGetReader = ReadableStream.prototype.getReader;
     72 
     73  const ReadableStreamDefaultReader = (new ReadableStream()).getReader().constructor;
     74  const oldDefaultReaderRead = ReadableStreamDefaultReader.prototype.read;
     75  const oldDefaultReaderCancel = ReadableStreamDefaultReader.prototype.cancel;
     76  const oldDefaultReaderReleaseLock = ReadableStreamDefaultReader.prototype.releaseLock;
     77 
     78  self.ReadableStream.prototype.getReader = function() {
     79    throw new Error('patched getReader() called');
     80  };
     81 
     82  ReadableStreamDefaultReader.prototype.read = function() {
     83    throw new Error('patched read() called');
     84  };
     85  ReadableStreamDefaultReader.prototype.cancel = function() {
     86    throw new Error('patched cancel() called');
     87  };
     88  ReadableStreamDefaultReader.prototype.releaseLock = function() {
     89    throw new Error('patched releaseLock() called');
     90  };
     91 
     92  t.add_cleanup(() => {
     93    self.ReadableStream.prototype.getReader = oldReadableStreamGetReader;
     94 
     95    ReadableStreamDefaultReader.prototype.read = oldDefaultReaderRead;
     96    ReadableStreamDefaultReader.prototype.cancel = oldDefaultReaderCancel;
     97    ReadableStreamDefaultReader.prototype.releaseLock = oldDefaultReaderReleaseLock;
     98  });
     99 
    100  // read the first chunk, then cancel
    101  for await (const chunk of rs) {
    102    break;
    103  }
    104 
    105  // should be able to acquire a new reader
    106  const reader = oldReadableStreamGetReader.call(rs);
    107  // stream should be cancelled
    108  await reader.closed;
    109 }, 'ReadableStream async iterator should use the original values of getReader() and ReadableStreamDefaultReader ' +
    110   'methods');
    111 
    112 test(t => {
    113  const oldPromiseThen = Promise.prototype.then;
    114  Promise.prototype.then = () => {
    115    throw new Error('patched then() called');
    116  };
    117  t.add_cleanup(() => {
    118    Promise.prototype.then = oldPromiseThen;
    119  });
    120  const [branch1, branch2] = new ReadableStream().tee();
    121  assert_true(isReadableStream(branch1), 'branch1 should be a ReadableStream');
    122  assert_true(isReadableStream(branch2), 'branch2 should be a ReadableStream');
    123 }, 'tee() should not call Promise.prototype.then()');
    124 
    125 test(t => {
    126  const oldPromiseThen = Promise.prototype.then;
    127  Promise.prototype.then = () => {
    128    throw new Error('patched then() called');
    129  };
    130  t.add_cleanup(() => {
    131    Promise.prototype.then = oldPromiseThen;
    132  });
    133  let readableController;
    134  const rs = new ReadableStream({
    135    start(c) {
    136      readableController = c;
    137    }
    138  });
    139  const ws = new WritableStream();
    140  rs.pipeTo(ws);
    141  readableController.close();
    142 }, 'pipeTo() should not call Promise.prototype.then()');