@@ -346,17 +346,65 @@ size_t StringBytes::Write(Isolate* isolate,
346346 }
347347
348348 case BASE64URL:
349- // Fall through
350- case BASE64:
351- if (str->IsExternalOneByte ()) {
349+ if (str->IsExternalOneByte ()) { // 8-bit case
352350 auto ext = str->GetExternalOneByteStringResource ();
353- nbytes = base64_decode (buf, buflen, ext->data (), ext->length ());
351+ auto result = simdutf::base64_to_binary_safe (
352+ ext->data (), ext->length (), buf, buflen, simdutf::base64_url);
353+ if (result.error == simdutf::error_code::SUCCESS) {
354+ nbytes = result.count ;
355+ } else {
356+ // The input does not follow the WHATWG forgiving-base64 specification
357+ // adapted for base64url
358+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
359+ nbytes = base64_decode (buf, buflen, ext->data (), ext->length ());
360+ }
354361 } else {
355362 String::Value value (isolate, str);
356- nbytes = base64_decode (buf, buflen, *value, value.length ());
363+ auto result =
364+ simdutf::base64_to_binary (reinterpret_cast <const char16_t *>(*value),
365+ value.length (),
366+ buf,
367+ simdutf::base64_url);
368+ if (result.error == simdutf::error_code::SUCCESS) {
369+ nbytes = result.count ;
370+ } else {
371+ // The input does not follow the WHATWG forgiving-base64 specification
372+ // (adapted for base64url with + and / replaced by - and _).
373+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
374+ nbytes = base64_decode (buf, buflen, *value, value.length ());
375+ }
357376 }
358377 break ;
359378
379+ case BASE64: {
380+ if (str->IsExternalOneByte ()) { // 8-bit case
381+ auto ext = str->GetExternalOneByteStringResource ();
382+ auto result = simdutf::base64_to_binary_safe (
383+ ext->data (), ext->length (), buf, buflen);
384+ if (result.error == simdutf::error_code::SUCCESS) {
385+ nbytes = result.count ;
386+ } else {
387+ // The input does not follow the WHATWG forgiving-base64 specification
388+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
389+ nbytes = base64_decode (buf, buflen, ext->data (), ext->length ());
390+ }
391+ } else {
392+ String::Value value (isolate, str);
393+ auto result = simdutf::base64_to_binary_safe (
394+ reinterpret_cast <const char16_t *>(*value),
395+ value.length (),
396+ buf,
397+ buflen);
398+ if (result.error == simdutf::error_code::SUCCESS) {
399+ nbytes = result.count ;
400+ } else {
401+ // The input does not follow the WHATWG base64 specification
402+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
403+ nbytes = base64_decode (buf, buflen, *value, value.length ());
404+ }
405+ }
406+ break ;
407+ }
360408 case HEX:
361409 if (str->IsExternalOneByte ()) {
362410 auto ext = str->GetExternalOneByteStringResource ();
@@ -411,9 +459,12 @@ Maybe<size_t> StringBytes::StorageSize(Isolate* isolate,
411459 break ;
412460
413461 case BASE64URL:
414- // Fall through
462+ data_size = simdutf::base64_length_from_binary (str->Length (),
463+ simdutf::base64_url);
464+ break ;
465+
415466 case BASE64:
416- data_size = base64_decoded_size_fast (str->Length ());
467+ data_size = simdutf::base64_length_from_binary (str->Length ());
417468 break ;
418469
419470 case HEX:
@@ -452,11 +503,15 @@ Maybe<size_t> StringBytes::Size(Isolate* isolate,
452503 case UCS2:
453504 return Just (str->Length () * sizeof (uint16_t ));
454505
455- case BASE64URL:
456- // Fall through
506+ case BASE64URL: {
507+ String::Value value (isolate, str);
508+ return Just (simdutf::base64_length_from_binary (value.length (),
509+ simdutf::base64_url));
510+ }
511+
457512 case BASE64: {
458513 String::Value value (isolate, str);
459- return Just (base64_decoded_size (*value, value.length ()));
514+ return Just (simdutf::base64_length_from_binary ( value.length ()));
460515 }
461516
462517 case HEX:
@@ -609,28 +664,30 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
609664 return ExternOneByteString::NewFromCopy (isolate, buf, buflen, error);
610665
611666 case BASE64: {
612- size_t dlen = base64_encoded_size (buflen);
667+ size_t dlen = simdutf::base64_length_from_binary (buflen);
613668 char * dst = node::UncheckedMalloc (dlen);
614669 if (dst == nullptr ) {
615670 *error = node::ERR_MEMORY_ALLOCATION_FAILED (isolate);
616671 return MaybeLocal<Value>();
617672 }
618673
619- size_t written = base64_encode (buf, buflen, dst, dlen );
674+ size_t written = simdutf::binary_to_base64 (buf, buflen, dst);
620675 CHECK_EQ (written, dlen);
621676
622677 return ExternOneByteString::New (isolate, dst, dlen, error);
623678 }
624679
625680 case BASE64URL: {
626- size_t dlen = base64_encoded_size (buflen, Base64Mode::URL);
681+ size_t dlen =
682+ simdutf::base64_length_from_binary (buflen, simdutf::base64_url);
627683 char * dst = node::UncheckedMalloc (dlen);
628684 if (dst == nullptr ) {
629685 *error = node::ERR_MEMORY_ALLOCATION_FAILED (isolate);
630686 return MaybeLocal<Value>();
631687 }
632688
633- size_t written = base64_encode (buf, buflen, dst, dlen, Base64Mode::URL);
689+ size_t written =
690+ simdutf::binary_to_base64 (buf, buflen, dst, simdutf::base64_url);
634691 CHECK_EQ (written, dlen);
635692
636693 return ExternOneByteString::New (isolate, dst, dlen, error);
0 commit comments