1// META: global=window,worker 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 9promise_test(() => { 10 const writer = setupTestStream(); 11 12 const writePromises = [ 13 writer.write(2), 14 writer.write(Number.MAX_SAFE_INTEGER) 15 ]; 16 17 assert_equals(writer.desiredSize, 0 - 2 - Number.MAX_SAFE_INTEGER, 18 'desiredSize must be calculated using double-precision floating-point arithmetic (after writing two chunks)'); 19 20 return Promise.all(writePromises).then(() => { 21 assert_equals(writer.desiredSize, 0, '[[queueTotalSize]] must clamp to 0 if it becomes negative'); 22 }); 23}, 'Floating point arithmetic must manifest near NUMBER.MAX_SAFE_INTEGER (total ends up positive)'); 24 25promise_test(() => { 26 const writer = setupTestStream(); 27 28 const writePromises = [ 29 writer.write(1e-16), 30 writer.write(1) 31 ]; 32 33 assert_equals(writer.desiredSize, 0 - 1e-16 - 1, 34 'desiredSize must be calculated using double-precision floating-point arithmetic (after writing two chunks)'); 35 36 return Promise.all(writePromises).then(() => { 37 assert_equals(writer.desiredSize, 0, '[[queueTotalSize]] must clamp to 0 if it becomes negative'); 38 }); 39}, 'Floating point arithmetic must manifest near 0 (total ends up positive, but clamped)'); 40 41promise_test(() => { 42 const writer = setupTestStream(); 43 44 const writePromises = [ 45 writer.write(1e-16), 46 writer.write(1), 47 writer.write(2e-16) 48 ]; 49 50 assert_equals(writer.desiredSize, 0 - 1e-16 - 1 - 2e-16, 51 'desiredSize must be calculated using double-precision floating-point arithmetic (after writing three chunks)'); 52 53 return Promise.all(writePromises).then(() => { 54 assert_equals(writer.desiredSize, 0 - 1e-16 - 1 - 2e-16 + 1e-16 + 1 + 2e-16, 55 'desiredSize must be calculated using floating-point arithmetic (after the three chunks have finished writing)'); 56 }); 57}, 'Floating point arithmetic must manifest near 0 (total ends up positive, and not clamped)'); 58 59promise_test(() => { 60 const writer = setupTestStream(); 61 62 const writePromises = [ 63 writer.write(2e-16), 64 writer.write(1) 65 ]; 66 67 assert_equals(writer.desiredSize, 0 - 2e-16 - 1, 68 'desiredSize must be calculated using double-precision floating-point arithmetic (after writing two chunks)'); 69 70 return Promise.all(writePromises).then(() => { 71 assert_equals(writer.desiredSize, 0 - 2e-16 - 1 + 2e-16 + 1, 72 'desiredSize must be calculated using floating-point arithmetic (after the two chunks have finished writing)'); 73 }); 74}, 'Floating point arithmetic must manifest near 0 (total ends up zero)'); 75 76function setupTestStream() { 77 const strategy = { 78 size(x) { 79 return x; 80 }, 81 highWaterMark: 0 82 }; 83 84 const ws = new WritableStream({}, strategy); 85 86 return ws.getWriter(); 87} 88