2121
2222#include " node.h"
2323#include " node_buffer.h"
24+ #include " node_debug.h"
2425#include " util.h"
2526
2627#include " async_wrap-inl.h"
@@ -52,6 +53,7 @@ namespace http_parser { // NOLINT(build/namespaces)
5253
5354using v8::Array;
5455using v8::Boolean;
56+ using v8::CFunction;
5557using v8::Context;
5658using v8::EscapableHandleScope;
5759using v8::Exception;
@@ -604,30 +606,49 @@ class Parser : public AsyncWrap, public StreamListener {
604606 new Parser (binding_data, args.This ());
605607 }
606608
607- // TODO(@anonrig): Add V8 Fast API
609+ // NOTE: Close() deletes the parser object, which is not safe in Fast API
610+ // because the calling convention assumes the receiver remains valid.
608611 static void Close (const FunctionCallbackInfo<Value>& args) {
609612 Parser* parser;
610613 ASSIGN_OR_RETURN_UNWRAP (&parser, args.This ());
611614
612615 delete parser;
613616 }
614617
615- // TODO(@anonrig): Add V8 Fast API
616618 static void Free (const FunctionCallbackInfo<Value>& args) {
617619 Parser* parser;
618620 ASSIGN_OR_RETURN_UNWRAP (&parser, args.This ());
621+ FreeImpl (parser);
622+ }
623+
624+ static void FastFree (Local<Object> receiver) {
625+ TRACK_V8_FAST_API_CALL (" http_parser.free" );
626+ Parser* parser;
627+ ASSIGN_OR_RETURN_UNWRAP (&parser, receiver);
628+ FreeImpl (parser);
629+ }
619630
631+ static void FreeImpl (Parser* parser) {
620632 // Since the Parser destructor isn't going to run the destroy() callbacks
621633 // it needs to be triggered manually.
622634 parser->EmitTraceEventDestroy ();
623635 parser->EmitDestroy ();
624636 }
625637
626- // TODO(@anonrig): Add V8 Fast API
627638 static void Remove (const FunctionCallbackInfo<Value>& args) {
628639 Parser* parser;
629640 ASSIGN_OR_RETURN_UNWRAP (&parser, args.This ());
641+ RemoveImpl (parser);
642+ }
643+
644+ static void FastRemove (Local<Object> receiver) {
645+ TRACK_V8_FAST_API_CALL (" http_parser.remove" );
646+ Parser* parser;
647+ ASSIGN_OR_RETURN_UNWRAP (&parser, receiver);
648+ RemoveImpl (parser);
649+ }
630650
651+ static void RemoveImpl (Parser* parser) {
631652 if (parser->connectionsList_ != nullptr ) {
632653 parser->connectionsList_ ->Pop (parser);
633654 parser->connectionsList_ ->PopActive (parser);
@@ -736,23 +757,39 @@ class Parser : public AsyncWrap, public StreamListener {
736757 }
737758 }
738759
739- // TODO(@anonrig): Add V8 Fast API
740760 template <bool should_pause>
741761 static void Pause (const FunctionCallbackInfo<Value>& args) {
742762 Environment* env = Environment::GetCurrent (args);
743763 Parser* parser;
744764 ASSIGN_OR_RETURN_UNWRAP (&parser, args.This ());
745765 // Should always be called from the same context.
746766 CHECK_EQ (env, parser->env ());
767+ PauseImpl<should_pause>(parser);
768+ }
769+
770+ template <bool should_pause>
771+ static void FastPause (Local<Object> receiver) {
772+ if constexpr (should_pause) {
773+ TRACK_V8_FAST_API_CALL (" http_parser.pause" );
774+ } else {
775+ TRACK_V8_FAST_API_CALL (" http_parser.resume" );
776+ }
777+ Parser* parser;
778+ ASSIGN_OR_RETURN_UNWRAP (&parser, receiver);
779+ PauseImpl<should_pause>(parser);
780+ }
747781
782+ template <bool should_pause>
783+ static void PauseImpl (Parser* parser) {
748784 if constexpr (should_pause) {
749785 llhttp_pause (&parser->parser_ );
750786 } else {
751787 llhttp_resume (&parser->parser_ );
752788 }
753789 }
754790
755- // TODO(@anonrig): Add V8 Fast API
791+ // NOTE: Consume() requires unwrapping a StreamBase from a JS object argument,
792+ // which involves V8 API calls that are not supported in Fast API.
756793 static void Consume (const FunctionCallbackInfo<Value>& args) {
757794 Parser* parser;
758795 ASSIGN_OR_RETURN_UNWRAP (&parser, args.This ());
@@ -762,11 +799,20 @@ class Parser : public AsyncWrap, public StreamListener {
762799 stream->PushStreamListener (parser);
763800 }
764801
765- // TODO(@anonrig): Add V8 Fast API
766802 static void Unconsume (const FunctionCallbackInfo<Value>& args) {
767803 Parser* parser;
768804 ASSIGN_OR_RETURN_UNWRAP (&parser, args.This ());
805+ UnconsumeImpl (parser);
806+ }
769807
808+ static void FastUnconsume (Local<Object> receiver) {
809+ TRACK_V8_FAST_API_CALL (" http_parser.unconsume" );
810+ Parser* parser;
811+ ASSIGN_OR_RETURN_UNWRAP (&parser, receiver);
812+ UnconsumeImpl (parser);
813+ }
814+
815+ static void UnconsumeImpl (Parser* parser) {
770816 // Already unconsumed
771817 if (parser->stream_ == nullptr )
772818 return ;
@@ -1086,9 +1132,22 @@ class Parser : public AsyncWrap, public StreamListener {
10861132 typedef int (Parser::*Call)();
10871133 typedef int (Parser::*DataCall)(const char * at, size_t length);
10881134
1135+ public:
10891136 static const llhttp_settings_t settings;
1137+
1138+ static CFunction fast_free_;
1139+ static CFunction fast_remove_;
1140+ static CFunction fast_pause_;
1141+ static CFunction fast_resume_;
1142+ static CFunction fast_unconsume_;
10901143};
10911144
1145+ CFunction Parser::fast_free_ (CFunction::Make(Parser::FastFree));
1146+ CFunction Parser::fast_remove_ (CFunction::Make(Parser::FastRemove));
1147+ CFunction Parser::fast_pause_ (CFunction::Make(Parser::FastPause<true >));
1148+ CFunction Parser::fast_resume_ (CFunction::Make(Parser::FastPause<false >));
1149+ CFunction Parser::fast_unconsume_ (CFunction::Make(Parser::FastUnconsume));
1150+
10921151bool ParserComparator::operator ()(const Parser* lhs, const Parser* rhs) const {
10931152 if (lhs->last_message_start_ == 0 && rhs->last_message_start_ == 0 ) {
10941153 // When both parsers are idle, guarantee strict order by
@@ -1330,16 +1389,30 @@ void CreatePerIsolateProperties(IsolateData* isolate_data,
13301389 Integer::NewFromUnsigned (isolate, kLenientAll ));
13311390
13321391 t->Inherit (AsyncWrap::GetConstructorTemplate (isolate_data));
1392+ Local<ObjectTemplate> instance = t->InstanceTemplate ();
13331393 SetProtoMethod (isolate, t, " close" , Parser::Close);
1334- SetProtoMethod (isolate, t, " free" , Parser::Free);
1335- SetProtoMethod (isolate, t, " remove" , Parser::Remove);
1394+ SetFastMethod (isolate, instance, " free" , Parser::Free, &Parser::fast_free_);
1395+ SetFastMethod (
1396+ isolate, instance, " remove" , Parser::Remove, &Parser::fast_remove_);
13361397 SetProtoMethod (isolate, t, " execute" , Parser::Execute);
13371398 SetProtoMethod (isolate, t, " finish" , Parser::Finish);
13381399 SetProtoMethod (isolate, t, " initialize" , Parser::Initialize);
1339- SetProtoMethod (isolate, t, " pause" , Parser::Pause<true >);
1340- SetProtoMethod (isolate, t, " resume" , Parser::Pause<false >);
1400+ SetFastMethod (isolate,
1401+ instance,
1402+ " pause" ,
1403+ Parser::Pause<true >,
1404+ &Parser::fast_pause_);
1405+ SetFastMethod (isolate,
1406+ instance,
1407+ " resume" ,
1408+ Parser::Pause<false >,
1409+ &Parser::fast_resume_);
13411410 SetProtoMethod (isolate, t, " consume" , Parser::Consume);
1342- SetProtoMethod (isolate, t, " unconsume" , Parser::Unconsume);
1411+ SetFastMethod (isolate,
1412+ instance,
1413+ " unconsume" ,
1414+ Parser::Unconsume,
1415+ &Parser::fast_unconsume_);
13431416 SetProtoMethod (isolate, t, " getCurrentBuffer" , Parser::GetCurrentBuffer);
13441417
13451418 SetConstructorFunction (isolate, target, " HTTPParser" , t);
@@ -1401,14 +1474,19 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
14011474 registry->Register (Parser::New);
14021475 registry->Register (Parser::Close);
14031476 registry->Register (Parser::Free);
1477+ registry->Register (Parser::fast_free_);
14041478 registry->Register (Parser::Remove);
1479+ registry->Register (Parser::fast_remove_);
14051480 registry->Register (Parser::Execute);
14061481 registry->Register (Parser::Finish);
14071482 registry->Register (Parser::Initialize);
14081483 registry->Register (Parser::Pause<true >);
1484+ registry->Register (Parser::fast_pause_);
14091485 registry->Register (Parser::Pause<false >);
1486+ registry->Register (Parser::fast_resume_);
14101487 registry->Register (Parser::Consume);
14111488 registry->Register (Parser::Unconsume);
1489+ registry->Register (Parser::fast_unconsume_);
14121490 registry->Register (Parser::GetCurrentBuffer);
14131491 registry->Register (ConnectionsList::New);
14141492 registry->Register (ConnectionsList::All);
0 commit comments