@@ -675,26 +675,17 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
675675 return ;
676676 }
677677
678- const uint8_t * source_data = nullptr ;
679- size_t source_len = 0 ;
678+ // This needs to be kept alive until the data
679+ // is actually copied.
680+ ArrayBufferViewContents<uint8_t > view;
680681
681- if (args[0 ]->IsArrayBuffer ()) {
682- Local<ArrayBuffer> array_buffer = args[0 ].As <ArrayBuffer>();
683- std::shared_ptr<BackingStore> store = array_buffer->GetBackingStore ();
684- if (!store) {
685- THROW_ERR_INVALID_ARG_VALUE (env, " Invalid ArrayBuffer backing store" );
686- return ;
687- }
688- source_data = static_cast <const uint8_t *>(store->Data ());
689- source_len = array_buffer->ByteLength ();
690- } else if (args[0 ]->IsArrayBufferView ()) {
691- ArrayBufferViewContents<uint8_t > view (args[0 ]);
682+ if (args[0 ]->IsArrayBuffer () || args[0 ]->IsSharedArrayBuffer () ||
683+ args[0 ]->IsArrayBufferView ()) {
684+ view.ReadValue (args[0 ]);
692685 if (view.WasDetached ()) {
693686 THROW_ERR_INVALID_ARG_VALUE (env, " Invalid ArrayBufferView backing store" );
694687 return ;
695688 }
696- source_data = view.data ();
697- source_len = view.length ();
698689 } else {
699690 THROW_ERR_INVALID_ARG_TYPE (
700691 env,
@@ -713,12 +704,12 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
713704 return ;
714705 }
715706
716- if (len < source_len ) {
707+ if (len < view. length () ) {
717708 THROW_ERR_OUT_OF_RANGE (env, " The length must be >= source byte length" );
718709 return ;
719710 }
720711
721- if (ptr == 0 && source_len > 0 ) {
712+ if (ptr == 0 && view. length () > 0 ) {
722713 THROW_ERR_FFI_INVALID_POINTER (env,
723714 " Cannot create a buffer from a null pointer" );
724715 return ;
@@ -733,9 +724,7 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
733724 return ;
734725 }
735726
736- if (source_len > 0 ) {
737- std::memcpy (reinterpret_cast <void *>(ptr), source_data, source_len);
738- }
727+ std::memcpy (reinterpret_cast <void *>(ptr), view.data (), view.length ());
739728}
740729
741730void GetRawPointer (const FunctionCallbackInfo<Value>& args) {
@@ -752,28 +741,34 @@ void GetRawPointer(const FunctionCallbackInfo<Value>& args) {
752741 }
753742
754743 uintptr_t ptr = 0 ;
744+ size_t offset = 0 ;
745+ std::shared_ptr<BackingStore> store;
755746
756747 if (args[0 ]->IsArrayBuffer ()) {
757- Local<ArrayBuffer> array_buffer = args[0 ].As <ArrayBuffer>();
758- std::shared_ptr<BackingStore> store = array_buffer->GetBackingStore ();
759- if (!store) {
760- THROW_ERR_INVALID_ARG_VALUE (env, " Invalid ArrayBuffer backing store" );
761- return ;
762- }
763- ptr = reinterpret_cast <uintptr_t >(store->Data ());
748+ store = args[0 ].As <ArrayBuffer>()->GetBackingStore ();
749+ } else if (args[0 ]->IsSharedArrayBuffer ()) {
750+ store = args[0 ].As <SharedArrayBuffer>()->GetBackingStore ();
764751 } else if (args[0 ]->IsArrayBufferView ()) {
765- ArrayBufferViewContents<uint8_t > view (args[0 ]);
766- if (view.WasDetached ()) {
767- THROW_ERR_INVALID_ARG_VALUE (env, " Invalid ArrayBufferView backing store" );
768- return ;
769- }
770- ptr = reinterpret_cast <uintptr_t >(view.data ());
752+ // Access the store here to ensure that it exists. Small typed arrays
753+ // may not have a store until this point and can instead be stored
754+ // entirely in-heap.
755+ store = args[0 ].As <ArrayBufferView>()->Buffer ()->GetBackingStore ();
756+ offset = args[0 ].As <ArrayBufferView>()->ByteOffset ();
771757 } else {
772- THROW_ERR_INVALID_ARG_TYPE (
773- env,
774- " The first argument must be a Buffer, ArrayBuffer, or ArrayBufferView" );
758+ THROW_ERR_INVALID_ARG_TYPE (env,
759+ " The first argument must be a Buffer, "
760+ " ArrayBuffer, or ArrayBufferView" );
761+ return ;
762+ }
763+
764+ // WARNING: There is no inherent guarantee that the pointer returned
765+ // from this function will be valid beyond the lifetime of the BackingStore
766+ // instance!
767+ if (!store) {
768+ THROW_ERR_INVALID_ARG_VALUE (env, " Invalid ArrayBuffer backing store" );
775769 return ;
776770 }
771+ ptr = reinterpret_cast <uintptr_t >(store->Data ()) + offset;
777772
778773 args.GetReturnValue ().Set (
779774 BigInt::NewFromUnsigned (isolate, static_cast <uint64_t >(ptr)));
0 commit comments