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

Commit ccaf7fe

Browse files
iskertargos
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 0c3ae25 commit ccaf7fe

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
@@ -142,6 +142,10 @@ function lazyFsStreams() {
142142

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

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

297-
let readable;
298305

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

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

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

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

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

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

331-
cancel() {
332-
ondone();
333-
},
334-
});
335-
}
336331

337332
const {
338333
readableStreamCancel,

test/parallel/test-filehandle-readablestream.js

Lines changed: 10 additions & 53 deletions

0 commit comments

Comments
 (0)