@@ -25,6 +25,7 @@ using v8::MaybeLocal;
2525using v8::NewStringType;
2626using v8::Number;
2727using v8::Object;
28+ using v8::SharedArrayBuffer;
2829using v8::String;
2930using v8::Value;
3031
@@ -675,26 +676,17 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
675676 return ;
676677 }
677678
678- const uint8_t * source_data = nullptr ;
679- size_t source_len = 0 ;
679+ // This needs to be kept alive until the data
680+ // is actually copied.
681+ ArrayBufferViewContents<uint8_t > view;
680682
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 ]);
683+ if (args[0 ]->IsArrayBuffer () || args[0 ]->IsSharedArrayBuffer () ||
684+ args[0 ]->IsArrayBufferView ()) {
685+ view.ReadValue (args[0 ]);
692686 if (view.WasDetached ()) {
693687 THROW_ERR_INVALID_ARG_VALUE (env, " Invalid ArrayBufferView backing store" );
694688 return ;
695689 }
696- source_data = view.data ();
697- source_len = view.length ();
698690 } else {
699691 THROW_ERR_INVALID_ARG_TYPE (
700692 env,
@@ -713,12 +705,12 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
713705 return ;
714706 }
715707
716- if (len < source_len ) {
708+ if (len < view. length () ) {
717709 THROW_ERR_OUT_OF_RANGE (env, " The length must be >= source byte length" );
718710 return ;
719711 }
720712
721- if (ptr == 0 && source_len > 0 ) {
713+ if (ptr == 0 && view. length () > 0 ) {
722714 THROW_ERR_FFI_INVALID_POINTER (env,
723715 " Cannot create a buffer from a null pointer" );
724716 return ;
@@ -733,9 +725,7 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
733725 return ;
734726 }
735727
736- if (source_len > 0 ) {
737- std::memcpy (reinterpret_cast <void *>(ptr), source_data, source_len);
738- }
728+ std::memcpy (reinterpret_cast <void *>(ptr), view.data (), view.length ());
739729}
740730
741731void GetRawPointer (const FunctionCallbackInfo<Value>& args) {
@@ -752,28 +742,34 @@ void GetRawPointer(const FunctionCallbackInfo<Value>& args) {
752742 }
753743
754744 uintptr_t ptr = 0 ;
745+ size_t offset = 0 ;
746+ std::shared_ptr<BackingStore> store;
755747
756748 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 ());
749+ store = args[0 ].As <ArrayBuffer>()->GetBackingStore ();
750+ } else if (args[0 ]->IsSharedArrayBuffer ()) {
751+ store = args[0 ].As <SharedArrayBuffer>()->GetBackingStore ();
764752 } 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 ());
753+ // Access the store here to ensure that it exists. Small typed arrays
754+ // may not have a store until this point and can instead be stored
755+ // entirely in-heap.
756+ store = args[0 ].As <ArrayBufferView>()->Buffer ()->GetBackingStore ();
757+ offset = args[0 ].As <ArrayBufferView>()->ByteOffset ();
771758 } else {
772- THROW_ERR_INVALID_ARG_TYPE (
773- env,
774- " The first argument must be a Buffer, ArrayBuffer, or ArrayBufferView" );
759+ THROW_ERR_INVALID_ARG_TYPE (env,
760+ " The first argument must be a Buffer, "
761+ " ArrayBuffer, or ArrayBufferView" );
762+ return ;
763+ }
764+
765+ // WARNING: There is no inherent guarantee that the pointer returned
766+ // from this function will be valid beyond the lifetime of the BackingStore
767+ // instance!
768+ if (!store) {
769+ THROW_ERR_INVALID_ARG_VALUE (env, " Invalid ArrayBuffer backing store" );
775770 return ;
776771 }
772+ ptr = reinterpret_cast <uintptr_t >(store->Data ()) + offset;
777773
778774 args.GetReturnValue ().Set (
779775 BigInt::NewFromUnsigned (isolate, static_cast <uint64_t >(ptr)));
0 commit comments