@@ -291,6 +291,7 @@ Local<FunctionTemplate> Blob::Reader::GetConstructorTemplate(Environment* env) {
291
291
BaseObject::kInternalFieldCount );
292
292
tmpl->SetClassName (FIXED_ONE_BYTE_STRING (env->isolate (), " BlobReader" ));
293
293
SetProtoMethod (env->isolate (), tmpl, " pull" , Pull);
294
+ SetProtoMethod (env->isolate (), tmpl, " pullAll" , PullAll);
294
295
env->set_blob_reader_constructor_template (tmpl);
295
296
}
296
297
return tmpl;
@@ -379,6 +380,95 @@ void Blob::Reader::Pull(const FunctionCallbackInfo<Value>& args) {
379
380
std::move (next), node::bob::OPTIONS_END, nullptr , 0 ));
380
381
}
381
382
383
+ void Blob::Reader::PullAll (const FunctionCallbackInfo<Value>& args) {
384
+ Environment* env = Environment::GetCurrent (args);
385
+ Blob::Reader* reader;
386
+ ASSIGN_OR_RETURN_UNWRAP (&reader, args.Holder ());
387
+
388
+ CHECK (args[0 ]->IsFunction ());
389
+ Local<Function> fn = args[0 ].As <Function>();
390
+ CHECK (!fn->IsConstructor ());
391
+
392
+ if (reader->eos_ ) {
393
+ Local<Value> arg = Int32::New (env->isolate (), bob::STATUS_EOS);
394
+ reader->MakeCallback (fn, 1 , &arg);
395
+ return args.GetReturnValue ().Set (bob::STATUS_EOS);
396
+ }
397
+
398
+ struct View {
399
+ std::shared_ptr<BackingStore> store;
400
+ size_t length;
401
+ size_t offset = 0 ;
402
+ };
403
+
404
+ struct Impl {
405
+ BaseObjectPtr<Blob::Reader> reader;
406
+ Global<Function> callback;
407
+ Environment* env;
408
+ size_t total = 0 ;
409
+ std::vector<View> views;
410
+ int status = 1 ;
411
+ };
412
+
413
+ Impl* impl = new Impl ();
414
+ impl->reader = BaseObjectPtr<Blob::Reader>(reader);
415
+ impl->callback .Reset (env->isolate (), fn);
416
+ impl->env = env;
417
+
418
+ auto next = [impl](int status,
419
+ const DataQueue::Vec* vecs,
420
+ size_t count,
421
+ bob::Done doneCb) mutable {
422
+ Environment* env = impl->env ;
423
+ if (status == bob::STATUS_EOS) impl->reader ->eos_ = true ;
424
+
425
+ if (count > 0 ) {
426
+ // Copy the returns vectors into a single ArrayBuffer.
427
+ size_t total = 0 ;
428
+ for (size_t n = 0 ; n < count; n++) total += vecs[n].len ;
429
+
430
+ std::shared_ptr<BackingStore> store =
431
+ v8::ArrayBuffer::NewBackingStore (env->isolate (), total);
432
+ auto ptr = static_cast <uint8_t *>(store->Data ());
433
+ for (size_t n = 0 ; n < count; n++) {
434
+ std::copy (vecs[n].base , vecs[n].base + vecs[n].len , ptr);
435
+ ptr += vecs[n].len ;
436
+ }
437
+ // Since we copied the data buffers, signal that we're done with them.
438
+ std::move (doneCb)(0 );
439
+ impl->views .push_back (View{store, total});
440
+ impl->total += total;
441
+ }
442
+
443
+ impl->status = status;
444
+ return ;
445
+ };
446
+
447
+ while (impl->status > 0 ) {
448
+ impl->reader ->inner_ ->Pull (
449
+ next, node::bob::OPTIONS_END, nullptr , 0 );
450
+ };
451
+
452
+ std::shared_ptr<BackingStore> store = ArrayBuffer::NewBackingStore (
453
+ env->isolate (), impl->total );
454
+ auto ptr = static_cast <uint8_t *>(store->Data ());
455
+ for (size_t n = 0 ; n < impl->views .size (); n++) {
456
+ uint8_t * from =
457
+ static_cast <uint8_t *>(impl->views [n].store ->Data ()) + impl->views [n].offset ;
458
+ std::copy (from, from + impl->views [n].length , ptr);
459
+ ptr += impl->views [n].length ;
460
+ }
461
+
462
+ Local<Value> argv[2 ] = {
463
+ Int32::New (env->isolate (), impl->status ),
464
+ ArrayBuffer::New (env->isolate (), store),
465
+ };
466
+
467
+ impl->reader ->MakeCallback (fn, arraysize (argv), argv);
468
+ auto dropMe = std::unique_ptr<Impl>(impl);
469
+ args.GetReturnValue ().Set (impl->status );
470
+ }
471
+
382
472
BaseObjectPtr<BaseObject>
383
473
Blob::BlobTransferData::Deserialize (
384
474
Environment* env,
@@ -560,6 +650,7 @@ void Blob::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
560
650
registry->Register (Blob::GetDataObject);
561
651
registry->Register (Blob::RevokeObjectURL);
562
652
registry->Register (Blob::Reader::Pull);
653
+ registry->Register (Blob::Reader::PullAll);
563
654
registry->Register (Concat);
564
655
registry->Register (BlobFromFilePath);
565
656
}
0 commit comments