11#include " encoding_binding.h"
22#include " ada.h"
3+ #include " encoding_singlebyte.h"
34#include " env-inl.h"
45#include " node_errors.h"
56#include " node_external_reference.h"
@@ -389,15 +390,80 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo<Value>& args) {
389390 }
390391}
391392
393+ void BindingData::DecodeSingleByte (const FunctionCallbackInfo<Value>& args) {
394+ Environment* env = Environment::GetCurrent (args);
395+
396+ CHECK_GE (args.Length (), 2 );
397+ Isolate* isolate = env->isolate ();
398+
399+ if (!(args[0 ]->IsArrayBuffer () || args[0 ]->IsSharedArrayBuffer () ||
400+ args[0 ]->IsArrayBufferView ())) {
401+ return node::THROW_ERR_INVALID_ARG_TYPE (
402+ isolate,
403+ " The \" input\" argument must be an instance of SharedArrayBuffer, "
404+ " ArrayBuffer or ArrayBufferView." );
405+ }
406+
407+ CHECK (args[1 ]->IsInt32 ());
408+ const int encoding = args[1 ].As <v8::Int32>()->Value ();
409+ CHECK (encoding >= 0 && encoding < 29 );
410+
411+ ArrayBufferViewContents<uint8_t > buffer (args[0 ]);
412+ const uint8_t * data = buffer.data ();
413+ size_t length = buffer.length ();
414+
415+ if (length == 0 ) return args.GetReturnValue ().SetEmptyString ();
416+
417+ const char * dataChar = reinterpret_cast <const char *>(data);
418+ if (!simdutf::validate_ascii_with_errors (dataChar, length).error ) {
419+ Local<Value> ret;
420+ if (StringBytes::Encode (isolate, dataChar, length, LATIN1).ToLocal (&ret)) {
421+ args.GetReturnValue ().Set (ret);
422+ }
423+ return ;
424+ }
425+
426+ uint16_t * dst = node::UncheckedMalloc<uint16_t >(length);
427+ if (dst == nullptr ) {
428+ isolate->ThrowException (node::ERR_MEMORY_ALLOCATION_FAILED (isolate));
429+ return MaybeLocal<Value>();
430+ }
431+
432+ if (encoding == 28 ) {
433+ // x-user-defined
434+ for (size_t i = 0 ; i < length; i++) {
435+ dst[i] = data[i] >= 0x80 ? data[i] + 0xf700 : data[i];
436+ }
437+ } else {
438+ bool has_fatal = args[2 ]->IsTrue ();
439+
440+ const uint16_t * table = tSingleByteEncodings[encoding];
441+ for (size_t i = 0 ; i < length; i++) dst[i] = table[data[i]];
442+
443+ const char16_t * dst16 = reinterpret_cast <char16_t *>(dst);
444+ if (has_fatal && fSingleByteEncodings [encoding] &&
445+ simdutf::find (dst16, dst16 + length, 0xfffd ) != dst16 + length) {
446+ free (dst);
447+ return node::THROW_ERR_ENCODING_INVALID_ENCODED_DATA (
448+ isolate, " The encoded data was not valid for this encoding" );
449+ }
450+ }
451+
452+ Local<Value> ret;
453+ if (StringBytes::Raw (isolate, dst, length).ToLocal (&ret)) {
454+ args.GetReturnValue ().Set (ret);
455+ }
456+ }
457+
392458void BindingData::ToASCII (const FunctionCallbackInfo<Value>& args) {
393459 Environment* env = Environment::GetCurrent (args);
394460 CHECK_GE (args.Length (), 1 );
395461 CHECK (args[0 ]->IsString ());
396462
397- Utf8Value input (env-> isolate () , args[0 ]);
463+ Utf8Value input (isolate, args[0 ]);
398464 auto out = ada::idna::to_ascii (input.ToStringView ());
399465 Local<Value> ret;
400- if (ToV8Value (env->context (), out, env-> isolate () ).ToLocal (&ret)) {
466+ if (ToV8Value (env->context (), out, isolate).ToLocal (&ret)) {
401467 args.GetReturnValue ().Set (ret);
402468 }
403469}
@@ -421,6 +487,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
421487 SetMethod (isolate, target, " encodeInto" , EncodeInto);
422488 SetMethodNoSideEffect (isolate, target, " encodeUtf8String" , EncodeUtf8String);
423489 SetMethodNoSideEffect (isolate, target, " decodeUTF8" , DecodeUTF8);
490+ SetMethodNoSideEffect (isolate, target, " decodeSingleByte" , DecodeSingleByte);
424491 SetMethodNoSideEffect (isolate, target, " toASCII" , ToASCII);
425492 SetMethodNoSideEffect (isolate, target, " toUnicode" , ToUnicode);
426493}
@@ -438,6 +505,7 @@ void BindingData::RegisterTimerExternalReferences(
438505 registry->Register (EncodeInto);
439506 registry->Register (EncodeUtf8String);
440507 registry->Register (DecodeUTF8);
508+ registry->Register (DecodeSingleByte);
441509 registry->Register (ToASCII);
442510 registry->Register (ToUnicode);
443511}
0 commit comments