Skip to content

Commit 4e4d1de

Browse files
joyeecheungRafaelGSS
authored andcommitted
src: refactor http parser binding initialization
- Use the per-isolate template to build constants and functions which is faster - Use Array::New() with prebuilt vectors which is faster - Register external references so the binding can be included in the snapshot PR-URL: #54276 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Paolo Insogna <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ethan Arrowood <[email protected]>
1 parent 409d9eb commit 4e4d1de

File tree

3 files changed

+128
-93
lines changed

3 files changed

+128
-93
lines changed

src/node_binding.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ static_assert(static_cast<int>(NM_F_LINKED) ==
4444
V(encoding_binding) \
4545
V(fs) \
4646
V(fs_dir) \
47+
V(http_parser) \
4748
V(messaging) \
4849
V(mksnapshot) \
4950
V(modules) \

src/node_external_reference.h

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class ExternalReferenceRegistry {
141141
V(fs_event_wrap) \
142142
V(handle_wrap) \
143143
V(heap_utils) \
144+
V(http_parser) \
144145
V(internal_only_v8) \
145146
V(messaging) \
146147
V(mksnapshot) \

src/node_http_parser.cc

+126-93
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@
2525

2626
#include "async_wrap-inl.h"
2727
#include "env-inl.h"
28+
#include "llhttp.h"
2829
#include "memory_tracker-inl.h"
30+
#include "node_external_reference.h"
2931
#include "stream_base-inl.h"
3032
#include "v8.h"
31-
#include "llhttp.h"
3233

3334
#include <cstdlib> // free()
3435
#include <cstring> // strdup(), strchr()
@@ -47,7 +48,7 @@
4748

4849

4950
namespace node {
50-
namespace { // NOLINT(build/namespaces)
51+
namespace http_parser { // NOLINT(build/namespaces)
5152

5253
using v8::Array;
5354
using v8::Boolean;
@@ -65,6 +66,7 @@ using v8::Local;
6566
using v8::MaybeLocal;
6667
using v8::Number;
6768
using v8::Object;
69+
using v8::ObjectTemplate;
6870
using v8::String;
6971
using v8::Uint32;
7072
using v8::Undefined;
@@ -1243,97 +1245,59 @@ const llhttp_settings_t Parser::settings = {
12431245
nullptr,
12441246
};
12451247

1246-
void InitializeHttpParser(Local<Object> target,
1247-
Local<Value> unused,
1248-
Local<Context> context,
1249-
void* priv) {
1250-
Realm* realm = Realm::GetCurrent(context);
1251-
Environment* env = realm->env();
1252-
Isolate* isolate = env->isolate();
1253-
BindingData* const binding_data = realm->AddBindingData<BindingData>(target);
1254-
if (binding_data == nullptr) return;
1248+
void CreatePerIsolateProperties(IsolateData* isolate_data,
1249+
Local<ObjectTemplate> target) {
1250+
Isolate* isolate = isolate_data->isolate();
12551251

12561252
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, Parser::New);
12571253
t->InstanceTemplate()->SetInternalFieldCount(Parser::kInternalFieldCount);
12581254

1259-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "REQUEST"),
1260-
Integer::New(env->isolate(), HTTP_REQUEST));
1261-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "RESPONSE"),
1262-
Integer::New(env->isolate(), HTTP_RESPONSE));
1263-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageBegin"),
1264-
Integer::NewFromUnsigned(env->isolate(), kOnMessageBegin));
1265-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeaders"),
1266-
Integer::NewFromUnsigned(env->isolate(), kOnHeaders));
1267-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnHeadersComplete"),
1268-
Integer::NewFromUnsigned(env->isolate(), kOnHeadersComplete));
1269-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnBody"),
1270-
Integer::NewFromUnsigned(env->isolate(), kOnBody));
1271-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnMessageComplete"),
1272-
Integer::NewFromUnsigned(env->isolate(), kOnMessageComplete));
1273-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnExecute"),
1274-
Integer::NewFromUnsigned(env->isolate(), kOnExecute));
1275-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnTimeout"),
1276-
Integer::NewFromUnsigned(env->isolate(), kOnTimeout));
1277-
1278-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientNone"),
1279-
Integer::NewFromUnsigned(env->isolate(), kLenientNone));
1280-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientHeaders"),
1281-
Integer::NewFromUnsigned(env->isolate(), kLenientHeaders));
1282-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientChunkedLength"),
1283-
Integer::NewFromUnsigned(env->isolate(), kLenientChunkedLength));
1284-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientKeepAlive"),
1285-
Integer::NewFromUnsigned(env->isolate(), kLenientKeepAlive));
1286-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientTransferEncoding"),
1287-
Integer::NewFromUnsigned(env->isolate(), kLenientTransferEncoding));
1288-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientVersion"),
1289-
Integer::NewFromUnsigned(env->isolate(), kLenientVersion));
1290-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientDataAfterClose"),
1291-
Integer::NewFromUnsigned(env->isolate(), kLenientDataAfterClose));
1292-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientOptionalLFAfterCR"),
1293-
Integer::NewFromUnsigned(env->isolate(), kLenientOptionalLFAfterCR));
1294-
t->Set(
1295-
FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientOptionalCRLFAfterChunk"),
1296-
Integer::NewFromUnsigned(env->isolate(), kLenientOptionalCRLFAfterChunk));
1297-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientOptionalCRBeforeLF"),
1298-
Integer::NewFromUnsigned(env->isolate(), kLenientOptionalCRBeforeLF));
1299-
t->Set(
1300-
FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientSpacesAfterChunkSize"),
1301-
Integer::NewFromUnsigned(env->isolate(), kLenientSpacesAfterChunkSize));
1302-
1303-
t->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kLenientAll"),
1304-
Integer::NewFromUnsigned(env->isolate(), kLenientAll));
1305-
1306-
Local<Array> methods = Array::New(env->isolate());
1307-
Local<Array> all_methods = Array::New(env->isolate());
1308-
size_t method_index = -1;
1309-
size_t all_method_index = -1;
1310-
#define V(num, name, string) \
1311-
methods \
1312-
->Set(env->context(), \
1313-
++method_index, \
1314-
FIXED_ONE_BYTE_STRING(env->isolate(), #string)) \
1315-
.Check();
1316-
HTTP_METHOD_MAP(V)
1317-
#undef V
1318-
#define V(num, name, string) \
1319-
all_methods \
1320-
->Set(env->context(), \
1321-
++all_method_index, \
1322-
FIXED_ONE_BYTE_STRING(env->isolate(), #string)) \
1323-
.Check();
1324-
HTTP_ALL_METHOD_MAP(V)
1325-
#undef V
1326-
1327-
target->Set(env->context(),
1328-
FIXED_ONE_BYTE_STRING(env->isolate(), "methods"),
1329-
methods).Check();
1330-
target
1331-
->Set(env->context(),
1332-
FIXED_ONE_BYTE_STRING(env->isolate(), "allMethods"),
1333-
all_methods)
1334-
.Check();
1335-
1336-
t->Inherit(AsyncWrap::GetConstructorTemplate(env));
1255+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "REQUEST"),
1256+
Integer::New(isolate, HTTP_REQUEST));
1257+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "RESPONSE"),
1258+
Integer::New(isolate, HTTP_RESPONSE));
1259+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kOnMessageBegin"),
1260+
Integer::NewFromUnsigned(isolate, kOnMessageBegin));
1261+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kOnHeaders"),
1262+
Integer::NewFromUnsigned(isolate, kOnHeaders));
1263+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kOnHeadersComplete"),
1264+
Integer::NewFromUnsigned(isolate, kOnHeadersComplete));
1265+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kOnBody"),
1266+
Integer::NewFromUnsigned(isolate, kOnBody));
1267+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kOnMessageComplete"),
1268+
Integer::NewFromUnsigned(isolate, kOnMessageComplete));
1269+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kOnExecute"),
1270+
Integer::NewFromUnsigned(isolate, kOnExecute));
1271+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kOnTimeout"),
1272+
Integer::NewFromUnsigned(isolate, kOnTimeout));
1273+
1274+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientNone"),
1275+
Integer::NewFromUnsigned(isolate, kLenientNone));
1276+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientHeaders"),
1277+
Integer::NewFromUnsigned(isolate, kLenientHeaders));
1278+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientChunkedLength"),
1279+
Integer::NewFromUnsigned(isolate, kLenientChunkedLength));
1280+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientKeepAlive"),
1281+
Integer::NewFromUnsigned(isolate, kLenientKeepAlive));
1282+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientTransferEncoding"),
1283+
Integer::NewFromUnsigned(isolate, kLenientTransferEncoding));
1284+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientVersion"),
1285+
Integer::NewFromUnsigned(isolate, kLenientVersion));
1286+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientDataAfterClose"),
1287+
Integer::NewFromUnsigned(isolate, kLenientDataAfterClose));
1288+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientOptionalLFAfterCR"),
1289+
Integer::NewFromUnsigned(isolate, kLenientOptionalLFAfterCR));
1290+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientOptionalCRLFAfterChunk"),
1291+
Integer::NewFromUnsigned(isolate, kLenientOptionalCRLFAfterChunk));
1292+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientOptionalCRBeforeLF"),
1293+
Integer::NewFromUnsigned(isolate, kLenientOptionalCRBeforeLF));
1294+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientSpacesAfterChunkSize"),
1295+
Integer::NewFromUnsigned(isolate, kLenientSpacesAfterChunkSize));
1296+
1297+
t->Set(FIXED_ONE_BYTE_STRING(isolate, "kLenientAll"),
1298+
Integer::NewFromUnsigned(isolate, kLenientAll));
1299+
1300+
t->Inherit(AsyncWrap::GetConstructorTemplate(isolate_data));
13371301
SetProtoMethod(isolate, t, "close", Parser::Close);
13381302
SetProtoMethod(isolate, t, "free", Parser::Free);
13391303
SetProtoMethod(isolate, t, "remove", Parser::Remove);
@@ -1348,7 +1312,7 @@ void InitializeHttpParser(Local<Object> target,
13481312
SetProtoMethod(isolate, t, "duration", Parser::Duration);
13491313
SetProtoMethod(isolate, t, "headersCompleted", Parser::HeadersCompleted);
13501314

1351-
SetConstructorFunction(context, target, "HTTPParser", t);
1315+
SetConstructorFunction(isolate, target, "HTTPParser", t);
13521316

13531317
Local<FunctionTemplate> c =
13541318
NewFunctionTemplate(isolate, ConnectionsList::New);
@@ -1358,10 +1322,79 @@ void InitializeHttpParser(Local<Object> target,
13581322
SetProtoMethod(isolate, c, "idle", ConnectionsList::Idle);
13591323
SetProtoMethod(isolate, c, "active", ConnectionsList::Active);
13601324
SetProtoMethod(isolate, c, "expired", ConnectionsList::Expired);
1361-
SetConstructorFunction(context, target, "ConnectionsList", c);
1325+
SetConstructorFunction(isolate, target, "ConnectionsList", c);
1326+
}
1327+
1328+
void CreatePerContextProperties(Local<Object> target,
1329+
Local<Value> unused,
1330+
Local<Context> context,
1331+
void* priv) {
1332+
Realm* realm = Realm::GetCurrent(context);
1333+
Environment* env = realm->env();
1334+
Isolate* isolate = env->isolate();
1335+
BindingData* const binding_data = realm->AddBindingData<BindingData>(target);
1336+
if (binding_data == nullptr) return;
1337+
1338+
std::vector<Local<Value>> methods_val;
1339+
std::vector<Local<Value>> all_methods_val;
1340+
1341+
#define V(num, name, string) \
1342+
methods_val.push_back(FIXED_ONE_BYTE_STRING(isolate, #string));
1343+
HTTP_METHOD_MAP(V)
1344+
#undef V
1345+
#define V(num, name, string) \
1346+
all_methods_val.push_back(FIXED_ONE_BYTE_STRING(isolate, #string));
1347+
HTTP_ALL_METHOD_MAP(V)
1348+
#undef V
1349+
1350+
Local<Array> methods =
1351+
Array::New(isolate, methods_val.data(), methods_val.size());
1352+
Local<Array> all_methods =
1353+
Array::New(isolate, all_methods_val.data(), all_methods_val.size());
1354+
if (!target
1355+
->Set(env->context(),
1356+
FIXED_ONE_BYTE_STRING(isolate, "methods"),
1357+
methods)
1358+
.IsJust()) {
1359+
return;
1360+
}
1361+
if (target
1362+
->Set(env->context(),
1363+
FIXED_ONE_BYTE_STRING(isolate, "allMethods"),
1364+
all_methods)
1365+
.IsJust()) {
1366+
return;
1367+
}
1368+
}
1369+
1370+
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1371+
registry->Register(Parser::New);
1372+
registry->Register(Parser::Close);
1373+
registry->Register(Parser::Free);
1374+
registry->Register(Parser::Remove);
1375+
registry->Register(Parser::Execute);
1376+
registry->Register(Parser::Finish);
1377+
registry->Register(Parser::Initialize);
1378+
registry->Register(Parser::Pause<true>);
1379+
registry->Register(Parser::Pause<false>);
1380+
registry->Register(Parser::Consume);
1381+
registry->Register(Parser::Unconsume);
1382+
registry->Register(Parser::GetCurrentBuffer);
1383+
registry->Register(Parser::Duration);
1384+
registry->Register(Parser::HeadersCompleted);
1385+
registry->Register(ConnectionsList::New);
1386+
registry->Register(ConnectionsList::All);
1387+
registry->Register(ConnectionsList::Idle);
1388+
registry->Register(ConnectionsList::Active);
1389+
registry->Register(ConnectionsList::Expired);
13621390
}
13631391

1364-
} // anonymous namespace
1392+
} // namespace http_parser
13651393
} // namespace node
13661394

1367-
NODE_BINDING_CONTEXT_AWARE_INTERNAL(http_parser, node::InitializeHttpParser)
1395+
NODE_BINDING_CONTEXT_AWARE_INTERNAL(
1396+
http_parser, node::http_parser::CreatePerContextProperties)
1397+
NODE_BINDING_PER_ISOLATE_INIT(http_parser,
1398+
node::http_parser::CreatePerIsolateProperties)
1399+
NODE_BINDING_EXTERNAL_REFERENCE(http_parser,
1400+
node::http_parser::RegisterExternalReferences)

0 commit comments

Comments
 (0)