@@ -1211,6 +1211,62 @@ 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 = simdutf::binary_to_base64 (ext->data (), ext->length (), buffer.out ());
1229+ } else if (input->IsOneByte ()) {
1230+ MaybeStackBuffer<uint8_t > stack_buf (input->Length ());
1231+ input->WriteOneByte (env->isolate (),
1232+ stack_buf.out (),
1233+ 0 ,
1234+ input->Length (),
1235+ String::NO_NULL_TERMINATION);
1236+
1237+ size_t expected_length =
1238+ simdutf::base64_length_from_binary (input->Length ());
1239+ buffer.AllocateSufficientStorage (expected_length + 1 );
1240+ buffer.SetLengthAndZeroTerminate (expected_length);
1241+ written =
1242+ simdutf::binary_to_base64 (reinterpret_cast <const char *>(*stack_buf),
1243+ input->Length (),
1244+ buffer.out ());
1245+ } else {
1246+ String::Value value (env->isolate (), input);
1247+ MaybeStackBuffer<char > stack_buf (value.length ());
1248+ size_t out_len = simdutf::convert_utf16_to_latin1 (
1249+ reinterpret_cast <const char16_t *>(*value),
1250+ value.length (),
1251+ stack_buf.out ());
1252+ if (out_len == 0 ) { // error
1253+ return args.GetReturnValue ().SetEmptyString ();
1254+ }
1255+ size_t expected_length = simdutf::base64_length_from_binary (out_len);
1256+ buffer.AllocateSufficientStorage (expected_length + 1 );
1257+ buffer.SetLengthAndZeroTerminate (expected_length);
1258+ written = simdutf::binary_to_base64 (*stack_buf, out_len, buffer.out ());
1259+ }
1260+
1261+ auto value =
1262+ String::NewFromOneByte (env->isolate (),
1263+ reinterpret_cast <const uint8_t *>(buffer.out ()),
1264+ NewStringType::kNormal ,
1265+ written)
1266+ .ToLocalChecked ();
1267+ return args.GetReturnValue ().Set (value);
1268+ }
1269+
12141270// In case of success, the decoded string is returned.
12151271// In case of error, a negative value is returned:
12161272// * -1 indicates a single character remained,
@@ -1329,6 +1385,7 @@ void Initialize(Local<Object> target,
13291385 Isolate* isolate = env->isolate ();
13301386
13311387 SetMethodNoSideEffect (context, target, " atob" , Atob);
1388+ SetMethodNoSideEffect (context, target, " btoa" , Btoa);
13321389
13331390 SetMethod (context, target, " setBufferPrototype" , SetBufferPrototype);
13341391 SetMethodNoSideEffect (context, target, " createFromString" , CreateFromString);
@@ -1433,6 +1490,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
14331490 registry->Register (CopyArrayBuffer);
14341491
14351492 registry->Register (Atob);
1493+ registry->Register (Btoa);
14361494}
14371495
14381496} // namespace Buffer
0 commit comments