node/test/parallel/test-whatwg-writablestream.js

269 lines
6.4 KiB
JavaScript
Raw Permalink Normal View History

// Flags: --expose-internals --no-warnings
'use strict';
const common = require('../common');
const assert = require('assert');
const {
WritableStream,
WritableStreamDefaultController,
WritableStreamDefaultWriter,
CountQueuingStrategy,
} = require('stream/web');
const {
kState,
} = require('internal/webstreams/util');
const {
isPromise,
} = require('util/types');
const {
kTransfer,
} = require('internal/worker/js_transferable');
const {
inspect,
} = require('util');
class Sink {
constructor() {
this.chunks = [];
}
start() {
this.started = true;
}
write(chunk) {
this.chunks.push(chunk);
}
close() {
this.closed = true;
}
abort() {
this.aborted = true;
}
}
{
const stream = new WritableStream();
assert(stream[kState].controller instanceof WritableStreamDefaultController);
assert(!stream.locked);
assert.strictEqual(typeof stream.abort, 'function');
assert.strictEqual(typeof stream.close, 'function');
assert.strictEqual(typeof stream.getWriter, 'function');
}
['a', false, 1, null].forEach((sink) => {
assert.throws(() => new WritableStream(sink), {
code: 'ERR_INVALID_ARG_TYPE',
});
});
['a', false, 1].forEach((strategy) => {
assert.throws(() => new WritableStream({}, strategy), {
code: 'ERR_INVALID_ARG_TYPE',
});
});
[1, false, ''].forEach((type) => {
assert.throws(() => new WritableStream({ type }), {
code: 'ERR_INVALID_ARG_VALUE',
});
});
['a', {}].forEach((highWaterMark) => {
assert.throws(() => new WritableStream({}, { highWaterMark }), {
code: 'ERR_INVALID_ARG_VALUE',
});
});
['a', false, {}].forEach((size) => {
assert.throws(() => new WritableStream({}, { size }), {
code: 'ERR_INVALID_ARG_TYPE',
});
});
{
new WritableStream({});
new WritableStream([]);
new WritableStream({}, null);
new WritableStream({}, {});
new WritableStream({}, []);
}
{
const sink = new Sink();
const stream = new WritableStream(
sink,
new CountQueuingStrategy({ highWaterMark: 1 }));
assert(!stream.locked);
const writer = stream.getWriter();
assert(stream.locked);
assert(writer instanceof WritableStreamDefaultWriter);
assert(isPromise(writer.closed));
assert(isPromise(writer.ready));
assert(typeof writer.desiredSize, 'number');
assert(typeof writer.abort, 'function');
assert(typeof writer.close, 'function');
assert(typeof writer.releaseLock, 'function');
assert(typeof writer.write, 'function');
writer.releaseLock();
assert(!stream.locked);
const writer2 = stream.getWriter();
assert(sink.started);
writer2.closed.then(common.mustCall());
writer2.ready.then(common.mustCall());
writer2.close().then(common.mustCall(() => {
assert.strict(sink.closed);
}));
}
{
const sink = new Sink();
const stream = new WritableStream(
sink,
new CountQueuingStrategy({ highWaterMark: 1 }));
const error = new Error('boom');
const writer = stream.getWriter();
assert.rejects(writer.closed, error).then(common.mustCall());
writer.abort(error).then(common.mustCall(() => {
assert.strictEqual(stream[kState].state, 'errored');
assert(sink.aborted);
}));
}
{
const sink = new Sink();
const stream = new WritableStream(
sink, { highWaterMark: 1 }
);
async function write(stream) {
const writer = stream.getWriter();
const p = writer.write('hello');
assert.strictEqual(writer.desiredSize, 0);
await p;
assert.strictEqual(writer.desiredSize, 1);
}
write(stream).then(common.mustCall(() => {
assert.deepStrictEqual(['hello'], sink.chunks);
}));
}
{
assert.throws(() => Reflect.get(WritableStream.prototype, 'locked', {}), {
code: 'ERR_INVALID_THIS',
});
assert.rejects(() => WritableStream.prototype.abort({}), {
code: 'ERR_INVALID_THIS',
}).then(common.mustCall());
assert.rejects(() => WritableStream.prototype.close({}), {
code: 'ERR_INVALID_THIS',
}).then(common.mustCall());
assert.throws(() => WritableStream.prototype.getWriter.call(), {
code: 'ERR_INVALID_THIS',
});
assert.throws(() => WritableStream.prototype[kTransfer].call(), {
code: 'ERR_INVALID_THIS',
});
assert.rejects(
Reflect.get(WritableStreamDefaultWriter.prototype, 'closed'), {
code: 'ERR_INVALID_THIS',
}).then(common.mustCall());
assert.rejects(
Reflect.get(WritableStreamDefaultWriter.prototype, 'ready'), {
code: 'ERR_INVALID_THIS',
}).then(common.mustCall());
assert.throws(
() => Reflect.get(WritableStreamDefaultWriter.prototype, 'desiredSize'), {
code: 'ERR_INVALID_THIS',
});
assert.rejects(WritableStreamDefaultWriter.prototype.abort({}), {
code: 'ERR_INVALID_THIS',
}).then(common.mustCall());
assert.rejects(WritableStreamDefaultWriter.prototype.close({}), {
code: 'ERR_INVALID_THIS',
}).then(common.mustCall());
assert.rejects(WritableStreamDefaultWriter.prototype.write({}), {
code: 'ERR_INVALID_THIS',
}).then(common.mustCall());
assert.throws(() => WritableStreamDefaultWriter.prototype.releaseLock({}), {
code: 'ERR_INVALID_THIS',
});
assert.throws(() => {
Reflect.get(WritableStreamDefaultController.prototype, 'signal', {});
}, {
code: 'ERR_INVALID_THIS',
});
assert.throws(() => {
WritableStreamDefaultController.prototype.error({});
}, {
code: 'ERR_INVALID_THIS',
});
}
{
let controller;
const writable = new WritableStream({
start(c) { controller = c; }
});
assert.strictEqual(
inspect(writable),
'WritableStream { locked: false, state: \'writable\' }');
assert.strictEqual(
inspect(writable, { depth: null }),
'WritableStream { locked: false, state: \'writable\' }');
assert.strictEqual(
inspect(writable, { depth: 0 }),
'WritableStream [Object]');
const writer = writable.getWriter();
assert.match(
inspect(writer),
/WritableStreamDefaultWriter/);
assert.match(
inspect(writer, { depth: null }),
/WritableStreamDefaultWriter/);
assert.match(
inspect(writer, { depth: 0 }),
/WritableStreamDefaultWriter \[/);
assert.match(
inspect(controller),
/WritableStreamDefaultController/);
assert.match(
inspect(controller, { depth: null }),
/WritableStreamDefaultController/);
assert.match(
inspect(controller, { depth: 0 }),
/WritableStreamDefaultController \[/);
writer.abort(new Error('boom'));
assert.strictEqual(writer.desiredSize, null);
setImmediate(() => assert.strictEqual(writer.desiredSize, null));
}