| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -202,15 +202,6 @@ When operating on file handles, the mode cannot be changed from what it was set | |||
| 202 | 202 | to with [`fsPromises.open()`][]. Therefore, this is equivalent to | |
| 203 | 203 | [`filehandle.writeFile()`][]. | |
| 204 | 204 | ||
| 205 | - #### `filehandle.blob()` | ||
| 206 | - <!-- YAML | ||
| 207 | - added: REPLACEME | ||
| 208 | - --> | ||
| 209 | - | ||
| 210 | - > Stability: 1 - Experimental | ||
| 211 | - | ||
| 212 | - Returns a {Blob} whose data is backed by this file. | ||
| 213 | - | ||
| 214 | 205 | #### `filehandle.chmod(mode)` | |
| 215 | 206 | ||
| 216 | 207 | <!-- YAML | |
@@ -3333,6 +3324,45 @@ a colon, Node.js will open a file system stream, as described by | |||
| 3333 | 3324 | Functions based on `fs.open()` exhibit this behavior as well: | |
| 3334 | 3325 | `fs.writeFile()`, `fs.readFile()`, etc. | |
| 3335 | 3326 | ||
| 3327 | + ### `fs.openAsBlob(path[, options])` | ||
| 3328 | + | ||
| 3329 | + <!-- YAML | ||
| 3330 | + added: REPLACEME | ||
| 3331 | + --> | ||
| 3332 | + | ||
| 3333 | + > Stability: 1 - Experimental | ||
| 3334 | + | ||
| 3335 | + * `path` {string|Buffer|URL} | ||
| 3336 | + * `options` {Object} | ||
| 3337 | + * `type` {string} An optional mime type for the blob. | ||
| 3338 | + * Return: {Promise} containing {Blob} | ||
| 3339 | + | ||
| 3340 | + Returns a {Blob} whose data is backed by the given file. | ||
| 3341 | + | ||
| 3342 | + The file must not be modified after the {Blob} is created. Any modifications | ||
| 3343 | + will cause reading the {Blob} data to fail with a `DOMException`. | ||
| 3344 | + error. Synchronous stat operations on the file when the `Blob` is created, and | ||
| 3345 | + before each read in order to detect whether the file data has been modified | ||
| 3346 | + on disk. | ||
| 3347 | + | ||
| 3348 | + ```mjs | ||
| 3349 | + import { openAsBlob } from 'node:fs'; | ||
| 3350 | + | ||
| 3351 | + const blob = await openAsBlob('the.file.txt'); | ||
| 3352 | + const ab = await blob.arrayBuffer(); | ||
| 3353 | + blob.stream(); | ||
| 3354 | + ``` | ||
| 3355 | + | ||
| 3356 | + ```cjs | ||
| 3357 | + const { openAsBlob } = require('node:fs'); | ||
| 3358 | + | ||
| 3359 | + (async () => { | ||
| 3360 | + const blob = await openAsBlob('the.file.txt'); | ||
| 3361 | + const ab = await blob.arrayBuffer(); | ||
| 3362 | + blob.stream(); | ||
| 3363 | + })(); | ||
| 3364 | + ``` | ||
| 3365 | + | ||
| 3336 | 3366 | ### `fs.opendir(path[, options], callback)` | |
| 3337 | 3367 | ||
| 3338 | 3368 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -32,6 +32,7 @@ const { | |||
| 32 | 32 | ObjectDefineProperties, | |
| 33 | 33 | ObjectDefineProperty, | |
| 34 | 34 | Promise, | |
| 35 | + PromiseResolve, | ||
| 35 | 36 | ReflectApply, | |
| 36 | 37 | SafeMap, | |
| 37 | 38 | SafeSet, | |
@@ -62,6 +63,9 @@ const { isArrayBufferView } = require('internal/util/types'); | |||
| 62 | 63 | // it's re-initialized after deserialization. | |
| 63 | 64 | ||
| 64 | 65 | const binding = internalBinding('fs'); | |
| 66 | + | ||
| 67 | + const { createBlobFromFilePath } = require('internal/blob'); | ||
| 68 | + | ||
| 65 | 69 | const { Buffer } = require('buffer'); | |
| 66 | 70 | const { | |
| 67 | 71 | aggregateTwoErrors, | |
@@ -586,6 +590,20 @@ function openSync(path, flags, mode) { | |||
| 586 | 590 | return result; | |
| 587 | 591 | } | |
| 588 | 592 | ||
| 593 | + /** | ||
| 594 | + * @param {string | Buffer | URL } path | ||
| 595 | + * @returns {Promise<Blob>} | ||
| 596 | + */ | ||
| 597 | + function openAsBlob(path, options = kEmptyObject) { | ||
| 598 | + validateObject(options, 'options'); | ||
| 599 | + const type = options.type || ''; | ||
| 600 | + validateString(type, 'options.type'); | ||
| 601 | + // The underlying implementation here returns the Blob synchronously for now. | ||
| 602 | + // To give ourselves flexibility to maybe return the Blob asynchronously, | ||
| 603 | + // this API returns a Promise. | ||
| 604 | + return PromiseResolve(createBlobFromFilePath(getValidatedPath(path), { type })); | ||
| 605 | + } | ||
| 606 | + | ||
| 589 | 607 | /** | |
| 590 | 608 | * Reads file from the specified `fd` (file descriptor). | |
| 591 | 609 | * @param {number} fd | |
@@ -3022,6 +3040,7 @@ module.exports = fs = { | |||
| 3022 | 3040 | mkdtempSync, | |
| 3023 | 3041 | open, | |
| 3024 | 3042 | openSync, | |
| 3043 | + openAsBlob, | ||
| 3025 | 3044 | readdir, | |
| 3026 | 3045 | readdirSync, | |
| 3027 | 3046 | read, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,7 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | + ArrayBuffer, | ||
| 4 | 5 | ArrayFrom, | |
| 5 | 6 | MathMax, | |
| 6 | 7 | MathMin, | |
@@ -21,7 +22,7 @@ const { | |||
| 21 | 22 | ||
| 22 | 23 | const { | |
| 23 | 24 | createBlob: _createBlob, | |
| 24 | - createBlobFromFileHandle: _createBlobFromFileHandle, | ||
| 25 | + createBlobFromFilePath: _createBlobFromFilePath, | ||
| 25 | 26 | concat, | |
| 26 | 27 | getDataObject, | |
| 27 | 28 | } = internalBinding('blob'); | |
@@ -48,6 +49,7 @@ const { | |||
| 48 | 49 | customInspectSymbol: kInspect, | |
| 49 | 50 | kEmptyObject, | |
| 50 | 51 | kEnumerableProperty, | |
| 52 | + lazyDOMException, | ||
| 51 | 53 | } = require('internal/util'); | |
| 52 | 54 | const { inspect } = require('internal/util/inspect'); | |
| 53 | 55 | ||
@@ -58,14 +60,17 @@ const { | |||
| 58 | 60 | ERR_INVALID_THIS, | |
| 59 | 61 | ERR_BUFFER_TOO_LARGE, | |
| 60 | 62 | }, | |
| 61 | - errnoException, | ||
| 62 | 63 | } = require('internal/errors'); | |
| 63 | 64 | ||
| 64 | 65 | const { | |
| 65 | 66 | isUint32, | |
| 66 | 67 | validateDictionary, | |
| 67 | 68 | } = require('internal/validators'); | |
| 68 | 69 | ||
| 70 | + const { | ||
| 71 | + CountQueuingStrategy, | ||
| 72 | + } = require('internal/webstreams/queuingstrategies'); | ||
| 73 | + | ||
| 69 | 74 | const kHandle = Symbol('kHandle'); | |
| 70 | 75 | const kType = Symbol('kType'); | |
| 71 | 76 | const kLength = Symbol('kLength'); | |
@@ -265,16 +270,23 @@ class Blob { | |||
| 265 | 270 | return PromiseResolve(new ArrayBuffer(0)); | |
| 266 | 271 | } | |
| 267 | 272 | ||
| 268 | - const { promise, resolve } = createDeferredPromise(); | ||
| 273 | + const { promise, resolve, reject } = createDeferredPromise(); | ||
| 269 | 274 | const reader = this[kHandle].getReader(); | |
| 270 | 275 | const buffers = []; | |
| 271 | 276 | const readNext = () => { | |
| 272 | 277 | reader.pull((status, buffer) => { | |
| 273 | - if (status === -1) { | ||
| 278 | + if (status === 0) { | ||
| 274 | 279 | // EOS, concat & resolve | |
| 275 | 280 | // buffer should be undefined here | |
| 276 | 281 | resolve(concat(buffers)); | |
| 277 | 282 | return; | |
| 283 | + } else if (status < 0) { | ||
| 284 | + // The read could fail for many different reasons when reading | ||
| 285 | + // from a non-memory resident blob part (e.g. file-backed blob). | ||
| 286 | + // The error details the system error code. | ||
| 287 | + const error = lazyDOMException('The blob could not be read', 'NotReadableError'); | ||
| 288 | + reject(error); | ||
| 289 | + return; | ||
| 278 | 290 | } | |
| 279 | 291 | if (buffer !== undefined) | |
| 280 | 292 | buffers.push(buffer); | |
@@ -319,7 +331,7 @@ class Blob { | |||
| 319 | 331 | }, | |
| 320 | 332 | pull(c) { | |
| 321 | 333 | const { promise, resolve, reject } = createDeferredPromise(); | |
| 322 | - this.pendingPulls.push({resolve, reject}); | ||
| 334 | + this.pendingPulls.push({ resolve, reject }); | ||
| 323 | 335 | reader.pull((status, buffer) => { | |
| 324 | 336 | // If pendingPulls is empty here, the stream had to have | |
| 325 | 337 | // been canceled, and we don't really care about the result. | |
@@ -328,18 +340,24 @@ class Blob { | |||
| 328 | 340 | return; | |
| 329 | 341 | } | |
| 330 | 342 | const pending = this.pendingPulls.shift(); | |
| 331 | - if (status === -1 || (status === 0 && buffer === undefined)) { | ||
| 343 | + if (status === 0) { | ||
| 332 | 344 | // EOS | |
| 333 | 345 | c.close(); | |
| 334 | 346 | pending.resolve(); | |
| 335 | 347 | return; | |
| 336 | 348 | } else if (status < 0) { | |
| 337 | - const error = errnoException(status, 'read'); | ||
| 349 | + // The read could fail for many different reasons when reading | ||
| 350 | + // from a non-memory resident blob part (e.g. file-backed blob). | ||
| 351 | + // The error details the system error code. | ||
| 352 | + const error = lazyDOMException('The blob could not be read', 'NotReadableError'); | ||
| 353 | + | ||
| 338 | 354 | c.error(error); | |
| 339 | 355 | pending.reject(error); | |
| 340 | 356 | return; | |
| 341 | 357 | } | |
| 342 | - c.enqueue(new Uint8Array(buffer)); | ||
| 358 | + if (buffer !== undefined) { | ||
| 359 | + c.enqueue(new Uint8Array(buffer)); | ||
| 360 | + } | ||
| 343 | 361 | pending.resolve(); | |
| 344 | 362 | }); | |
| 345 | 363 | return promise; | |
@@ -422,16 +440,22 @@ function resolveObjectURL(url) { | |||
| 422 | 440 | } | |
| 423 | 441 | } | |
| 424 | 442 | ||
| 425 | - function createBlobFromFileHandle(handle) { | ||
| 426 | - const [blob, length] = _createBlobFromFileHandle(handle); | ||
| 427 | - return createBlob(blob, length); | ||
| 443 | + // TODO(@jasnell): Now that the File class exists, we might consider having | ||
| 444 | + // this return a `File` instead of a `Blob`. | ||
| 445 | + function createBlobFromFilePath(path, options) { | ||
| 446 | + const maybeBlob = _createBlobFromFilePath(path); | ||
| 447 | + if (maybeBlob === undefined) { | ||
| 448 | + return lazyDOMException('The blob could not be read', 'NotReadableError'); | ||
| 449 | + } | ||
| 450 | + const { 0: blob, 1: length } = maybeBlob; | ||
| 451 | + return createBlob(blob, length, options?.type); | ||
| 428 | 452 | } | |
| 429 | 453 | ||
| 430 | 454 | module.exports = { | |
| 431 | 455 | Blob, | |
| 432 | 456 | ClonedBlob, | |
| 433 | 457 | createBlob, | |
| 434 | - createBlobFromFileHandle, | ||
| 458 | + createBlobFromFilePath, | ||
| 435 | 459 | isBlob, | |
| 436 | 460 | kHandle, | |
| 437 | 461 | resolveObjectURL, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,8 +25,6 @@ const { | |||
| 25 | 25 | S_IFREG | |
| 26 | 26 | } = constants; | |
| 27 | 27 | ||
| 28 | - const { createBlobFromFileHandle } = require('internal/blob'); | ||
| 29 | - | ||
| 30 | 28 | const binding = internalBinding('fs'); | |
| 31 | 29 | const { Buffer } = require('buffer'); | |
| 32 | 30 | ||
@@ -312,14 +310,6 @@ class FileHandle extends EventEmitterMixin(JSTransferable) { | |||
| 312 | 310 | return new WriteStream(undefined, { ...options, fd: this }); | |
| 313 | 311 | } | |
| 314 | 312 | ||
| 315 | - /** | ||
| 316 | - * @typedef {import('../blob').Blob} Blob | ||
| 317 | - * @returns {Blob} | ||
| 318 | - */ | ||
| 319 | - blob() { | ||
| 320 | - return createBlobFromFileHandle(this[kHandle]); | ||
| 321 | - } | ||
| 322 | - | ||
| 323 | 313 | [kTransfer]() { | |
| 324 | 314 | if (this[kClosePromise] || this[kRefs] > 1) { | |
| 325 | 315 | throw lazyDOMException('Cannot transfer FileHandle while in use', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,49 +31,49 @@ | |||
| 31 | 31 | ||
| 32 | 32 | namespace node { | |
| 33 | 33 | ||
| 34 | - #define NODE_ASYNC_NON_CRYPTO_PROVIDER_TYPES(V) \ | ||
| 35 | - V(NONE) \ | ||
| 36 | - V(DIRHANDLE) \ | ||
| 37 | - V(DNSCHANNEL) \ | ||
| 38 | - V(ELDHISTOGRAM) \ | ||
| 39 | - V(FILEHANDLE) \ | ||
| 40 | - V(FILEHANDLECLOSEREQ) \ | ||
| 41 | - V(BLOBREADER) \ | ||
| 42 | - V(FSEVENTWRAP) \ | ||
| 43 | - V(FSREQCALLBACK) \ | ||
| 44 | - V(FSREQPROMISE) \ | ||
| 45 | - V(GETADDRINFOREQWRAP) \ | ||
| 46 | - V(GETNAMEINFOREQWRAP) \ | ||
| 47 | - V(HEAPSNAPSHOT) \ | ||
| 48 | - V(HTTP2SESSION) \ | ||
| 49 | - V(HTTP2STREAM) \ | ||
| 50 | - V(HTTP2PING) \ | ||
| 51 | - V(HTTP2SETTINGS) \ | ||
| 52 | - V(HTTPINCOMINGMESSAGE) \ | ||
| 53 | - V(HTTPCLIENTREQUEST) \ | ||
| 54 | - V(JSSTREAM) \ | ||
| 55 | - V(JSUDPWRAP) \ | ||
| 56 | - V(MESSAGEPORT) \ | ||
| 57 | - V(PIPECONNECTWRAP) \ | ||
| 58 | - V(PIPESERVERWRAP) \ | ||
| 59 | - V(PIPEWRAP) \ | ||
| 60 | - V(PROCESSWRAP) \ | ||
| 61 | - V(PROMISE) \ | ||
| 62 | - V(QUERYWRAP) \ | ||
| 63 | - V(SHUTDOWNWRAP) \ | ||
| 64 | - V(SIGNALWRAP) \ | ||
| 65 | - V(STATWATCHER) \ | ||
| 66 | - V(STREAMPIPE) \ | ||
| 67 | - V(TCPCONNECTWRAP) \ | ||
| 68 | - V(TCPSERVERWRAP) \ | ||
| 69 | - V(TCPWRAP) \ | ||
| 70 | - V(TTYWRAP) \ | ||
| 71 | - V(UDPSENDWRAP) \ | ||
| 72 | - V(UDPWRAP) \ | ||
| 73 | - V(SIGINTWATCHDOG) \ | ||
| 74 | - V(WORKER) \ | ||
| 75 | - V(WORKERHEAPSNAPSHOT) \ | ||
| 76 | - V(WRITEWRAP) \ | ||
| 34 | + #define NODE_ASYNC_NON_CRYPTO_PROVIDER_TYPES(V) \ | ||
| 35 | + V(NONE) \ | ||
| 36 | + V(DIRHANDLE) \ | ||
| 37 | + V(DNSCHANNEL) \ | ||
| 38 | + V(ELDHISTOGRAM) \ | ||
| 39 | + V(FILEHANDLE) \ | ||
| 40 | + V(FILEHANDLECLOSEREQ) \ | ||
| 41 | + V(BLOBREADER) \ | ||
| 42 | + V(FSEVENTWRAP) \ | ||
| 43 | + V(FSREQCALLBACK) \ | ||
| 44 | + V(FSREQPROMISE) \ | ||
| 45 | + V(GETADDRINFOREQWRAP) \ | ||
| 46 | + V(GETNAMEINFOREQWRAP) \ | ||
| 47 | + V(HEAPSNAPSHOT) \ | ||
| 48 | + V(HTTP2SESSION) \ | ||
| 49 | + V(HTTP2STREAM) \ | ||
| 50 | + V(HTTP2PING) \ | ||
| 51 | + V(HTTP2SETTINGS) \ | ||
| 52 | + V(HTTPINCOMINGMESSAGE) \ | ||
| 53 | + V(HTTPCLIENTREQUEST) \ | ||
| 54 | + V(JSSTREAM) \ | ||
| 55 | + V(JSUDPWRAP) \ | ||
| 56 | + V(MESSAGEPORT) \ | ||
| 57 | + V(PIPECONNECTWRAP) \ | ||
| 58 | + V(PIPESERVERWRAP) \ | ||
| 59 | + V(PIPEWRAP) \ | ||
| 60 | + V(PROCESSWRAP) \ | ||
| 61 | + V(PROMISE) \ | ||
| 62 | + V(QUERYWRAP) \ | ||
| 63 | + V(SHUTDOWNWRAP) \ | ||
| 64 | + V(SIGNALWRAP) \ | ||
| 65 | + V(STATWATCHER) \ | ||
| 66 | + V(STREAMPIPE) \ | ||
| 67 | + V(TCPCONNECTWRAP) \ | ||
| 68 | + V(TCPSERVERWRAP) \ | ||
| 69 | + V(TCPWRAP) \ | ||
| 70 | + V(TTYWRAP) \ | ||
| 71 | + V(UDPSENDWRAP) \ | ||
| 72 | + V(UDPWRAP) \ | ||
| 73 | + V(SIGINTWATCHDOG) \ | ||
| 74 | + V(WORKER) \ | ||
| 75 | + V(WORKERHEAPSNAPSHOT) \ | ||
| 76 | + V(WRITEWRAP) \ | ||
| 77 | 77 | V(ZLIB) | |
| 78 | 78 | ||
| 79 | 79 | #if HAVE_OPENSSL | |
| Back | FazBrowse Home | New Git URL |
0 commit comments