2021-01-11 12:13:41 -05:00
|
|
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
2020-09-27 06:22:32 -04:00
|
|
|
import { assert, assertEquals, assertThrows, unitTest } from "./test_util.ts";
|
2020-04-30 10:40:10 -04:00
|
|
|
|
|
|
|
unitTest(function writableStreamDesiredSizeOnReleasedWriter() {
|
|
|
|
const ws = new WritableStream();
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
writer.releaseLock();
|
|
|
|
assertThrows(() => {
|
|
|
|
writer.desiredSize;
|
|
|
|
}, TypeError);
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function writableStreamDesiredSizeInitialValue() {
|
|
|
|
const ws = new WritableStream();
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
assertEquals(writer.desiredSize, 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(async function writableStreamDesiredSizeClosed() {
|
|
|
|
const ws = new WritableStream();
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
await writer.close();
|
|
|
|
assertEquals(writer.desiredSize, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function writableStreamStartThrowsDesiredSizeNull() {
|
|
|
|
const ws = new WritableStream({
|
|
|
|
start(c): void {
|
|
|
|
c.error();
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
assertEquals(writer.desiredSize, null, "desiredSize should be null");
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function getWriterOnClosingStream() {
|
|
|
|
const ws = new WritableStream({});
|
|
|
|
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
writer.close();
|
|
|
|
writer.releaseLock();
|
|
|
|
|
|
|
|
ws.getWriter();
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(async function getWriterOnClosedStream() {
|
|
|
|
const ws = new WritableStream({});
|
|
|
|
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
await writer.close();
|
|
|
|
writer.releaseLock();
|
|
|
|
|
|
|
|
ws.getWriter();
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function getWriterOnAbortedStream() {
|
|
|
|
const ws = new WritableStream({});
|
|
|
|
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
writer.abort();
|
|
|
|
writer.releaseLock();
|
|
|
|
|
|
|
|
ws.getWriter();
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function getWriterOnErroredStream() {
|
|
|
|
const ws = new WritableStream({
|
|
|
|
start(c): void {
|
|
|
|
c.error();
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
return writer.closed.then(
|
|
|
|
(v) => {
|
|
|
|
throw new Error(`writer.closed fulfilled unexpectedly with: ${v}`);
|
|
|
|
},
|
|
|
|
() => {
|
|
|
|
writer.releaseLock();
|
|
|
|
ws.getWriter();
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function closedAndReadyOnReleasedWriter() {
|
|
|
|
const ws = new WritableStream({});
|
|
|
|
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
writer.releaseLock();
|
|
|
|
|
|
|
|
return writer.closed.then(
|
|
|
|
(v) => {
|
|
|
|
throw new Error("writer.closed fulfilled unexpectedly with: " + v);
|
|
|
|
},
|
|
|
|
(closedRejection) => {
|
|
|
|
assertEquals(
|
|
|
|
closedRejection.name,
|
|
|
|
"TypeError",
|
2020-07-14 15:24:17 -04:00
|
|
|
"closed promise should reject with a TypeError",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
return writer.ready.then(
|
|
|
|
(v) => {
|
|
|
|
throw new Error("writer.ready fulfilled unexpectedly with: " + v);
|
|
|
|
},
|
|
|
|
(readyRejection) =>
|
|
|
|
assertEquals(
|
|
|
|
readyRejection,
|
|
|
|
closedRejection,
|
2020-07-14 15:24:17 -04:00
|
|
|
"ready promise should reject with the same error",
|
|
|
|
),
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function sinkMethodsCalledAsMethods() {
|
|
|
|
let thisObject: Sink | null = null;
|
|
|
|
// Calls to Sink methods after the first are implicitly ignored. Only the
|
|
|
|
// first value that is passed to the resolver is used.
|
|
|
|
class Sink {
|
|
|
|
start(): void {
|
|
|
|
assertEquals(this, thisObject, "start should be called as a method");
|
|
|
|
}
|
|
|
|
|
|
|
|
write(): void {
|
|
|
|
assertEquals(this, thisObject, "write should be called as a method");
|
|
|
|
}
|
|
|
|
|
|
|
|
close(): void {
|
|
|
|
assertEquals(this, thisObject, "close should be called as a method");
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(): void {
|
|
|
|
assertEquals(this, thisObject, "abort should be called as a method");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const theSink = new Sink();
|
|
|
|
thisObject = theSink;
|
|
|
|
const ws = new WritableStream(theSink);
|
|
|
|
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
|
|
|
|
writer.write("a");
|
|
|
|
const closePromise = writer.close();
|
|
|
|
|
|
|
|
const ws2 = new WritableStream(theSink);
|
|
|
|
const writer2 = ws2.getWriter();
|
|
|
|
const abortPromise = writer2.abort();
|
|
|
|
|
|
|
|
return Promise.all([closePromise, abortPromise]).then(undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function sizeShouldNotBeCalledAsMethod() {
|
|
|
|
const strategy = {
|
|
|
|
size(): number {
|
|
|
|
if (this !== undefined) {
|
|
|
|
throw new Error("size called as a method");
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const ws = new WritableStream({}, strategy);
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
return writer.write("a");
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function redundantReleaseLockIsNoOp() {
|
|
|
|
const ws = new WritableStream();
|
|
|
|
const writer1 = ws.getWriter();
|
|
|
|
assertEquals(
|
|
|
|
undefined,
|
|
|
|
writer1.releaseLock(),
|
2020-07-14 15:24:17 -04:00
|
|
|
"releaseLock() should return undefined",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
const writer2 = ws.getWriter();
|
|
|
|
assertEquals(
|
|
|
|
undefined,
|
|
|
|
writer1.releaseLock(),
|
2020-07-14 15:24:17 -04:00
|
|
|
"no-op releaseLock() should return undefined",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
// Calling releaseLock() on writer1 should not interfere with writer2. If it did, then the ready promise would be
|
|
|
|
// rejected.
|
|
|
|
return writer2.ready;
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function readyPromiseShouldFireBeforeReleaseLock() {
|
|
|
|
const events: string[] = [];
|
|
|
|
const ws = new WritableStream();
|
|
|
|
const writer = ws.getWriter();
|
|
|
|
return writer.ready.then(() => {
|
|
|
|
// Force the ready promise back to a pending state.
|
|
|
|
const writerPromise = writer.write("dummy");
|
|
|
|
const readyPromise = writer.ready.catch(() => events.push("ready"));
|
|
|
|
const closedPromise = writer.closed.catch(() => events.push("closed"));
|
|
|
|
writer.releaseLock();
|
|
|
|
return Promise.all([readyPromise, closedPromise]).then(() => {
|
|
|
|
assertEquals(
|
|
|
|
events,
|
|
|
|
["ready", "closed"],
|
2020-07-14 15:24:17 -04:00
|
|
|
"ready promise should fire before closed promise",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
// Stop the writer promise hanging around after the test has finished.
|
|
|
|
return Promise.all([writerPromise, ws.abort()]).then(undefined);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function subclassingWritableStream() {
|
|
|
|
class Subclass extends WritableStream {
|
|
|
|
extraFunction(): boolean {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(
|
|
|
|
Object.getPrototypeOf(Subclass.prototype) === WritableStream.prototype,
|
2020-07-14 15:24:17 -04:00
|
|
|
"Subclass.prototype's prototype should be WritableStream.prototype",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
assert(
|
|
|
|
Object.getPrototypeOf(Subclass) === WritableStream,
|
2020-07-14 15:24:17 -04:00
|
|
|
"Subclass's prototype should be WritableStream",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
const sub = new Subclass();
|
|
|
|
assert(
|
|
|
|
sub instanceof WritableStream,
|
2020-07-14 15:24:17 -04:00
|
|
|
"Subclass object should be an instance of WritableStream",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
assert(
|
|
|
|
sub instanceof Subclass,
|
2020-07-14 15:24:17 -04:00
|
|
|
"Subclass object should be an instance of Subclass",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
const lockedGetter = Object.getOwnPropertyDescriptor(
|
|
|
|
WritableStream.prototype,
|
2020-07-14 15:24:17 -04:00
|
|
|
"locked",
|
2020-04-30 10:40:10 -04:00
|
|
|
)!.get!;
|
|
|
|
assert(
|
|
|
|
lockedGetter.call(sub) === sub.locked,
|
2020-07-14 15:24:17 -04:00
|
|
|
"Subclass object should pass brand check",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
assert(
|
|
|
|
sub.extraFunction(),
|
2020-07-14 15:24:17 -04:00
|
|
|
"extraFunction() should be present on Subclass object",
|
2020-04-30 10:40:10 -04:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
unitTest(function lockedGetterShouldReturnTrue() {
|
|
|
|
const ws = new WritableStream();
|
|
|
|
assert(!ws.locked, "stream should not be locked");
|
|
|
|
ws.getWriter();
|
|
|
|
assert(ws.locked, "stream should be locked");
|
|
|
|
});
|