fs: make `FileHandle.readableWebStream` always create byte streams · nodejs/node@14b2d49 · GitHub
Skip to content

Commit 14b2d49

Browse files
iskerRafaelGSS
authored andcommitted
fs: make FileHandle.readableWebStream always create byte streams
The original implementation of the experimental `FileHandle.readableWebStream` API created non-`type: 'bytes'` streams, which prevented callers from creating `mode: 'byob'` readers from the returned stream, which means they could not achieve the associated "zero-copy" performance characteristics. Then, #46933 added a parameter allowing callers to pass the `type` parameter down to the ReadableStream constructor, exposing the same semantics to callers of `FileHandle.readableWebStream`. But there is no point to giving callers this choice: FileHandle-derived streams are by their very nature byte streams. We should not require callers to explicitly opt in to having byte stream semantics. Moreover, I do not see a situation in which callers would ever want to have a non-bytes stream: bytes-streams only do anything differently than normal ones if `mode: 'byob'` is passed to `getReader`. So, remove the `options` parameter and always create a ReadableStream with `type: 'bytes'`. Fixes #54041. PR-URL: #55461 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 7eb3b44 commit 14b2d49

3 files changed

Lines changed: 47 additions & 95 deletions

File tree

doc/api/fs.md

Lines changed: 6 additions & 6 deletions

lib/internal/fs/promises.js

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ function lazyFsStreams() {
141141

142142
const lazyRimRaf = getLazy(() => require('internal/fs/rimraf').rimrafPromises);
143143

144+
const lazyReadableStream = getLazy(() =>
145+
require('internal/webstreams/readablestream').ReadableStream,
146+
);
147+
144148
// By the time the C++ land creates an error for a promise rejection (likely from a
145149
// libuv callback), there is already no JS frames on the stack. So we need to
146150
// wait until V8 resumes execution back to JS land before we have enough information
@@ -275,12 +279,9 @@ class FileHandle extends EventEmitter {
275279
/**
276280
* @typedef {import('../webstreams/readablestream').ReadableStream
277281
* } ReadableStream
278-
* @param {{
279-
* type?: string;
280-
* }} [options]
281282
* @returns {ReadableStream}
282283
*/
283-
readableWebStream(options = kEmptyObject) {
284+
readableWebStream(options = { __proto__: null, type: 'bytes' }) {
284285
if (this[kFd] === -1)
285286
throw new ERR_INVALID_STATE('The FileHandle is closed');
286287
if (this[kClosePromise])
@@ -292,46 +293,40 @@ class FileHandle extends EventEmitter {
292293
if (options.type !== undefined) {
293294
validateString(options.type, 'options.type');
294295
}
296+
if (options.type !== 'bytes') {
297+
process.emitWarning(
298+
'A non-"bytes" options.type has no effect. A byte-oriented steam is ' +
299+
'always created.',
300+
'ExperimentalWarning',
301+
);
302+
}
295303

296-
let readable;
297304

298-
if (options.type !== 'bytes') {
299-
const {
300-
newReadableStreamFromStreamBase,
301-
} = require('internal/webstreams/adapters');
302-
readable = newReadableStreamFromStreamBase(
303-
this[kHandle],
304-
undefined,
305-
{ ondone: () => this[kUnref]() });
306-
} else {
307-
const {
308-
ReadableStream,
309-
} = require('internal/webstreams/readablestream');
305+
const readFn = FunctionPrototypeBind(this.read, this);
306+
const ondone = FunctionPrototypeBind(this[kUnref], this);
310307

311-
const readFn = FunctionPrototypeBind(this.read, this);
312-
const ondone = FunctionPrototypeBind(this[kUnref], this);
308+
const ReadableStream = lazyReadableStream();
309+
const readable = new ReadableStream({
310+
type: 'bytes',
311+
autoAllocateChunkSize: 16384,
313312

314-
readable = new ReadableStream({
315-
type: 'bytes',
316-
autoAllocateChunkSize: 16384,
313+
async pull(controller) {
314+
const view = controller.byobRequest.view;
315+
const { bytesRead } = await readFn(view, view.byteOffset, view.byteLength);
317316

318-
async pull(controller) {
319-
const view = controller.byobRequest.view;
320-
const { bytesRead } = await readFn(view, view.byteOffset, view.byteLength);
317+
if (bytesRead === 0) {
318+
ondone();
319+
controller.close();
320+
}
321321

322-
if (bytesRead === 0) {
323-
ondone();
324-
controller.close();
325-
}
322+
controller.byobRequest.respond(bytesRead);
323+
},
326324

327-
controller.byobRequest.respond(bytesRead);
328-
},
325+
cancel() {
326+
ondone();
327+
},
328+
});
329329

330-
cancel() {
331-
ondone();
332-
},
333-
});
334-
}
335330

336331
const {
337332
readableStreamCancel,

test/parallel/test-filehandle-readablestream.js

Lines changed: 10 additions & 53 deletions

0 commit comments

Comments
 (0)