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