@@ -80,7 +80,6 @@ using v8::Object;
8080using v8::SharedArrayBuffer;
8181using v8::String;
8282using v8::Uint32;
83- using v8::Uint32Array;
8483using v8::Uint8Array;
8584using v8::Value;
8685
@@ -1244,45 +1243,6 @@ void SetBufferPrototype(const FunctionCallbackInfo<Value>& args) {
12441243 realm->set_buffer_prototype_object (proto);
12451244}
12461245
1247- void GetZeroFillToggle (const FunctionCallbackInfo<Value>& args) {
1248- Environment* env = Environment::GetCurrent (args);
1249- NodeArrayBufferAllocator* allocator = env->isolate_data ()->node_allocator ();
1250- Local<ArrayBuffer> ab;
1251- // It can be a nullptr when running inside an isolate where we
1252- // do not own the ArrayBuffer allocator.
1253- if (allocator == nullptr || env->isolate_data ()->is_building_snapshot ()) {
1254- // Create a dummy Uint32Array - the JS land can only toggle the C++ land
1255- // setting when the allocator uses our toggle. With this the toggle in JS
1256- // land results in no-ops.
1257- // When building a snapshot, just use a dummy toggle as well to avoid
1258- // introducing the dynamic external reference. We'll re-initialize the
1259- // toggle with a real one connected to the C++ allocator after snapshot
1260- // deserialization.
1261-
1262- ab = ArrayBuffer::New (env->isolate (), sizeof (uint32_t ));
1263- } else {
1264- // TODO(joyeecheung): save ab->GetBackingStore()->Data() in the Node.js
1265- // array buffer allocator and include it into the C++ toggle while the
1266- // Environment is still alive.
1267- uint32_t * zero_fill_field = allocator->zero_fill_field ();
1268- std::unique_ptr<BackingStore> backing =
1269- ArrayBuffer::NewBackingStore (zero_fill_field,
1270- sizeof (*zero_fill_field),
1271- [](void *, size_t , void *) {},
1272- nullptr );
1273- ab = ArrayBuffer::New (env->isolate (), std::move (backing));
1274- }
1275-
1276- if (ab->SetPrivate (env->context (),
1277- env->untransferable_object_private_symbol (),
1278- True (env->isolate ()))
1279- .IsNothing ()) {
1280- return ;
1281- }
1282-
1283- args.GetReturnValue ().Set (Uint32Array::New (ab, 0 , 1 ));
1284- }
1285-
12861246static void Btoa (const FunctionCallbackInfo<Value>& args) {
12871247 CHECK_EQ (args.Length (), 1 );
12881248 Environment* env = Environment::GetCurrent (args);
@@ -1449,6 +1409,57 @@ void CopyArrayBuffer(const FunctionCallbackInfo<Value>& args) {
14491409 memcpy (dest, src, bytes_to_copy);
14501410}
14511411
1412+ // Converts a number parameter to size_t suitable for ArrayBuffer sizes
1413+ // Could be larger than uint32_t
1414+ // See v8::internal::TryNumberToSize and v8::internal::NumberToSize
1415+ inline size_t CheckNumberToSize (Local<Value> number) {
1416+ CHECK (number->IsNumber ());
1417+ double value = number.As <Number>()->Value ();
1418+ // See v8::internal::TryNumberToSize on this (and on < comparison)
1419+ double maxSize = static_cast <double >(std::numeric_limits<size_t >::max ());
1420+ CHECK (value >= 0 && value < maxSize);
1421+ size_t size = static_cast <size_t >(value);
1422+ #ifdef V8_ENABLE_SANDBOX
1423+ CHECK_LE (size, kMaxSafeBufferSizeForSandbox );
1424+ #endif
1425+ return size;
1426+ }
1427+
1428+ void CreateUnsafeArrayBuffer (const FunctionCallbackInfo<Value>& args) {
1429+ Environment* env = Environment::GetCurrent (args);
1430+ if (args.Length () != 1 ) {
1431+ env->ThrowRangeError (" Invalid array buffer length" );
1432+ return ;
1433+ }
1434+
1435+ size_t size = CheckNumberToSize (args[0 ]);
1436+
1437+ Isolate* isolate = env->isolate ();
1438+
1439+ Local<ArrayBuffer> buf;
1440+
1441+ // 0-length, or zero-fill flag is set, or building snapshot
1442+ if (size == 0 || per_process::cli_options->zero_fill_all_buffers ||
1443+ env->isolate_data ()->is_building_snapshot ()) {
1444+ buf = ArrayBuffer::New (isolate, size);
1445+ } else {
1446+ std::unique_ptr<BackingStore> store = ArrayBuffer::NewBackingStore (
1447+ isolate,
1448+ size,
1449+ BackingStoreInitializationMode::kUninitialized ,
1450+ v8::BackingStoreOnFailureMode::kReturnNull );
1451+
1452+ if (!store) {
1453+ env->ThrowRangeError (" Array buffer allocation failed" );
1454+ return ;
1455+ }
1456+
1457+ buf = ArrayBuffer::New (isolate, std::move (store));
1458+ }
1459+
1460+ args.GetReturnValue ().Set (buf);
1461+ }
1462+
14521463template <encoding encoding>
14531464uint32_t WriteOneByteString (const char * src,
14541465 uint32_t src_len,
@@ -1576,6 +1587,8 @@ void Initialize(Local<Object> target,
15761587 SetMethodNoSideEffect (context, target, " indexOfString" , IndexOfString);
15771588
15781589 SetMethod (context, target, " copyArrayBuffer" , CopyArrayBuffer);
1590+ SetMethodNoSideEffect (
1591+ context, target, " createUnsafeArrayBuffer" , CreateUnsafeArrayBuffer);
15791592
15801593 SetMethod (context, target, " swap16" , Swap16);
15811594 SetMethod (context, target, " swap32" , Swap32);
@@ -1625,8 +1638,6 @@ void Initialize(Local<Object> target,
16251638 " utf8WriteStatic" ,
16261639 SlowWriteString<UTF8>,
16271640 &fast_write_string_utf8);
1628-
1629- SetMethod (context, target, " getZeroFillToggle" , GetZeroFillToggle);
16301641}
16311642
16321643} // anonymous namespace
@@ -1675,9 +1686,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
16751686 registry->Register (StringWrite<HEX>);
16761687 registry->Register (StringWrite<UCS2>);
16771688 registry->Register (StringWrite<UTF8>);
1678- registry->Register (GetZeroFillToggle);
16791689
16801690 registry->Register (CopyArrayBuffer);
1691+ registry->Register (CreateUnsafeArrayBuffer);
16811692
16821693 registry->Register (Atob);
16831694 registry->Register (Btoa);
0 commit comments