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