• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// META: global=window,worker
2// META: script=../resources/recording-streams.js
3// META: script=../resources/test-utils.js
4'use strict';
5
6// Here we just test that the strategies are correctly passed to the readable and writable sides. We assume that
7// ReadableStream and WritableStream will correctly apply the strategies when they are being used by a TransformStream
8// and so it isn't necessary to repeat their tests here.
9
10test(() => {
11  const ts = new TransformStream({}, { highWaterMark: 17 });
12  assert_equals(ts.writable.getWriter().desiredSize, 17, 'desiredSize should be 17');
13}, 'writableStrategy highWaterMark should work');
14
15promise_test(() => {
16  const ts = recordingTransformStream({}, undefined, { highWaterMark: 9 });
17  const writer = ts.writable.getWriter();
18  for (let i = 0; i < 10; ++i) {
19    writer.write(i);
20  }
21  return delay(0).then(() => {
22    assert_array_equals(ts.events, [
23      'transform', 0, 'transform', 1, 'transform', 2, 'transform', 3, 'transform', 4,
24      'transform', 5, 'transform', 6, 'transform', 7, 'transform', 8],
25                        'transform() should have been called 9 times');
26  });
27}, 'readableStrategy highWaterMark should work');
28
29promise_test(t => {
30  let writableSizeCalled = false;
31  let readableSizeCalled = false;
32  let transformCalled = false;
33  const ts = new TransformStream(
34    {
35      transform(chunk, controller) {
36        t.step(() => {
37          transformCalled = true;
38          assert_true(writableSizeCalled, 'writableStrategy.size() should have been called');
39          assert_false(readableSizeCalled, 'readableStrategy.size() should not have been called');
40          controller.enqueue(chunk);
41          assert_true(readableSizeCalled, 'readableStrategy.size() should have been called');
42        });
43      }
44    },
45    {
46      size() {
47        writableSizeCalled = true;
48        return 1;
49      }
50    },
51    {
52      size() {
53        readableSizeCalled = true;
54        return 1;
55      },
56      highWaterMark: Infinity
57    });
58  return ts.writable.getWriter().write().then(() => {
59    assert_true(transformCalled, 'transform() should be called');
60  });
61}, 'writable should have the correct size() function');
62
63test(() => {
64  const ts = new TransformStream();
65  const writer = ts.writable.getWriter();
66  assert_equals(writer.desiredSize, 1, 'default writable HWM is 1');
67  writer.write(undefined);
68  assert_equals(writer.desiredSize, 0, 'default chunk size is 1');
69}, 'default writable strategy should be equivalent to { highWaterMark: 1 }');
70
71promise_test(t => {
72  const ts = new TransformStream({
73    transform(chunk, controller) {
74      return t.step(() => {
75        assert_equals(controller.desiredSize, 0, 'desiredSize should be 0');
76        controller.enqueue(undefined);
77        // The first chunk enqueued is consumed by the pending read().
78        assert_equals(controller.desiredSize, 0, 'desiredSize should still be 0');
79        controller.enqueue(undefined);
80        assert_equals(controller.desiredSize, -1, 'desiredSize should be -1');
81      });
82    }
83  });
84  const writePromise = ts.writable.getWriter().write();
85  return ts.readable.getReader().read().then(() => writePromise);
86}, 'default readable strategy should be equivalent to { highWaterMark: 0 }');
87
88test(() => {
89  assert_throws_js(RangeError, () => new TransformStream(undefined, { highWaterMark: -1 }),
90                   'should throw RangeError for negative writableHighWaterMark');
91  assert_throws_js(RangeError, () => new TransformStream(undefined, undefined, { highWaterMark: -1 }),
92                   'should throw RangeError for negative readableHighWaterMark');
93  assert_throws_js(RangeError, () => new TransformStream(undefined, { highWaterMark: NaN }),
94                   'should throw RangeError for NaN writableHighWaterMark');
95  assert_throws_js(RangeError, () => new TransformStream(undefined, undefined, { highWaterMark: NaN }),
96                   'should throw RangeError for NaN readableHighWaterMark');
97}, 'a RangeError should be thrown for an invalid highWaterMark');
98
99const objectThatConvertsTo42 = {
100  toString() {
101    return '42';
102  }
103};
104
105test(() => {
106  const ts = new TransformStream(undefined, { highWaterMark: objectThatConvertsTo42 });
107  const writer = ts.writable.getWriter();
108  assert_equals(writer.desiredSize, 42, 'writable HWM is 42');
109}, 'writableStrategy highWaterMark should be converted to a number');
110
111test(() => {
112  const ts = new TransformStream({
113    start(controller) {
114      assert_equals(controller.desiredSize, 42, 'desiredSize should be 42');
115    }
116  }, undefined, { highWaterMark: objectThatConvertsTo42 });
117}, 'readableStrategy highWaterMark should be converted to a number');
118
119promise_test(t => {
120  const ts = new TransformStream(undefined, undefined, {
121    size() { return NaN; },
122    highWaterMark: 1
123  });
124  const writer = ts.writable.getWriter();
125  return promise_rejects_js(t, RangeError, writer.write(), 'write should reject');
126}, 'a bad readableStrategy size function should cause writer.write() to reject on an identity transform');
127
128promise_test(t => {
129  const ts = new TransformStream({
130    transform(chunk, controller) {
131      // This assert has the important side-effect of catching the error, so transform() does not throw.
132      assert_throws_js(RangeError, () => controller.enqueue(chunk), 'enqueue should throw');
133    }
134  }, undefined, {
135    size() {
136      return -1;
137    },
138    highWaterMark: 1
139  });
140
141  const writer = ts.writable.getWriter();
142  return writer.write().then(() => {
143    return Promise.all([
144      promise_rejects_js(t, RangeError, writer.ready, 'ready should reject'),
145      promise_rejects_js(t, RangeError, writer.closed, 'closed should reject'),
146      promise_rejects_js(t, RangeError, ts.readable.getReader().closed, 'readable closed should reject')
147    ]);
148  });
149}, 'a bad readableStrategy size function should error the stream on enqueue even when transformer.transform() ' +
150   'catches the exception');
151