tor-browser

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

floating-point-total-queue-size.any.js (4879B)


      1 // META: global=window,worker,shadowrealm
      2 'use strict';
      3 
      4 // Due to the limitations of floating-point precision, the calculation of desiredSize sometimes gives different answers
      5 // than adding up the items in the queue would. It is important that implementations give the same result in these edge
      6 // cases so that developers do not come to depend on non-standard behaviour. See
      7 // https://github.com/whatwg/streams/issues/582 and linked issues for further discussion.
      8 
      9 promise_test(() => {
     10  const { reader, controller } = setupTestStream();
     11 
     12  controller.enqueue(2);
     13  assert_equals(controller.desiredSize, 0 - 2, 'desiredSize must be -2 after enqueueing such a chunk');
     14 
     15  controller.enqueue(Number.MAX_SAFE_INTEGER);
     16  assert_equals(controller.desiredSize, 0 - Number.MAX_SAFE_INTEGER - 2,
     17    'desiredSize must be calculated using double-precision floating-point arithmetic (adding a second chunk)');
     18 
     19  return reader.read().then(() => {
     20    assert_equals(controller.desiredSize, 0 - Number.MAX_SAFE_INTEGER - 2 + 2,
     21      'desiredSize must be calculated using double-precision floating-point arithmetic (subtracting a chunk)');
     22 
     23    return reader.read();
     24  }).then(() => {
     25    assert_equals(controller.desiredSize, 0, '[[queueTotalSize]] must clamp to 0 if it becomes negative');
     26  });
     27 }, 'Floating point arithmetic must manifest near NUMBER.MAX_SAFE_INTEGER (total ends up positive)');
     28 
     29 promise_test(() => {
     30  const { reader, controller } = setupTestStream();
     31 
     32  controller.enqueue(1e-16);
     33  assert_equals(controller.desiredSize, 0 - 1e-16, 'desiredSize must be -1e16 after enqueueing such a chunk');
     34 
     35  controller.enqueue(1);
     36  assert_equals(controller.desiredSize, 0 - 1e-16 - 1,
     37    'desiredSize must be calculated using double-precision floating-point arithmetic (adding a second chunk)');
     38 
     39  return reader.read().then(() => {
     40    assert_equals(controller.desiredSize, 0 - 1e-16 - 1 + 1e-16,
     41      'desiredSize must be calculated using double-precision floating-point arithmetic (subtracting a chunk)');
     42 
     43    return reader.read();
     44  }).then(() => {
     45    assert_equals(controller.desiredSize, 0, '[[queueTotalSize]] must clamp to 0 if it becomes negative');
     46  });
     47 }, 'Floating point arithmetic must manifest near 0 (total ends up positive, but clamped)');
     48 
     49 promise_test(() => {
     50  const { reader, controller } = setupTestStream();
     51 
     52  controller.enqueue(1e-16);
     53  assert_equals(controller.desiredSize, 0 - 1e-16, 'desiredSize must be -2e16 after enqueueing such a chunk');
     54 
     55  controller.enqueue(1);
     56  assert_equals(controller.desiredSize, 0 - 1e-16 - 1,
     57    'desiredSize must be calculated using double-precision floating-point arithmetic (adding a second chunk)');
     58 
     59  controller.enqueue(2e-16);
     60  assert_equals(controller.desiredSize, 0 - 1e-16 - 1 - 2e-16,
     61    'desiredSize must be calculated using double-precision floating-point arithmetic (adding a third chunk)');
     62 
     63  return reader.read().then(() => {
     64    assert_equals(controller.desiredSize, 0 - 1e-16 - 1 - 2e-16 + 1e-16,
     65      'desiredSize must be calculated using double-precision floating-point arithmetic (subtracting a chunk)');
     66 
     67    return reader.read();
     68  }).then(() => {
     69    assert_equals(controller.desiredSize, 0 - 1e-16 - 1 - 2e-16 + 1e-16 + 1,
     70      'desiredSize must be calculated using double-precision floating-point arithmetic (subtracting a second chunk)');
     71 
     72    return reader.read();
     73  }).then(() => {
     74    assert_equals(controller.desiredSize, 0 - 1e-16 - 1 - 2e-16 + 1e-16 + 1 + 2e-16,
     75      'desiredSize must be calculated using double-precision floating-point arithmetic (subtracting a third chunk)');
     76  });
     77 }, 'Floating point arithmetic must manifest near 0 (total ends up positive, and not clamped)');
     78 
     79 promise_test(() => {
     80  const { reader, controller } = setupTestStream();
     81 
     82  controller.enqueue(2e-16);
     83  assert_equals(controller.desiredSize, 0 - 2e-16, 'desiredSize must be -2e16 after enqueueing such a chunk');
     84 
     85  controller.enqueue(1);
     86  assert_equals(controller.desiredSize, 0 - 2e-16 - 1,
     87    'desiredSize must be calculated using double-precision floating-point arithmetic (adding a second chunk)');
     88 
     89  return reader.read().then(() => {
     90    assert_equals(controller.desiredSize, 0 - 2e-16 - 1 + 2e-16,
     91      'desiredSize must be calculated using double-precision floating-point arithmetic (subtracting a chunk)');
     92 
     93    return reader.read();
     94  }).then(() => {
     95    assert_equals(controller.desiredSize, 0,
     96      'desiredSize must be calculated using double-precision floating-point arithmetic (subtracting a second chunk)');
     97  });
     98 }, 'Floating point arithmetic must manifest near 0 (total ends up zero)');
     99 
    100 function setupTestStream() {
    101  const strategy = {
    102    size(x) {
    103      return x;
    104    },
    105    highWaterMark: 0
    106  };
    107 
    108  let controller;
    109  const rs = new ReadableStream({
    110    start(c) {
    111      controller = c;
    112    }
    113  }, strategy);
    114 
    115  return { reader: rs.getReader(), controller };
    116 }