1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
// Adapted from js/src/tests/non262/ReadableStream/subclassing.js to suit requirements of xpcshell-testing.
function assertEq(a, b) {
Assert.equal(a, b);
}
function assertThrowsInstanceOf(fun, err) {
var regexp = new RegExp(err.name);
print(regexp);
Assert.throws(fun, regexp);
}
// Spot-check subclassing of stream constructors.
// ReadableStream can be subclassed.
class PartyStreamer extends ReadableStream {}
let started = false;
add_task(function subclass_helper() {
// The base class constructor is called.
let stream = new PartyStreamer({
// (The ReadableStream constructor calls this start method.)
start() {
started = true;
},
});
assertEq(started, true);
// The instance's prototype chain is correct.
assertEq(stream.__proto__, PartyStreamer.prototype);
assertEq(stream.__proto__.__proto__, ReadableStream.prototype);
assertEq(stream.__proto__.__proto__.__proto__, Object.prototype);
assertEq(stream.__proto__.__proto__.__proto__.__proto__, null);
assertEq(stream instanceof ReadableStream, true);
// Non-generic methods can be called on the resulting stream.
stream.getReader();
assertEq(stream.locked, true);
});
add_task(function strategy_helper() {
// CountQueuingStrategy can be subclassed.
class PixelStrategy extends CountQueuingStrategy {}
assertEq(
new PixelStrategy({ highWaterMark: 4 }).__proto__,
PixelStrategy.prototype
);
// The base class constructor is called.
assertThrowsInstanceOf(() => new PixelStrategy(), TypeError);
assertEq(new PixelStrategy({ highWaterMark: -1 }).highWaterMark, -1);
// // VerySmartStrategy can be subclassed.
// class VerySmartStrategy extends ByteLengthQueuingStrategy {
// size(chunk) {
// return super.size(chunk) * 8;
// }
// }
// let vss = new VerySmartStrategy({ highWaterMark: 12 });
// assertEq(vss.size(new ArrayBuffer(8)), 64);
// assertEq(vss.__proto__, VerySmartStrategy.prototype);
});
// Even ReadableStreamDefaultReader can be subclassed.
add_task(async function readerTest() {
const ReadableStreamDefaultReader = new ReadableStream().getReader()
.constructor;
class MindReader extends ReadableStreamDefaultReader {
async read() {
let foretold = { value: "death", done: false };
let actual = await super.read();
actual = foretold; // ZOMG I WAS RIGHT, EXACTLY AS FORETOLD they should call me a righter
return actual;
}
}
let stream = new ReadableStream({
start(c) {
c.enqueue("one");
c.enqueue("two");
},
pull(c) {
c.close();
},
});
let reader = new MindReader(stream);
let result = await reader.read();
assertEq(result.value, "death");
reader.releaseLock();
reader = stream.getReader();
result = await reader.read();
assertEq(result.done, false);
assertEq(result.value, "two");
result = await reader.read();
assertEq(result.done, true);
assertEq(result.value, undefined);
});
add_task(function default_controller() {
// Even ReadableStreamDefaultController, which can't be constructed,
// can be subclassed.
let ReadableStreamDefaultController;
new ReadableStream({
start(c) {
ReadableStreamDefaultController = c.constructor;
},
});
class MasterController extends ReadableStreamDefaultController {
constructor() {
// don't call super, it'll just throw
return Object.create(MasterController.prototype);
}
}
let c = new MasterController();
// The prototype chain is per spec.
assertEq(c instanceof ReadableStreamDefaultController, true);
// But the instance does not have the internal slots of a
// ReadableStreamDefaultController, so the non-generic methods can't be used.
assertThrowsInstanceOf(() => c.enqueue("horse"), TypeError);
});
|