@@ -7,10 +7,11 @@ const {
77 ObjectDefineProperty,
88 PromiseResolve,
99 PromiseReject,
10- PromisePrototypeFinally ,
10+ SafePromisePrototypeFinally ,
1111 ReflectConstruct,
1212 RegExpPrototypeTest,
1313 StringPrototypeToLowerCase,
14+ StringPrototypeSplit,
1415 Symbol,
1516 SymbolIterator,
1617 SymbolToStringTag,
@@ -20,7 +21,8 @@ const {
2021const {
2122 createBlob : _createBlob ,
2223 FixedSizeBlobCopyJob,
23- } = internalBinding ( 'buffer' ) ;
24+ getDataObject,
25+ } = internalBinding ( 'blob' ) ;
2426
2527const { TextDecoder } = require ( 'internal/encoding' ) ;
2628
@@ -57,26 +59,37 @@ const {
5759} = require ( 'internal/validators' ) ;
5860
5961const kHandle = Symbol ( 'kHandle' ) ;
62+ const kState = Symbol ( 'kState' ) ;
6063const kType = Symbol ( 'kType' ) ;
6164const kLength = Symbol ( 'kLength' ) ;
6265const kArrayBufferPromise = Symbol ( 'kArrayBufferPromise' ) ;
6366
67+ const kMaxChunkSize = 65536 ;
68+
6469const disallowedTypeCharacters = / [ ^ \u{0020} - \u{007E} ] / u;
6570
6671let Buffer ;
6772let ReadableStream ;
73+ let URL ;
74+
75+
76+ // Yes, lazy loading is annoying but because of circular
77+ // references between the url, internal/blob, and buffer
78+ // modules, lazy loading here makes sure that things work.
79+
80+ function lazyURL ( id ) {
81+ URL ??= require ( 'internal/url' ) . URL ;
82+ return new URL ( id ) ;
83+ }
6884
6985function lazyBuffer ( ) {
70- if ( Buffer === undefined )
71- Buffer = require ( 'buffer' ) . Buffer ;
86+ Buffer ??= require ( 'buffer' ) . Buffer ;
7287 return Buffer ;
7388}
7489
7590function lazyReadableStream ( options ) {
76- if ( ReadableStream === undefined ) {
77- ReadableStream =
78- require ( 'internal/webstreams/readablestream' ) . ReadableStream ;
79- }
91+ ReadableStream ??=
92+ require ( 'internal/webstreams/readablestream' ) . ReadableStream ;
8093 return new ReadableStream ( options ) ;
8194}
8295
@@ -232,9 +245,9 @@ class Blob {
232245 return PromiseReject ( new ERR_INVALID_THIS ( 'Blob' ) ) ;
233246
234247 // If there's already a promise in flight for the content,
235- // reuse it, but only once . After the cached promise resolves
236- // it will be cleared, allowing it to be garbage collected
237- // as soon as possible.
248+ // reuse it, but only while it's in flight . After the cached
249+ // promise resolves it will be cleared, allowing it to be
250+ // garbage collected as soon as possible.
238251 if ( this [ kArrayBufferPromise ] )
239252 return this [ kArrayBufferPromise ] ;
240253
@@ -260,15 +273,14 @@ class Blob {
260273 resolve ( ab ) ;
261274 } ;
262275 this [ kArrayBufferPromise ] =
263- PromisePrototypeFinally (
276+ SafePromisePrototypeFinally (
264277 promise ,
265278 ( ) => this [ kArrayBufferPromise ] = undefined ) ;
266279
267280 return this [ kArrayBufferPromise ] ;
268281 }
269282
270283 /**
271- *
272284 * @returns {Promise<string> }
273285 */
274286 async text ( ) {
@@ -288,10 +300,20 @@ class Blob {
288300
289301 const self = this ;
290302 return new lazyReadableStream ( {
291- async start ( controller ) {
292- const ab = await self . arrayBuffer ( ) ;
293- controller . enqueue ( new Uint8Array ( ab ) ) ;
294- controller . close ( ) ;
303+ async start ( ) {
304+ this [ kState ] = await self . arrayBuffer ( ) ;
305+ } ,
306+
307+ pull ( controller ) {
308+ if ( this [ kState ] . byteLength <= kMaxChunkSize ) {
309+ controller . enqueue ( new Uint8Array ( this [ kState ] ) ) ;
310+ controller . close ( ) ;
311+ this [ kState ] = undefined ;
312+ } else {
313+ const slice = this [ kState ] . slice ( 0 , kMaxChunkSize ) ;
314+ this [ kState ] = this [ kState ] . slice ( kMaxChunkSize ) ;
315+ controller . enqueue ( new Uint8Array ( slice ) ) ;
316+ }
295317 }
296318 } ) ;
297319 }
@@ -315,9 +337,47 @@ ObjectDefineProperty(Blob.prototype, SymbolToStringTag, {
315337 value : 'Blob' ,
316338} ) ;
317339
340+ function resolveObjectURL ( url ) {
341+ url = `${ url } ` ;
342+ try {
343+ const parsed = new lazyURL ( url ) ;
344+
345+ const split = StringPrototypeSplit ( parsed . pathname , ':' ) ;
346+
347+ if ( split . length !== 2 )
348+ return ;
349+
350+ const {
351+ 0 : base ,
352+ 1 : id ,
353+ } = split ;
354+
355+ if ( base !== 'nodedata' )
356+ return ;
357+
358+ const ret = getDataObject ( id ) ;
359+
360+ if ( ret === undefined )
361+ return ;
362+
363+ const {
364+ 0 : handle ,
365+ 1 : length ,
366+ 2 : type ,
367+ } = ret ;
368+
369+ if ( handle !== undefined )
370+ return createBlob ( handle , length , type ) ;
371+ } catch {
372+ // If there's an error, it's ignored and nothing is returned
373+ }
374+ }
375+
318376module . exports = {
319377 Blob,
320378 ClonedBlob,
321379 createBlob,
322380 isBlob,
381+ kHandle,
382+ resolveObjectURL,
323383} ;
0 commit comments