@@ -1360,37 +1360,93 @@ void FastSwap64(Local<Value> receiver,
13601360
13611361static CFunction fast_swap64 (CFunction::Make(FastSwap64));
13621362
1363+ struct ValidationResult {
1364+ bool is_valid;
1365+ bool was_detached;
1366+ };
1367+
1368+ static ValidationResult ValidateUtf8 (Local<Value> value) {
1369+ ArrayBufferViewContents<char > abv (value);
1370+ bool was_detached = abv.WasDetached ();
1371+ return {!was_detached && simdutf::validate_utf8 (abv.data (), abv.length ()),
1372+ was_detached};
1373+ }
1374+
13631375static void IsUtf8 (const FunctionCallbackInfo<Value>& args) {
13641376 Environment* env = Environment::GetCurrent (args);
13651377 CHECK_EQ (args.Length (), 1 );
13661378 CHECK (args[0 ]->IsTypedArray () || args[0 ]->IsArrayBuffer () ||
13671379 args[0 ]->IsSharedArrayBuffer ());
1368- ArrayBufferViewContents<char > abv (args[0 ]);
13691380
1370- if (abv.WasDetached ()) {
1381+ const ValidationResult result = ValidateUtf8 (args[0 ]);
1382+ if (result.was_detached ) {
13711383 return node::THROW_ERR_INVALID_STATE (
13721384 env, " Cannot validate on a detached buffer" );
13731385 }
13741386
1375- args.GetReturnValue ().Set (simdutf::validate_utf8 (abv.data (), abv.length ()));
1387+ args.GetReturnValue ().Set (result.is_valid );
1388+ }
1389+
1390+ static bool FastIsUtf8 (Local<Value> receiver,
1391+ Local<Value> value,
1392+ // NOLINTNEXTLINE(runtime/references)
1393+ FastApiCallbackOptions& options) {
1394+ TRACK_V8_FAST_API_CALL (" buffer.isUtf8" );
1395+ HandleScope scope (options.isolate );
1396+
1397+ const ValidationResult result = ValidateUtf8 (value);
1398+ if (result.was_detached ) {
1399+ node::THROW_ERR_INVALID_STATE (options.isolate ,
1400+ " Cannot validate on a detached buffer" );
1401+ return false ;
1402+ }
1403+ return result.is_valid ;
1404+ }
1405+
1406+ static CFunction fast_is_utf8 (CFunction::Make(FastIsUtf8));
1407+
1408+ static ValidationResult ValidateAscii (Local<Value> value) {
1409+ ArrayBufferViewContents<char > abv (value);
1410+ bool was_detached = abv.WasDetached ();
1411+ return {
1412+ !was_detached &&
1413+ !simdutf::validate_ascii_with_errors (abv.data (), abv.length ()).error ,
1414+ was_detached};
13761415}
13771416
13781417static void IsAscii (const FunctionCallbackInfo<Value>& args) {
13791418 Environment* env = Environment::GetCurrent (args);
13801419 CHECK_EQ (args.Length (), 1 );
13811420 CHECK (args[0 ]->IsTypedArray () || args[0 ]->IsArrayBuffer () ||
13821421 args[0 ]->IsSharedArrayBuffer ());
1383- ArrayBufferViewContents<char > abv (args[0 ]);
13841422
1385- if (abv.WasDetached ()) {
1423+ const ValidationResult result = ValidateAscii (args[0 ]);
1424+ if (result.was_detached ) {
13861425 return node::THROW_ERR_INVALID_STATE (
13871426 env, " Cannot validate on a detached buffer" );
13881427 }
13891428
1390- args.GetReturnValue ().Set (
1391- !simdutf::validate_ascii_with_errors (abv.data (), abv.length ()).error );
1429+ args.GetReturnValue ().Set (result.is_valid );
13921430}
13931431
1432+ static bool FastIsAscii (Local<Value> receiver,
1433+ Local<Value> value,
1434+ // NOLINTNEXTLINE(runtime/references)
1435+ FastApiCallbackOptions& options) {
1436+ TRACK_V8_FAST_API_CALL (" buffer.isAscii" );
1437+ HandleScope scope (options.isolate );
1438+
1439+ const ValidationResult result = ValidateAscii (value);
1440+ if (result.was_detached ) {
1441+ node::THROW_ERR_INVALID_STATE (options.isolate ,
1442+ " Cannot validate on a detached buffer" );
1443+ return false ;
1444+ }
1445+ return result.is_valid ;
1446+ }
1447+
1448+ static CFunction fast_is_ascii (CFunction::Make(FastIsAscii));
1449+
13941450void SetBufferPrototype (const FunctionCallbackInfo<Value>& args) {
13951451 Realm* realm = Realm::GetCurrent (args);
13961452
@@ -1762,8 +1818,9 @@ void Initialize(Local<Object> target,
17621818 SetFastMethod (context, target, " swap32" , Swap32, &fast_swap32);
17631819 SetFastMethod (context, target, " swap64" , Swap64, &fast_swap64);
17641820
1765- SetMethodNoSideEffect (context, target, " isUtf8" , IsUtf8);
1766- SetMethodNoSideEffect (context, target, " isAscii" , IsAscii);
1821+ SetFastMethodNoSideEffect (context, target, " isUtf8" , IsUtf8, &fast_is_utf8);
1822+ SetFastMethodNoSideEffect (
1823+ context, target, " isAscii" , IsAscii, &fast_is_ascii);
17671824
17681825 target
17691826 ->Set (context,
@@ -1836,7 +1893,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
18361893 registry->Register (fast_swap64);
18371894
18381895 registry->Register (IsUtf8);
1896+ registry->Register (fast_is_utf8);
18391897 registry->Register (IsAscii);
1898+ registry->Register (fast_is_ascii);
18401899
18411900 registry->Register (StringSlice<ASCII >);
18421901 registry->Register (StringSlice<BASE64 >);
0 commit comments