@@ -305,6 +305,7 @@ Local<FunctionTemplate> Blob::Reader::GetConstructorTemplate(Environment* env) {
305
305
BaseObject::kInternalFieldCount );
306
306
tmpl->SetClassName (FIXED_ONE_BYTE_STRING (env->isolate (), " BlobReader" ));
307
307
SetProtoMethod (env->isolate (), tmpl, " pull" , Pull);
308
+ SetProtoMethod (env->isolate (), tmpl, " pullAll" , PullAll);
308
309
env->set_blob_reader_constructor_template (tmpl);
309
310
}
310
311
return tmpl;
@@ -393,6 +394,90 @@ void Blob::Reader::Pull(const FunctionCallbackInfo<Value>& args) {
393
394
std::move (next), node::bob::OPTIONS_END, nullptr , 0 ));
394
395
}
395
396
397
+ void Blob::Reader::PullAll (const FunctionCallbackInfo<Value>& args) {
398
+ Environment* env = Environment::GetCurrent (args);
399
+ Blob::Reader* reader;
400
+ ASSIGN_OR_RETURN_UNWRAP (&reader, args.Holder ());
401
+
402
+ CHECK (args[0 ]->IsFunction ());
403
+ Local<Function> fn = args[0 ].As <Function>();
404
+ CHECK (!fn->IsConstructor ());
405
+
406
+ if (reader->eos_ ) {
407
+ Local<Value> arg = Int32::New (env->isolate (), bob::STATUS_EOS);
408
+ reader->MakeCallback (fn, 1 , &arg);
409
+ return ;
410
+ }
411
+
412
+ struct View {
413
+ std::shared_ptr<BackingStore> store;
414
+ size_t length;
415
+ size_t offset = 0 ;
416
+ };
417
+
418
+ struct Impl {
419
+ BaseObjectPtr<Blob::Reader> reader;
420
+ Global<Function> callback;
421
+ Environment* env;
422
+ std::function<void ()> enqueue_cb;
423
+ std::vector<View> views;
424
+ size_t total_size = 0 ;
425
+ };
426
+
427
+ std::shared_ptr<Impl> impl_ptr = std::make_shared<Impl>();
428
+ impl_ptr->reader = BaseObjectPtr<Blob::Reader>(reader);
429
+ impl_ptr->callback .Reset (env->isolate (), fn);
430
+ impl_ptr->env = env;
431
+
432
+ auto next = [impl_ptr](int status, const DataQueue::Vec* vecs, size_t count, bob::Done doneCb) mutable {
433
+ Environment* env = impl_ptr->env ;
434
+ HandleScope handleScope (env->isolate ());
435
+ Local<Function> fn = impl_ptr->callback .Get (env->isolate ());
436
+
437
+ if (status == bob::STATUS_EOS) impl_ptr->reader ->eos_ = true ;
438
+
439
+ if (count > 0 ) {
440
+ size_t total = 0 ;
441
+ for (size_t n = 0 ; n < count; n++) total += vecs[n].len ;
442
+
443
+ // contructing array buffer requires a shared_ptr
444
+ std::shared_ptr<BackingStore> store = v8::ArrayBuffer::NewBackingStore (env->isolate (), total);
445
+ auto ptr = static_cast <uint8_t *>(store->Data ());
446
+ for (size_t n = 0 ; n < count; n++) {
447
+ std::copy (vecs[n].base , vecs[n].base + vecs[n].len , ptr);
448
+ ptr += vecs[n].len ;
449
+ }
450
+ doneCb (0 );
451
+ impl_ptr->views .emplace_back (View{store, total});
452
+ impl_ptr->total_size += total;
453
+ }
454
+
455
+ if (status > 0 ) {
456
+ impl_ptr->enqueue_cb ();
457
+ } else {
458
+ std::shared_ptr<BackingStore> store = ArrayBuffer::NewBackingStore (env->isolate (), impl_ptr->total_size );
459
+ auto ptr = static_cast <uint8_t *>(store->Data ());
460
+ auto views = impl_ptr->views ;
461
+ for (const auto & view : views) {
462
+ uint8_t * from = static_cast <uint8_t *>(view.store ->Data ()) + view.offset ;
463
+ std::copy (from, from + view.length , ptr);
464
+ ptr += view.length ;
465
+ }
466
+ Local<Value> argv[2 ] = {Int32::New (env->isolate (), status), ArrayBuffer::New (env->isolate (), store)};
467
+ impl_ptr->reader ->MakeCallback (fn, arraysize (argv), argv);
468
+ impl_ptr->reader .reset ();
469
+ }
470
+ };
471
+
472
+ impl_ptr->enqueue_cb = [next, impl_ptr]() {
473
+ if (impl_ptr->reader && impl_ptr->reader ->inner_ ) {
474
+ impl_ptr->reader ->inner_ ->Pull (next, node::bob::OPTIONS_END, nullptr , 0 );
475
+ }
476
+ };
477
+
478
+ impl_ptr->enqueue_cb ();
479
+ }
480
+
396
481
BaseObjectPtr<BaseObject>
397
482
Blob::BlobTransferData::Deserialize (
398
483
Environment* env,
@@ -574,6 +659,7 @@ void Blob::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
574
659
registry->Register (Blob::GetDataObject);
575
660
registry->Register (Blob::RevokeObjectURL);
576
661
registry->Register (Blob::Reader::Pull);
662
+ registry->Register (Blob::Reader::PullAll);
577
663
registry->Register (Concat);
578
664
registry->Register (BlobFromFilePath);
579
665
}
0 commit comments