@@ -24,7 +24,10 @@ const {
2424 getDataObject,
2525} = internalBinding ( 'blob' ) ;
2626
27- const { TextDecoder } = require ( 'internal/encoding' ) ;
27+ const {
28+ TextDecoder,
29+ TextEncoder,
30+ } = require ( 'internal/encoding' ) ;
2831
2932const {
3033 makeTransferable,
@@ -48,6 +51,7 @@ const {
4851 AbortError,
4952 codes : {
5053 ERR_INVALID_ARG_TYPE ,
54+ ERR_INVALID_ARG_VALUE ,
5155 ERR_INVALID_THIS ,
5256 ERR_BUFFER_TOO_LARGE ,
5357 }
@@ -65,10 +69,11 @@ const kArrayBufferPromise = Symbol('kArrayBufferPromise');
6569
6670const disallowedTypeCharacters = / [ ^ \u{0020} - \u{007E} ] / u;
6771
68- let Buffer ;
6972let ReadableStream ;
7073let URL ;
74+ let EOL ;
7175
76+ const enc = new TextEncoder ( ) ;
7277
7378// Yes, lazy loading is annoying but because of circular
7479// references between the url, internal/blob, and buffer
@@ -79,29 +84,35 @@ function lazyURL(id) {
7984 return new URL ( id ) ;
8085}
8186
82- function lazyBuffer ( ) {
83- Buffer ??= require ( 'buffer' ) . Buffer ;
84- return Buffer ;
85- }
86-
8787function lazyReadableStream ( options ) {
8888 ReadableStream ??=
8989 require ( 'internal/webstreams/readablestream' ) . ReadableStream ;
9090 return new ReadableStream ( options ) ;
9191}
9292
93+ // TODO(@jasnell): This is annoying but this has to be lazy because
94+ // requiring the 'os' module too early causes building Node.js to
95+ // fail with an unknown reference failure.
96+ function lazyEOL ( ) {
97+ EOL ??= require ( 'os' ) . EOL ;
98+ return EOL ;
99+ }
100+
93101function isBlob ( object ) {
94102 return object ?. [ kHandle ] !== undefined ;
95103}
96104
97- function getSource ( source , encoding ) {
105+ function getSource ( source , endings ) {
98106 if ( isBlob ( source ) )
99107 return [ source . size , source [ kHandle ] ] ;
100108
101109 if ( isAnyArrayBuffer ( source ) ) {
102110 source = new Uint8Array ( source ) ;
103111 } else if ( ! isArrayBufferView ( source ) ) {
104- source = lazyBuffer ( ) . from ( `${ source } ` , encoding ) ;
112+ source = `${ source } ` ;
113+ if ( endings === 'native' )
114+ source = source . replaceAll ( / ( \n | \r \n ) / g, lazyEOL ( ) ) ;
115+ source = enc . encode ( source ) ;
105116 }
106117
107118 // We copy into a new Uint8Array because the underlying
@@ -113,6 +124,16 @@ function getSource(source, encoding) {
113124}
114125
115126class Blob {
127+ /**
128+ * @typedef {string|ArrayBuffer|ArrayBufferView|Blob } SourcePart
129+ *
130+ * @param {SourcePart[] } [sources]
131+ * @param {{
132+ * endings? : string,
133+ * type? : string,
134+ * }} options
135+ * @returns
136+ */
116137 constructor ( sources = [ ] , options = { } ) {
117138 emitExperimentalWarning ( 'buffer.Blob' ) ;
118139 if ( sources === null ||
@@ -121,12 +142,18 @@ class Blob {
121142 throw new ERR_INVALID_ARG_TYPE ( 'sources' , 'Iterable' , sources ) ;
122143 }
123144 validateObject ( options , 'options' ) ;
124- const { encoding = 'utf8' } = options ;
125- let { type = '' } = options ;
145+ let {
146+ type = '' ,
147+ endings = 'transparent' ,
148+ } = options ;
149+
150+ endings = `${ endings } ` ;
151+ if ( endings !== 'transparent' || endings !== 'native' )
152+ throw new ERR_INVALID_ARG_VALUE ( 'options.endings' , endings ) ;
126153
127154 let length = 0 ;
128155 const sources_ = ArrayFrom ( sources , ( source ) => {
129- const { 0 : len , 1 : src } = getSource ( source , encoding ) ;
156+ const { 0 : len , 1 : src } = getSource ( source , endings ) ;
130157 length += len ;
131158 return src ;
132159 } ) ;
0 commit comments