@@ -1211,6 +1211,63 @@ void DetachArrayBuffer(const FunctionCallbackInfo<Value>& args) {
12111211 }
12121212}
12131213
1214+ static void Btoa (const FunctionCallbackInfo<Value>& args) {
1215+ CHECK_EQ (args.Length (), 1 );
1216+ Environment* env = Environment::GetCurrent (args);
1217+ THROW_AND_RETURN_IF_NOT_STRING (env, args[0 ], " argument" );
1218+
1219+ Local<String> input = args[0 ].As <String>();
1220+ MaybeStackBuffer<char > buffer;
1221+ size_t written;
1222+
1223+ if (input->IsExternalOneByte ()) { // 8-bit case
1224+ auto ext = input->GetExternalOneByteStringResource ();
1225+ size_t expected_length = simdutf::base64_length_from_binary (ext->length ());
1226+ buffer.AllocateSufficientStorage (expected_length + 1 );
1227+ buffer.SetLengthAndZeroTerminate (expected_length);
1228+ written =
1229+ simdutf::binary_to_base64 (ext->data (), ext->length (), buffer.out ());
1230+ } else if (input->IsOneByte ()) {
1231+ MaybeStackBuffer<uint8_t > stack_buf (input->Length ());
1232+ input->WriteOneByte (env->isolate (),
1233+ stack_buf.out (),
1234+ 0 ,
1235+ input->Length (),
1236+ String::NO_NULL_TERMINATION);
1237+
1238+ size_t expected_length =
1239+ simdutf::base64_length_from_binary (input->Length ());
1240+ buffer.AllocateSufficientStorage (expected_length + 1 );
1241+ buffer.SetLengthAndZeroTerminate (expected_length);
1242+ written =
1243+ simdutf::binary_to_base64 (reinterpret_cast <const char *>(*stack_buf),
1244+ input->Length (),
1245+ buffer.out ());
1246+ } else {
1247+ String::Value value (env->isolate (), input);
1248+ MaybeStackBuffer<char > stack_buf (value.length ());
1249+ size_t out_len = simdutf::convert_utf16_to_latin1 (
1250+ reinterpret_cast <const char16_t *>(*value),
1251+ value.length (),
1252+ stack_buf.out ());
1253+ if (out_len == 0 ) { // error
1254+ return args.GetReturnValue ().Set (-1 );
1255+ }
1256+ size_t expected_length = simdutf::base64_length_from_binary (out_len);
1257+ buffer.AllocateSufficientStorage (expected_length + 1 );
1258+ buffer.SetLengthAndZeroTerminate (expected_length);
1259+ written = simdutf::binary_to_base64 (*stack_buf, out_len, buffer.out ());
1260+ }
1261+
1262+ auto value =
1263+ String::NewFromOneByte (env->isolate (),
1264+ reinterpret_cast <const uint8_t *>(buffer.out ()),
1265+ NewStringType::kNormal ,
1266+ written)
1267+ .ToLocalChecked ();
1268+ return args.GetReturnValue ().Set (value);
1269+ }
1270+
12141271// In case of success, the decoded string is returned.
12151272// In case of error, a negative value is returned:
12161273// * -1 indicates a single character remained,
@@ -1329,6 +1386,7 @@ void Initialize(Local<Object> target,
13291386 Isolate* isolate = env->isolate ();
13301387
13311388 SetMethodNoSideEffect (context, target, " atob" , Atob);
1389+ SetMethodNoSideEffect (context, target, " btoa" , Btoa);
13321390
13331391 SetMethod (context, target, " setBufferPrototype" , SetBufferPrototype);
13341392 SetMethodNoSideEffect (context, target, " createFromString" , CreateFromString);
@@ -1433,6 +1491,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
14331491 registry->Register (CopyArrayBuffer);
14341492
14351493 registry->Register (Atob);
1494+ registry->Register (Btoa);
14361495}
14371496
14381497} // namespace Buffer
0 commit comments