diff --git a/src/encoding_binding.cc b/src/encoding_binding.cc index 69a34500b4590a..d60e080e22f0c4 100644 --- a/src/encoding_binding.cc +++ b/src/encoding_binding.cc @@ -2,10 +2,12 @@ #include "ada.h" #include "env-inl.h" #include "node_buffer.h" +#include "node_debug.h" #include "node_errors.h" #include "node_external_reference.h" #include "simdutf.h" #include "string_bytes.h" +#include "v8-fast-api-calls.h" #include "v8.h" #include @@ -16,7 +18,9 @@ namespace encoding_binding { using v8::ArrayBuffer; using v8::BackingStore; using v8::BackingStoreInitializationMode; +using v8::CFunction; using v8::Context; +using v8::FastApiCallbackOptions; using v8::FunctionCallbackInfo; using v8::HandleScope; using v8::Isolate; @@ -112,6 +116,42 @@ void BindingData::EncodeInto(const FunctionCallbackInfo& args) { binding_data->encode_into_results_buffer_[1] = written; } +void BindingData::FastEncodeInto( + Local receiver, + Local source, + Local dest, + // NOLINTNEXTLINE(runtime/references) This is V8 api. + FastApiCallbackOptions& options) { + TRACK_V8_FAST_API_CALL("encoding_binding.encodeInto"); + CHECK(source->IsString()); + CHECK(dest->IsUint8Array()); + + HandleScope scope(options.isolate); + auto context = options.isolate->GetCurrentContext(); + Realm* realm = Realm::GetCurrent(context); + BindingData* binding_data = realm->GetBindingData(); + + auto source_ = source.As(); + auto dest_ = dest.As(); + Local buf = dest_->Buffer(); + char* write_result = static_cast(buf->Data()) + dest_->ByteOffset(); + size_t dest_length = dest_->ByteLength(); + + size_t nchars; + size_t written = source_->WriteUtf8V2( + options.isolate, + write_result, + dest_length, + String::WriteFlags::kReplaceInvalidUtf8, + &nchars); + + binding_data->encode_into_results_buffer_[0] = nchars; + binding_data->encode_into_results_buffer_[1] = written; +} + +static CFunction fast_encode_into_ = + CFunction::Make(BindingData::FastEncodeInto); + // Encode a single string to a UTF-8 Uint8Array (not Buffer). // Used in TextEncoder.prototype.encode. void BindingData::EncodeUtf8String(const FunctionCallbackInfo& args) { @@ -217,7 +257,7 @@ void BindingData::ToUnicode(const FunctionCallbackInfo& args) { void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data, Local target) { Isolate* isolate = isolate_data->isolate(); - SetMethod(isolate, target, "encodeInto", EncodeInto); + SetFastMethod(isolate, target, "encodeInto", EncodeInto, &fast_encode_into_); SetMethodNoSideEffect(isolate, target, "encodeUtf8String", EncodeUtf8String); SetMethodNoSideEffect(isolate, target, "decodeUTF8", DecodeUTF8); SetMethodNoSideEffect(isolate, target, "toASCII", ToASCII); @@ -236,6 +276,8 @@ void BindingData::CreatePerContextProperties(Local target, void BindingData::RegisterTimerExternalReferences( ExternalReferenceRegistry* registry) { registry->Register(EncodeInto); + registry->Register(FastEncodeInto); + registry->Register(fast_encode_into_.GetTypeInfo()); registry->Register(EncodeUtf8String); registry->Register(DecodeUTF8); registry->Register(ToASCII); diff --git a/src/encoding_binding.h b/src/encoding_binding.h index 97f55394d27641..4f30e19f7dcfc1 100644 --- a/src/encoding_binding.h +++ b/src/encoding_binding.h @@ -29,6 +29,10 @@ class BindingData : public SnapshotableObject { SET_MEMORY_INFO_NAME(BindingData) static void EncodeInto(const v8::FunctionCallbackInfo& args); + static void FastEncodeInto(v8::Local receiver, + v8::Local source, + v8::Local dest, + v8::FastApiCallbackOptions& options); static void EncodeUtf8String(const v8::FunctionCallbackInfo& args); static void DecodeUTF8(const v8::FunctionCallbackInfo& args); static void DecodeLatin1(const v8::FunctionCallbackInfo& args); diff --git a/src/node_external_reference.h b/src/node_external_reference.h index 1ade653aeb4150..c63f1084fe5e3e 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -92,6 +92,13 @@ using CFunctionBufferCopy = uint32_t (*)(v8::Local, uint32_t, v8::FastApiCallbackOptions&); +using CFunctionEncodeInto = + void (*)(v8::Local receiver, + v8::Local source, + v8::Local dest, + // NOLINTNEXTLINE(runtime/references) This is V8 api. + v8::FastApiCallbackOptions& options); + // This class manages the external references from the V8 heap // to the C++ addresses in Node.js. class ExternalReferenceRegistry { @@ -121,6 +128,7 @@ class ExternalReferenceRegistry { V(CFunctionWithBool) \ V(CFunctionBufferCopy) \ V(CFunctionWriteString) \ + V(CFunctionEncodeInto) \ V(const v8::CFunctionInfo*) \ V(v8::FunctionCallback) \ V(v8::AccessorNameGetterCallback) \