@@ -75,7 +75,6 @@ using v8::Object;
7575using v8::SharedArrayBuffer;
7676using v8::String;
7777using v8::Uint32;
78- using v8::Uint32Array;
7978using v8::Uint8Array;
8079using v8::Value;
8180
@@ -1177,35 +1176,6 @@ void SetBufferPrototype(const FunctionCallbackInfo<Value>& args) {
11771176 realm->set_buffer_prototype_object (proto);
11781177}
11791178
1180- void GetZeroFillToggle (const FunctionCallbackInfo<Value>& args) {
1181- Environment* env = Environment::GetCurrent (args);
1182- NodeArrayBufferAllocator* allocator = env->isolate_data ()->node_allocator ();
1183- Local<ArrayBuffer> ab;
1184- // It can be a nullptr when running inside an isolate where we
1185- // do not own the ArrayBuffer allocator.
1186- if (allocator == nullptr ) {
1187- // Create a dummy Uint32Array - the JS land can only toggle the C++ land
1188- // setting when the allocator uses our toggle. With this the toggle in JS
1189- // land results in no-ops.
1190- ab = ArrayBuffer::New (env->isolate (), sizeof (uint32_t ));
1191- } else {
1192- uint32_t * zero_fill_field = allocator->zero_fill_field ();
1193- std::unique_ptr<BackingStore> backing =
1194- ArrayBuffer::NewBackingStore (zero_fill_field,
1195- sizeof (*zero_fill_field),
1196- [](void *, size_t , void *) {},
1197- nullptr );
1198- ab = ArrayBuffer::New (env->isolate (), std::move (backing));
1199- }
1200-
1201- ab->SetPrivate (
1202- env->context (),
1203- env->untransferable_object_private_symbol (),
1204- True (env->isolate ())).Check ();
1205-
1206- args.GetReturnValue ().Set (Uint32Array::New (ab, 0 , 1 ));
1207- }
1208-
12091179void DetachArrayBuffer (const FunctionCallbackInfo<Value>& args) {
12101180 Environment* env = Environment::GetCurrent (args);
12111181 if (args[0 ]->IsArrayBuffer ()) {
@@ -1397,6 +1367,54 @@ void CopyArrayBuffer(const FunctionCallbackInfo<Value>& args) {
13971367 memcpy (dest, src, bytes_to_copy);
13981368}
13991369
1370+ // Converts a number parameter to size_t suitable for ArrayBuffer sizes
1371+ // Could be larger than uint32_t
1372+ // See v8::internal::TryNumberToSize and v8::internal::NumberToSize
1373+ inline size_t CheckNumberToSize (Local<Value> number) {
1374+ CHECK (number->IsNumber ());
1375+ double value = number.As <Number>()->Value ();
1376+ // See v8::internal::TryNumberToSize on this (and on < comparison)
1377+ double maxSize = static_cast <double >(std::numeric_limits<size_t >::max ());
1378+ CHECK (value >= 0 && value < maxSize);
1379+ size_t size = static_cast <size_t >(value);
1380+ #ifdef V8_ENABLE_SANDBOX
1381+ CHECK_LE (size, kMaxSafeBufferSizeForSandbox );
1382+ #endif
1383+ return size;
1384+ }
1385+
1386+ void CreateUnsafeArrayBuffer (const FunctionCallbackInfo<Value>& args) {
1387+ Environment* env = Environment::GetCurrent (args);
1388+ if (args.Length () != 1 ) {
1389+ env->ThrowRangeError (" Invalid array buffer length" );
1390+ return ;
1391+ }
1392+
1393+ size_t size = CheckNumberToSize (args[0 ]);
1394+
1395+ Isolate* isolate = env->isolate ();
1396+
1397+ Local<ArrayBuffer> buf;
1398+
1399+ NodeArrayBufferAllocator* allocator = env->isolate_data ()->node_allocator ();
1400+ // 0-length, or zero-fill flag is set, or building snapshot
1401+ if (size == 0 || per_process::cli_options->zero_fill_all_buffers ||
1402+ allocator == nullptr ) {
1403+ buf = ArrayBuffer::New (isolate, size);
1404+ } else {
1405+ std::unique_ptr<BackingStore> store =
1406+ ArrayBuffer::NewBackingStoreForNodeLTS (isolate, size);
1407+ if (!store) {
1408+ // This slightly differs from the old behavior,
1409+ // as in v8 that's a RangeError, and this is an Error with code
1410+ return env->ThrowRangeError (" Array buffer allocation failed" );
1411+ }
1412+ buf = ArrayBuffer::New (isolate, std::move (store));
1413+ }
1414+
1415+ args.GetReturnValue ().Set (buf);
1416+ }
1417+
14001418void Initialize (Local<Object> target,
14011419 Local<Value> unused,
14021420 Local<Context> context,
@@ -1428,6 +1446,8 @@ void Initialize(Local<Object> target,
14281446
14291447 SetMethod (context, target, " detachArrayBuffer" , DetachArrayBuffer);
14301448 SetMethod (context, target, " copyArrayBuffer" , CopyArrayBuffer);
1449+ SetMethodNoSideEffect (
1450+ context, target, " createUnsafeArrayBuffer" , CreateUnsafeArrayBuffer);
14311451
14321452 SetMethod (context, target, " swap16" , Swap16);
14331453 SetMethod (context, target, " swap32" , Swap32);
@@ -1464,8 +1484,6 @@ void Initialize(Local<Object> target,
14641484 SetMethod (context, target, " hexWrite" , StringWrite<HEX>);
14651485 SetMethod (context, target, " ucs2Write" , StringWrite<UCS2>);
14661486 SetMethod (context, target, " utf8Write" , StringWrite<UTF8>);
1467-
1468- SetMethod (context, target, " getZeroFillToggle" , GetZeroFillToggle);
14691487}
14701488
14711489} // anonymous namespace
@@ -1508,10 +1526,10 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
15081526 registry->Register (StringWrite<HEX>);
15091527 registry->Register (StringWrite<UCS2>);
15101528 registry->Register (StringWrite<UTF8>);
1511- registry->Register (GetZeroFillToggle);
15121529
15131530 registry->Register (DetachArrayBuffer);
15141531 registry->Register (CopyArrayBuffer);
1532+ registry->Register (CreateUnsafeArrayBuffer);
15151533
15161534 registry->Register (Atob);
15171535 registry->Register (Btoa);
0 commit comments