| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent cd9b0bf commit 5bc31ea
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -459,14 +459,20 @@ multiple worker threads. | |||
| 459 | 459 | ### `new buffer.Blob([sources[, options]])` | |
| 460 | 460 | <!-- YAML | |
| 461 | 461 | added: v15.7.0 | |
| 462 | + changes: | ||
| 463 | + - version: REPLACEME | ||
| 464 | + pr-url: https://github.com/nodejs/node/pull/39708 | ||
| 465 | + description: Added the standard `endings` option to replace line-endings, | ||
| 466 | + and removed the non-standard `encoding` option. | ||
| 462 | 467 | --> | |
| 463 | 468 | ||
| 464 | 469 | * `sources` {string[]|ArrayBuffer[]|TypedArray[]|DataView[]|Blob[]} An array | |
| 465 | 470 | of string, {ArrayBuffer}, {TypedArray}, {DataView}, or {Blob} objects, or | |
| 466 | 471 | any mix of such objects, that will be stored within the `Blob`. | |
| 467 | 472 | * `options` {Object} | |
| 468 | - * `encoding` {string} The character encoding to use for string sources. | ||
| 469 | - **Default:** `'utf8'`. | ||
| 473 | + * `endings` {string} One of either `'transparent'` or `'native'`. When set | ||
| 474 | + to `'native'`, line endings in string source parts will be converted to | ||
| 475 | + the platform native line-ending as specified by `require('os').EOL`. | ||
| 470 | 476 | * `type` {string} The Blob content-type. The intent is for `type` to convey | |
| 471 | 477 | the MIME media type of the data, however no validation of the type format | |
| 472 | 478 | is performed. | |
@@ -476,7 +482,9 @@ Creates a new `Blob` object containing a concatenation of the given sources. | |||
| 476 | 482 | {ArrayBuffer}, {TypedArray}, {DataView}, and {Buffer} sources are copied into | |
| 477 | 483 | the 'Blob' and can therefore be safely modified after the 'Blob' is created. | |
| 478 | 484 | ||
| 479 | - String sources are also copied into the `Blob`. | ||
| 485 | + String sources are encoded as UTF-8 byte sequences and copied into the Blob. | ||
| 486 | + Unmatched surrogate pairs within each string part will be replaced by Unicode | ||
| 487 | + U+FFFD replacement characters. | ||
| 480 | 488 | ||
| 481 | 489 | ### `blob.arrayBuffer()` | |
| 482 | 490 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,6 +9,7 @@ const { | |||
| 9 | 9 | PromiseReject, | |
| 10 | 10 | SafePromisePrototypeFinally, | |
| 11 | 11 | ReflectConstruct, | |
| 12 | + RegExpPrototypeSymbolReplace, | ||
| 12 | 13 | RegExpPrototypeTest, | |
| 13 | 14 | StringPrototypeToLowerCase, | |
| 14 | 15 | StringPrototypeSplit, | |
@@ -24,7 +25,10 @@ const { | |||
| 24 | 25 | getDataObject, | |
| 25 | 26 | } = internalBinding('blob'); | |
| 26 | 27 | ||
| 27 | - const { TextDecoder } = require('internal/encoding'); | ||
| 28 | + const { | ||
| 29 | + TextDecoder, | ||
| 30 | + TextEncoder, | ||
| 31 | + } = require('internal/encoding'); | ||
| 28 | 32 | ||
| 29 | 33 | const { | |
| 30 | 34 | makeTransferable, | |
@@ -48,6 +52,7 @@ const { | |||
| 48 | 52 | AbortError, | |
| 49 | 53 | codes: { | |
| 50 | 54 | ERR_INVALID_ARG_TYPE, | |
| 55 | + ERR_INVALID_ARG_VALUE, | ||
| 51 | 56 | ERR_INVALID_THIS, | |
| 52 | 57 | ERR_BUFFER_TOO_LARGE, | |
| 53 | 58 | } | |
@@ -68,10 +73,11 @@ const kMaxChunkSize = 65536; | |||
| 68 | 73 | ||
| 69 | 74 | const disallowedTypeCharacters = /[^\u{0020}-\u{007E}]/u; | |
| 70 | 75 | ||
| 71 | - let Buffer; | ||
| 72 | 76 | let ReadableStream; | |
| 73 | 77 | let URL; | |
| 78 | + let EOL; | ||
| 74 | 79 | ||
| 80 | + const enc = new TextEncoder(); | ||
| 75 | 81 | ||
| 76 | 82 | // Yes, lazy loading is annoying but because of circular | |
| 77 | 83 | // references between the url, internal/blob, and buffer | |
@@ -82,29 +88,35 @@ function lazyURL(id) { | |||
| 82 | 88 | return new URL(id); | |
| 83 | 89 | } | |
| 84 | 90 | ||
| 85 | - function lazyBuffer() { | ||
| 86 | - Buffer ??= require('buffer').Buffer; | ||
| 87 | - return Buffer; | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | 91 | function lazyReadableStream(options) { | |
| 91 | 92 | ReadableStream ??= | |
| 92 | 93 | require('internal/webstreams/readablestream').ReadableStream; | |
| 93 | 94 | return new ReadableStream(options); | |
| 94 | 95 | } | |
| 95 | 96 | ||
| 97 | + // TODO(@jasnell): This is annoying but this has to be lazy because | ||
| 98 | + // requiring the 'os' module too early causes building Node.js to | ||
| 99 | + // fail with an unknown reference failure. | ||
| 100 | + function lazyEOL() { | ||
| 101 | + EOL ??= require('os').EOL; | ||
| 102 | + return EOL; | ||
| 103 | + } | ||
| 104 | + | ||
| 96 | 105 | function isBlob(object) { | |
| 97 | 106 | return object?.[kHandle] !== undefined; | |
| 98 | 107 | } | |
| 99 | 108 | ||
| 100 | - function getSource(source, encoding) { | ||
| 109 | + function getSource(source, endings) { | ||
| 101 | 110 | if (isBlob(source)) | |
| 102 | 111 | return [source.size, source[kHandle]]; | |
| 103 | 112 | ||
| 104 | 113 | if (isAnyArrayBuffer(source)) { | |
| 105 | 114 | source = new Uint8Array(source); | |
| 106 | 115 | } else if (!isArrayBufferView(source)) { | |
| 107 | - source = lazyBuffer().from(`${source}`, encoding); | ||
| 116 | + source = `${source}`; | ||
| 117 | + if (endings === 'native') | ||
| 118 | + source = RegExpPrototypeSymbolReplace(/\n|\r\n/g, source, lazyEOL()); | ||
| 119 | + source = enc.encode(source); | ||
| 108 | 120 | } | |
| 109 | 121 | ||
| 110 | 122 | // We copy into a new Uint8Array because the underlying | |
@@ -116,6 +128,16 @@ function getSource(source, encoding) { | |||
| 116 | 128 | } | |
| 117 | 129 | ||
| 118 | 130 | class Blob { | |
| 131 | + /** | ||
| 132 | + * @typedef {string|ArrayBuffer|ArrayBufferView|Blob} SourcePart | ||
| 133 | + * | ||
| 134 | + * @param {SourcePart[]} [sources] | ||
| 135 | + * @param {{ | ||
| 136 | + * endings? : string, | ||
| 137 | + * type? : string, | ||
| 138 | + * }} [options] | ||
| 139 | + * @returns | ||
| 140 | + */ | ||
| 119 | 141 | constructor(sources = [], options = {}) { | |
| 120 | 142 | emitExperimentalWarning('buffer.Blob'); | |
| 121 | 143 | if (sources === null || | |
@@ -124,12 +146,18 @@ class Blob { | |||
| 124 | 146 | throw new ERR_INVALID_ARG_TYPE('sources', 'Iterable', sources); | |
| 125 | 147 | } | |
| 126 | 148 | validateObject(options, 'options'); | |
| 127 | - const { encoding = 'utf8' } = options; | ||
| 128 | - let { type = '' } = options; | ||
| 149 | + let { | ||
| 150 | + type = '', | ||
| 151 | + endings = 'transparent', | ||
| 152 | + } = options; | ||
| 153 | + | ||
| 154 | + endings = `${endings}`; | ||
| 155 | + if (endings !== 'transparent' && endings !== 'native') | ||
| 156 | + throw new ERR_INVALID_ARG_VALUE('options.endings', endings); | ||
| 129 | 157 | ||
| 130 | 158 | let length = 0; | |
| 131 | 159 | const sources_ = ArrayFrom(sources, (source) => { | |
| 132 | - const { 0: len, 1: src } = getSource(source, encoding); | ||
| 160 | + const { 0: len, 1: src } = getSource(source, endings); | ||
| 133 | 161 | length += len; | |
| 134 | 162 | return src; | |
| 135 | 163 | }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,9 +1,11 @@ | |||
| 1 | + // Flags: --no-warnings | ||
| 1 | 2 | 'use strict'; | |
| 2 | 3 | ||
| 3 | 4 | const common = require('../common'); | |
| 4 | 5 | const assert = require('assert'); | |
| 5 | 6 | const { Blob } = require('buffer'); | |
| 6 | 7 | const { inspect } = require('util'); | |
| 8 | + const { EOL } = require('os'); | ||
| 7 | 9 | ||
| 8 | 10 | { | |
| 9 | 11 | const b = new Blob(); | |
@@ -45,15 +47,6 @@ assert.throws(() => new Blob({}), { | |||
| 45 | 47 | assert.strictEqual(new Blob([], { type: {} }).type, '[object object]'); | |
| 46 | 48 | } | |
| 47 | 49 | ||
| 48 | - { | ||
| 49 | - const b = new Blob(['616263'], { encoding: 'hex', type: 'foo' }); | ||
| 50 | - assert.strictEqual(b.size, 3); | ||
| 51 | - assert.strictEqual(b.type, 'foo'); | ||
| 52 | - b.text().then(common.mustCall((text) => { | ||
| 53 | - assert.strictEqual(text, 'abc'); | ||
| 54 | - })); | ||
| 55 | - } | ||
| 56 | - | ||
| 57 | 50 | { | |
| 58 | 51 | const b = new Blob([Buffer.from('abc')]); | |
| 59 | 52 | assert.strictEqual(b.size, 3); | |
@@ -216,3 +209,14 @@ assert.throws(() => new Blob({}), { | |||
| 216 | 209 | res = await reader.read(); | |
| 217 | 210 | assert(res.done); | |
| 218 | 211 | })().then(common.mustCall()); | |
| 212 | + | ||
| 213 | + { | ||
| 214 | + const b = new Blob(['hello\n'], { endings: 'native' }); | ||
| 215 | + assert.strictEqual(b.size, EOL.length + 5); | ||
| 216 | + | ||
| 217 | + [1, {}, 'foo'].forEach((endings) => { | ||
| 218 | + assert.throws(() => new Blob([], { endings }), { | ||
| 219 | + code: 'ERR_INVALID_ARG_VALUE', | ||
| 220 | + }); | ||
| 221 | + }); | ||
| 222 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments