ef41fe604c02c7d9242d482c2270e1758df432a2
[WebKit-https.git] / LayoutTests / streams / reference-implementation / brand-checks.html
1 <!DOCTYPE html>
2 <script src='../../resources/testharness.js'></script>
3 <script src='../../resources/testharnessreport.js'></script>
4 <script src='resources/streams-utils.js'></script>
5 <script>
6 // This is updated till https://github.com/whatwg/streams/commit/ec5ffa036308d9f6350d2946560d48cdbf090939
7
8 var ReadableStreamReader;
9 var ReadableStreamController;
10
11 test(function() {
12     // It's not exposed globally, but we test a few of its properties here.
13     ReadableStreamReader = (new ReadableStream()).getReader().constructor;
14 }, 'Can get the ReadableStreamReader constructor indirectly');
15
16 test(function() {
17     // It's not exposed globally, but we test a few of its properties here.
18     new ReadableStream({
19         start: function(c) {
20             ReadableStreamController = c.constructor;
21         }
22     });
23 }, 'Can get the ReadableStreamController constructor indirectly');
24
25 function fakeReadableStream() {
26     return {
27         cancel: function(reason) { return Promise.resolve(); },
28         getReader: function() { return new ReadableStreamReader(new ReadableStream()); },
29         pipeThrough: function(obj, options) { return obj.readable; },
30         pipeTo: function() { return Promise.resolve(); },
31         tee: function() { return [realReadableStream(), realReadableStream()]; }
32     };
33 }
34
35 function realReadableStream() {
36     return new ReadableStream();
37 }
38
39 function fakeWritableStream() {
40   return {
41     get closed() { return Promise.resolve(); },
42     get ready() { return Promise.resolve(); },
43     get state() { return 'closed' },
44     abort(reason) { return Promise.resolve(); },
45     close() { return Promise.resolve(); },
46     write(chunk) { return Promise.resolve(); }
47   };
48 }
49
50 function realWritableStream() {
51   return new WritableStream();
52 }
53
54 function fakeReadableStreamReader() {
55     return {
56         get closed() { return Promise.resolve(); },
57         cancel: function(reason) { return Promise.resolve(); },
58         read: function() { return Promise.resolve({ value: undefined, done: true }); },
59         releaseLock: function() { return; }
60     };
61 }
62
63 function fakeReadableStreamController() {
64     return {
65         close: function() { },
66         enqueue: function(chunk) { },
67         error: function(e) { }
68     };
69 }
70
71 function fakeByteLengthQueuingStrategy() {
72     return {
73         highWaterMark: 0,
74         size: function(chunk) {
75             return chunk.byteLength;
76         }
77     };
78 }
79
80 function realByteLengthQueuingStrategy() {
81     return new ByteLengthQueuingStrategy({ highWaterMark: 1 });
82 }
83
84 function fakeCountQueuingStrategy() {
85     return {
86         highWaterMark: 0,
87         size: function(chunk) {
88             return 1;
89         }
90     }
91 }
92
93 function realCountQueuingStrategy() {
94     return new CountQueuingStrategy({ highWaterMark: 1 });
95 }
96
97 function getterRejects(test, obj, getterName, target, endTest) {
98     var getter = Object.getOwnPropertyDescriptor(obj, getterName).get;
99
100     getter.call(target).then(
101         test.step_func(function() { assert_unreached(getterName + ' should not fulfill'); }),
102         test.step_func(function(e) {
103             assert_throws(new TypeError(), function() { throw e; }, getterName + ' should reject with a TypeError');
104             if (endTest === true) {
105                 test.done();
106             }
107         }));
108 }
109
110 function methodRejects(test, obj, methodName, target, endTest) {
111     var method = obj[methodName];
112
113     method.call(target).then(
114         test.step_func(function() { assert_unreached(methodName + ' should not fulfill'); }),
115         test.step_func(function(e) {
116             assert_throws(new TypeError(), function() { throw e; }, methodName + ' should reject with a TypeError');
117             if (endTest === true) {
118                 test.done();
119             }
120         }));
121 }
122
123 function getterThrows(obj, getterName, target) {
124   var getter = Object.getOwnPropertyDescriptor(obj, getterName).get;
125
126     assert_throws(new TypeError(), function() { getter.call(target); }, getterName + ' should throw a TypeError');
127 }
128
129 function methodThrows(obj, methodName, target) {
130     var method = obj[methodName];
131
132     assert_throws(new TypeError(), function() { method.call(target); }, methodName + ' should throw a TypeError');
133 }
134
135 var test1 = async_test('ReadableStream.prototype.cancel enforces a brand check');
136 test1.step(function() {
137     methodRejects(test1, ReadableStream.prototype, 'cancel', fakeReadableStream());
138     methodRejects(test1, ReadableStream.prototype, 'cancel', realWritableStream(), true);
139 });
140
141 test(function() {
142     methodThrows(ReadableStream.prototype, 'getReader', fakeReadableStream());
143     methodThrows(ReadableStream.prototype, 'getReader', realWritableStream());
144 }, 'ReadableStream.prototype.getReader enforces a brand check');
145
146 test(function() {
147     var pipeToArguments;
148     var thisValue = {
149         pipeTo: function() {
150             pipeToArguments = arguments;
151         }
152     };
153
154     var input = { readable: {}, writable: {} };
155     var options = {};
156     var result = ReadableStream.prototype.pipeThrough.call(thisValue, input, options);
157
158     assert_array_equals(pipeToArguments, [input.writable, options], 'correct arguments should be passed to thisValue.pipeTo');
159     assert_equals(result, input.readable, 'return value should be the passed readable property');
160 }, 'ReadableStream.prototype.pipeThrough works generically on its this and its arguments');
161
162 test(function() {
163     ReadableStream.prototype.pipeTo.call(fakeReadableStream(), fakeWritableStream()); // Check it does not throw.
164 }, 'ReadableStream.prototype.pipeTo works generically on its this and its arguments');
165
166 test(function() {
167     methodThrows(ReadableStream.prototype, 'tee', fakeReadableStream());
168     methodThrows(ReadableStream.prototype, 'tee', realWritableStream());
169 }, 'ReadableStream.prototype.tee enforces a brand check');
170
171 test(function() {
172     assert_throws(new TypeError(), function() { new ReadableStreamReader(fakeReadableStream()); }, 'Constructing a ReadableStreamReader should throw');
173 }, 'ReadableStreamReader enforces a brand check on its argument');
174
175 var test2 = async_test('ReadableStreamReader.prototype.closed enforces a brand check');
176 test2.step(function() {
177     getterRejects(test2, ReadableStreamReader.prototype, 'closed', fakeReadableStreamReader());
178     getterRejects(test2, ReadableStreamReader.prototype, 'closed', realReadableStream(), true);
179 });
180
181 var test3 = async_test('ReadableStreamReader.prototype.cancel enforces a brand check');
182 test3.step(function() {
183     methodRejects(test3, ReadableStreamReader.prototype, 'cancel', fakeReadableStreamReader());
184     methodRejects(test3, ReadableStreamReader.prototype, 'cancel', realReadableStream(), true);
185 });
186
187 var test4 = async_test('ReadableStreamReader.prototype.read enforces a brand check');
188 test4.step(function() {
189     methodRejects(test4, ReadableStreamReader.prototype, 'read', fakeReadableStreamReader());
190     methodRejects(test4, ReadableStreamReader.prototype, 'read', realReadableStream(), true);
191 });
192
193 var test5 = async_test('ReadableStreamReader.prototype.read enforces a brand check');
194 test5.step(function() {
195     methodRejects(test5, ReadableStreamReader.prototype, 'read', fakeReadableStreamReader());
196     methodRejects(test5, ReadableStreamReader.prototype, 'read', realReadableStream(), true);
197 });
198
199 test(function() {
200     methodThrows(ReadableStreamReader.prototype, 'releaseLock', fakeReadableStreamReader());
201     methodThrows(ReadableStreamReader.prototype, 'releaseLock', realReadableStream());
202 }, 'ReadableStreamReader.prototype.releaseLock enforces a brand check');
203
204 test(function() {
205     assert_throws(new TypeError(), function() { new ReadableStreamController(fakeReadableStream()); }, 'Constructing a ReadableStreamController should throw');
206 }, 'ReadableStreamController enforces a brand check on its argument');
207
208 test(function() {
209     assert_throws(new TypeError(), function() { new ReadableStreamController(realReadableStream()); }, 'Constructing a ReadableStreamController should throw');
210 }, 'ReadableStreamController can\'t be given a fully-constructed ReadableStream');
211
212 test(function() {
213   methodThrows(ReadableStreamController.prototype, 'close', fakeReadableStreamController());
214 }, 'ReadableStreamController.prototype.close enforces a brand check');
215
216 test(function() {
217   methodThrows(ReadableStreamController.prototype, 'enqueue', fakeReadableStreamController());
218 }, 'ReadableStreamController.prototype.enqueue enforces a brand check');
219
220 test(function() {
221   methodThrows(ReadableStreamController.prototype, 'error', fakeReadableStreamController());
222 }, 'ReadableStreamController.prototype.error enforces a brand check');
223
224 var test6 = async_test('WritableStream.prototype.closed enforces a brand check');
225 test6.step(function() {
226     getterRejects(test6, WritableStream.prototype, 'closed', fakeWritableStream());
227     getterRejects(test6, WritableStream.prototype, 'closed', realReadableStream(), true);
228 });
229
230 var test7 = async_test('WritableStream.prototype.ready enforces a brand check');
231 test7.step(function() {
232     getterRejects(test7, WritableStream.prototype, 'ready', fakeWritableStream());
233     getterRejects(test7, WritableStream.prototype, 'ready', realReadableStream(), true);
234 });
235
236 test(function() {
237     getterThrows(WritableStream.prototype, 'state', fakeWritableStream());
238     getterThrows(WritableStream.prototype, 'state', realReadableStream());
239 }, 'WritableStream.prototype.state enforces a brand check');
240
241 var test8 = async_test('WritableStream.prototype.abort enforces a brand check');
242 test8.step(function() {
243     methodRejects(test8, WritableStream.prototype, 'abort', fakeWritableStream());
244     methodRejects(test8, WritableStream.prototype, 'abort', realReadableStream(), true);
245 });
246
247 var test9 = async_test('WritableStream.prototype.write enforces a brand check');
248 test9.step(function() {
249     methodRejects(test9, WritableStream.prototype, 'write', fakeWritableStream());
250     methodRejects(test9, WritableStream.prototype, 'write', realReadableStream(), true);
251 });
252
253 var test10 = async_test('WritableStream.prototype.close enforces a brand check');
254 test10.step(function() {
255     methodRejects(test10, WritableStream.prototype, 'close', fakeWritableStream());
256     methodRejects(test10, WritableStream.prototype, 'close', realReadableStream(), true);
257 });
258
259 test(function() {
260     var thisValue = null;
261     var returnValue = { 'returned from': 'byteLength getter' };
262     var chunk = {
263         get byteLength() {
264             return returnValue;
265         }
266     };
267
268     assert_equals(ByteLengthQueuingStrategy.prototype.size.call(thisValue, chunk), returnValue);
269 }, 'ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments');
270
271 test(function() {
272     var thisValue = null;
273     var chunk = {
274         get byteLength() {
275             throw new TypeError('shouldn\'t be called');
276         }
277     };
278
279     assert_equals(CountQueuingStrategy.prototype.size.call(thisValue, chunk), 1);
280 }, 'CountQueuingStrategy.prototype.size should work generically on its this and its arguments');
281 </script>