tor-browser

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

global.html (7277B)


      1 <!doctype html>
      2 <meta charset="utf-8">
      3 <title>Ensure Stream objects are created in expected globals. </title>
      4 
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 
      8 <body></body>
      9 <script>
     10 // These tests are loosely derived from Gecko's readable-stream-globals.js,
     11 // which is a test case designed around the JS Streams implementation.
     12 //
     13 // Unlike in JS Streams, where function calls switch realms and change
     14 // the resulting global of the resulting objects, in WebIDL streams,
     15 // the global of an object is (currently underspecified, but) intended
     16 // to be the "Relevant Global" of the 'this' object.
     17 //
     18 // See:
     19 // https://html.spec.whatwg.org/multipage/webappapis.html#relevant
     20 // https://github.com/whatwg/streams/issues/1213
     21 "use strict"
     22 
     23 const iframe = document.createElement("iframe")
     24 document.body.append(iframe)
     25 
     26 const otherGlobal = iframe.contentWindow;
     27 const OtherReadableStream = otherGlobal.ReadableStream
     28 const OtherReadableStreamDefaultReader = otherGlobal.ReadableStreamDefaultReader;
     29 const OtherReadableStreamDefaultController = otherGlobal.ReadableStreamDefaultController;
     30 
     31 promise_test(async () => {
     32 
     33    // Controllers
     34    let controller;
     35    let otherController;
     36 
     37    // Get Stream Prototypes and controllers.
     38    let streamController;
     39    let stream = new ReadableStream({start(c) { streamController = c; }});
     40 
     41    const callReaderThisGlobal = OtherReadableStream.prototype.getReader.call(stream);
     42    const newReaderOtherGlobal = new OtherReadableStreamDefaultReader(new ReadableStream());
     43 
     44    // Relevant Global Checking.
     45    assert_equals(callReaderThisGlobal instanceof ReadableStreamDefaultReader, true, "reader was created in this global (.call)");
     46    assert_equals(newReaderOtherGlobal instanceof ReadableStreamDefaultReader, false, "reader was created in other global (new)");
     47 
     48    assert_equals(callReaderThisGlobal instanceof OtherReadableStreamDefaultReader, false, "reader isn't coming from other global (.call)" );
     49    assert_equals(newReaderOtherGlobal instanceof OtherReadableStreamDefaultReader, true, "reader isn't coming from other global (new)");
     50 
     51    assert_equals(otherController instanceof ReadableStreamDefaultController, false, "otherController should come from other gloal")
     52 
     53 
     54    const request = callReaderThisGlobal.read();
     55    assert_equals(request instanceof Promise, true, "Promise comes from this global");
     56 
     57    streamController.close();
     58    const requestResult = await request;
     59    assert_equals(requestResult instanceof Object, true, "returned object comes from this global");
     60 }, "Stream objects created in expected globals")
     61 
     62 promise_test(async () => {
     63    const stream = new ReadableStream();
     64    const otherReader = new OtherReadableStreamDefaultReader(stream);
     65    const cancelPromise = ReadableStreamDefaultReader.prototype.cancel.call(otherReader);
     66    assert_equals(cancelPromise instanceof Promise, true, "Cancel promise comes from the same global as the stream");
     67    assert_equals(await cancelPromise, undefined, "Cancel promise resolves to undefined");
     68 }, "Cancel promise is created in same global as stream")
     69 
     70 // Refresh the streams and controllers.
     71 function getFreshInstances() {
     72    let controller;
     73    let otherController;
     74    let stream = new ReadableStream({
     75        start(c) {
     76            controller = c;
     77        }
     78    });
     79 
     80    new OtherReadableStream({
     81        start(c) {
     82            otherController = c;
     83        }
     84    });
     85 
     86    return {stream, controller, otherController}
     87 }
     88 
     89 
     90 promise_test(async () => {
     91    // Test closed promise on reader from another global (connected to a this-global stream)
     92    const {stream, controller, otherController} = getFreshInstances();
     93 
     94    const otherReader = new OtherReadableStreamDefaultReader(stream);
     95    const closedPromise = otherReader.closed;
     96    assert_equals(closedPromise instanceof otherGlobal.Promise, true, "Closed promise in other global.");
     97 }, "Closed Promise in correct global");
     98 
     99 promise_test(async () => {
    100    const {stream, controller, otherController} = getFreshInstances();
    101 
    102    const otherReader = OtherReadableStream.prototype.getReader.call(stream);
    103    assert_equals(otherReader instanceof ReadableStreamDefaultReader, true, "Reader comes from this global")
    104    const request = otherReader.read();
    105    assert_equals(request instanceof Promise, true, "Promise still comes from stream's realm (this realm)");
    106    otherController.close.call(controller);
    107    assert_equals((await request) instanceof otherGlobal.Object, true, "Object comes from other realm");
    108 }, "Reader objects in correct global");
    109 
    110 
    111 promise_test(async () => {
    112    const {stream, controller, otherController} = getFreshInstances();
    113    assert_equals(controller.desiredSize, 1, "Desired size is expected");
    114    Object.defineProperty(controller, "desiredSize",
    115        Object.getOwnPropertyDescriptor(OtherReadableStreamDefaultController.prototype, "desiredSize"));
    116    assert_equals(controller.desiredSize, 1, "Grafting getter from other prototype still returns desired size");
    117 }, "Desired size can be grafted from one prototype to another");
    118 
    119 promise_test(async () => {
    120    const {stream, controller, otherController} = getFreshInstances();
    121 
    122    // Make sure the controller close method returns the correct TypeError
    123    const enqueuedError = { name: "enqueuedError" };
    124    controller.error(enqueuedError);
    125 
    126    assert_throws_js(TypeError, () => controller.close(),  "Current Global controller");
    127    assert_throws_js(otherGlobal.TypeError, () => otherController.close.call(controller),  "Other global controller");
    128 }, "Closing errored stream throws object in appropriate global")
    129 
    130 promise_test(async () => {
    131    const {otherController} = getFreshInstances();
    132    // We can enqueue chunks from multiple globals
    133    const chunk = { name: "chunk" };
    134 
    135    let controller;
    136    const stream = new ReadableStream({ start(c) { controller = c; } }, { size() {return 1} });
    137    otherController.enqueue.call(controller, chunk);
    138    otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10));
    139    controller.enqueue(new otherGlobal.Uint8Array(10));
    140 }, "Can enqueue chunks from multiple globals")
    141 
    142 promise_test(async () => {
    143    const {stream, controller, otherController} = getFreshInstances();
    144    const chunk = { name: "chunk" };
    145 
    146    // We get the correct type errors out of a closed stream.
    147    controller.close();
    148    assert_throws_js(TypeError, () => controller.enqueue(new otherGlobal.Uint8Array(10)));
    149    assert_throws_js(otherGlobal.TypeError, () => otherController.enqueue.call(controller, chunk));
    150    assert_throws_js(otherGlobal.TypeError, () => otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10)));
    151 }, "Correct errors and globals for closed streams");
    152 
    153 
    154 promise_test(async () => {
    155    const {stream, controller, otherController} = getFreshInstances();
    156    // Branches out of tee are in the correct global
    157 
    158    const [branch1, branch2] = otherGlobal.ReadableStream.prototype.tee.call(stream);
    159    assert_equals(branch1 instanceof ReadableStream, true, "Branch created in this global (as stream is in this global)");
    160    assert_equals(branch2 instanceof ReadableStream, true, "Branch created in this global (as stream is in this global)");
    161 }, "Tee Branches in correct global");
    162 </script>