Skip to content

Commit d688b8a

Browse files
maclover7BridgeAR
authored andcommitted
src: remove templating from StreamBase
PR-URL: #25142 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 972a0f9 commit d688b8a

12 files changed

+133
-159
lines changed

Diff for: src/js_stream.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ JSStream::JSStream(Environment* env, Local<Object> obj)
2727
: AsyncWrap(env, obj, AsyncWrap::PROVIDER_JSSTREAM),
2828
StreamBase(env) {
2929
MakeWeak();
30+
StreamBase::AttachToObject(obj);
3031
}
3132

3233

@@ -203,15 +204,16 @@ void JSStream::Initialize(Local<Object> target,
203204
Local<String> jsStreamString =
204205
FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream");
205206
t->SetClassName(jsStreamString);
206-
t->InstanceTemplate()->SetInternalFieldCount(1);
207+
t->InstanceTemplate()
208+
->SetInternalFieldCount(StreamBase::kStreamBaseField + 1);
207209
t->Inherit(AsyncWrap::GetConstructorTemplate(env));
208210

209211
env->SetProtoMethod(t, "finishWrite", Finish<WriteWrap>);
210212
env->SetProtoMethod(t, "finishShutdown", Finish<ShutdownWrap>);
211213
env->SetProtoMethod(t, "readBuffer", ReadBuffer);
212214
env->SetProtoMethod(t, "emitEOF", EmitEOF);
213215

214-
StreamBase::AddMethods<JSStream>(env, t);
216+
StreamBase::AddMethods(env, t);
215217
target->Set(env->context(),
216218
jsStreamString,
217219
t->GetFunction(context).ToLocalChecked()).FromJust();

Diff for: src/node_file.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ FileHandle::FileHandle(Environment* env, Local<Object> obj, int fd)
111111
StreamBase(env),
112112
fd_(fd) {
113113
MakeWeak();
114+
StreamBase::AttachToObject(GetObject());
114115
}
115116

116117
FileHandle* FileHandle::New(Environment* env, int fd, Local<Object> obj) {
@@ -2227,11 +2228,11 @@ void Initialize(Local<Object> target,
22272228
env->SetProtoMethod(fd, "close", FileHandle::Close);
22282229
env->SetProtoMethod(fd, "releaseFD", FileHandle::ReleaseFD);
22292230
Local<ObjectTemplate> fdt = fd->InstanceTemplate();
2230-
fdt->SetInternalFieldCount(1);
2231+
fdt->SetInternalFieldCount(StreamBase::kStreamBaseField + 1);
22312232
Local<String> handleString =
22322233
FIXED_ONE_BYTE_STRING(isolate, "FileHandle");
22332234
fd->SetClassName(handleString);
2234-
StreamBase::AddMethods<FileHandle>(env, fd);
2235+
StreamBase::AddMethods(env, fd);
22352236
target
22362237
->Set(context, handleString,
22372238
fd->GetFunction(env->context()).ToLocalChecked())

Diff for: src/node_http2.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,7 @@ Http2Stream::Http2Stream(Http2Session* session,
18681868
id_(id),
18691869
current_headers_category_(category) {
18701870
MakeWeak();
1871+
StreamBase::AttachToObject(GetObject());
18711872
statistics_.start_time = uv_hrtime();
18721873

18731874
// Limit the number of header pairs
@@ -3009,9 +3010,9 @@ void Initialize(Local<Object> target,
30093010
env->SetProtoMethod(stream, "rstStream", Http2Stream::RstStream);
30103011
env->SetProtoMethod(stream, "refreshState", Http2Stream::RefreshState);
30113012
stream->Inherit(AsyncWrap::GetConstructorTemplate(env));
3012-
StreamBase::AddMethods<Http2Stream>(env, stream);
3013+
StreamBase::AddMethods(env, stream);
30133014
Local<ObjectTemplate> streamt = stream->InstanceTemplate();
3014-
streamt->SetInternalFieldCount(1);
3015+
streamt->SetInternalFieldCount(StreamBase::kStreamBaseField + 1);
30153016
env->set_http2stream_constructor_template(streamt);
30163017
target->Set(context,
30173018
FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Stream"),

Diff for: src/pipe_wrap.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ void PipeWrap::Initialize(Local<Object> target,
7474
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
7575
Local<String> pipeString = FIXED_ONE_BYTE_STRING(env->isolate(), "Pipe");
7676
t->SetClassName(pipeString);
77-
t->InstanceTemplate()->SetInternalFieldCount(1);
77+
t->InstanceTemplate()
78+
->SetInternalFieldCount(StreamBase::kStreamBaseField + 1);
7879

7980
t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env));
8081

Diff for: src/stream_base-inl.h

+7-135
Original file line numberDiff line numberDiff line change
@@ -273,144 +273,16 @@ inline WriteWrap* StreamBase::CreateWriteWrap(
273273
return new SimpleWriteWrap<AsyncWrap>(this, object);
274274
}
275275

276-
template <class Base>
277-
void StreamBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
278-
HandleScope scope(env->isolate());
279-
280-
enum PropertyAttribute attributes =
281-
static_cast<PropertyAttribute>(
282-
v8::ReadOnly | v8::DontDelete | v8::DontEnum);
283-
284-
Local<Signature> signature = Signature::New(env->isolate(), t);
285-
286-
Local<FunctionTemplate> get_fd_templ =
287-
env->NewFunctionTemplate(GetFD<Base>,
288-
signature,
289-
v8::ConstructorBehavior::kThrow,
290-
v8::SideEffectType::kHasNoSideEffect);
291-
292-
Local<FunctionTemplate> get_external_templ =
293-
env->NewFunctionTemplate(GetExternal<Base>,
294-
signature,
295-
v8::ConstructorBehavior::kThrow,
296-
v8::SideEffectType::kHasNoSideEffect);
297-
298-
Local<FunctionTemplate> get_bytes_read_templ =
299-
env->NewFunctionTemplate(GetBytesRead<Base>,
300-
signature,
301-
v8::ConstructorBehavior::kThrow,
302-
v8::SideEffectType::kHasNoSideEffect);
303-
304-
Local<FunctionTemplate> get_bytes_written_templ =
305-
env->NewFunctionTemplate(GetBytesWritten<Base>,
306-
signature,
307-
v8::ConstructorBehavior::kThrow,
308-
v8::SideEffectType::kHasNoSideEffect);
309-
310-
t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),
311-
get_fd_templ,
312-
Local<FunctionTemplate>(),
313-
attributes);
314-
315-
t->PrototypeTemplate()->SetAccessorProperty(env->external_stream_string(),
316-
get_external_templ,
317-
Local<FunctionTemplate>(),
318-
attributes);
319-
320-
t->PrototypeTemplate()->SetAccessorProperty(env->bytes_read_string(),
321-
get_bytes_read_templ,
322-
Local<FunctionTemplate>(),
323-
attributes);
324-
325-
t->PrototypeTemplate()->SetAccessorProperty(env->bytes_written_string(),
326-
get_bytes_written_templ,
327-
Local<FunctionTemplate>(),
328-
attributes);
329-
330-
env->SetProtoMethod(t, "readStart", JSMethod<Base, &StreamBase::ReadStartJS>);
331-
env->SetProtoMethod(t, "readStop", JSMethod<Base, &StreamBase::ReadStopJS>);
332-
env->SetProtoMethod(t, "shutdown", JSMethod<Base, &StreamBase::Shutdown>);
333-
env->SetProtoMethod(t, "writev", JSMethod<Base, &StreamBase::Writev>);
334-
env->SetProtoMethod(t,
335-
"writeBuffer",
336-
JSMethod<Base, &StreamBase::WriteBuffer>);
337-
env->SetProtoMethod(t,
338-
"writeAsciiString",
339-
JSMethod<Base, &StreamBase::WriteString<ASCII> >);
340-
env->SetProtoMethod(t,
341-
"writeUtf8String",
342-
JSMethod<Base, &StreamBase::WriteString<UTF8> >);
343-
env->SetProtoMethod(t,
344-
"writeUcs2String",
345-
JSMethod<Base, &StreamBase::WriteString<UCS2> >);
346-
env->SetProtoMethod(t,
347-
"writeLatin1String",
348-
JSMethod<Base, &StreamBase::WriteString<LATIN1> >);
276+
inline void StreamBase::AttachToObject(v8::Local<v8::Object> obj) {
277+
obj->SetAlignedPointerInInternalField(kStreamBaseField, this);
349278
}
350279

280+
inline StreamBase* StreamBase::FromObject(v8::Local<v8::Object> obj) {
281+
if (obj->GetAlignedPointerFromInternalField(0) == nullptr)
282+
return nullptr;
351283

352-
template <class Base>
353-
void StreamBase::GetFD(const FunctionCallbackInfo<Value>& args) {
354-
// Mimic implementation of StreamBase::GetFD() and UDPWrap::GetFD().
355-
Base* handle;
356-
ASSIGN_OR_RETURN_UNWRAP(&handle,
357-
args.This(),
358-
args.GetReturnValue().Set(UV_EINVAL));
359-
360-
StreamBase* wrap = static_cast<StreamBase*>(handle);
361-
if (!wrap->IsAlive())
362-
return args.GetReturnValue().Set(UV_EINVAL);
363-
364-
args.GetReturnValue().Set(wrap->GetFD());
365-
}
366-
367-
template <class Base>
368-
void StreamBase::GetBytesRead(const FunctionCallbackInfo<Value>& args) {
369-
Base* handle;
370-
ASSIGN_OR_RETURN_UNWRAP(&handle,
371-
args.This(),
372-
args.GetReturnValue().Set(0));
373-
374-
StreamBase* wrap = static_cast<StreamBase*>(handle);
375-
// uint64_t -> double. 53bits is enough for all real cases.
376-
args.GetReturnValue().Set(static_cast<double>(wrap->bytes_read_));
377-
}
378-
379-
template <class Base>
380-
void StreamBase::GetBytesWritten(const FunctionCallbackInfo<Value>& args) {
381-
Base* handle;
382-
ASSIGN_OR_RETURN_UNWRAP(&handle,
383-
args.This(),
384-
args.GetReturnValue().Set(0));
385-
386-
StreamBase* wrap = static_cast<StreamBase*>(handle);
387-
// uint64_t -> double. 53bits is enough for all real cases.
388-
args.GetReturnValue().Set(static_cast<double>(wrap->bytes_written_));
389-
}
390-
391-
template <class Base>
392-
void StreamBase::GetExternal(const FunctionCallbackInfo<Value>& args) {
393-
Base* handle;
394-
ASSIGN_OR_RETURN_UNWRAP(&handle, args.This());
395-
396-
StreamBase* wrap = static_cast<StreamBase*>(handle);
397-
Local<External> ext = External::New(args.GetIsolate(), wrap);
398-
args.GetReturnValue().Set(ext);
399-
}
400-
401-
402-
template <class Base,
403-
int (StreamBase::*Method)(const FunctionCallbackInfo<Value>& args)>
404-
void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) {
405-
Base* handle;
406-
ASSIGN_OR_RETURN_UNWRAP(&handle, args.Holder());
407-
408-
StreamBase* wrap = static_cast<StreamBase*>(handle);
409-
if (!wrap->IsAlive())
410-
return args.GetReturnValue().Set(UV_EINVAL);
411-
412-
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(handle);
413-
args.GetReturnValue().Set((wrap->*Method)(args));
284+
return static_cast<StreamBase*>(
285+
obj->GetAlignedPointerFromInternalField(kStreamBaseField));
414286
}
415287

416288

Diff for: src/stream_base.cc

+87
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,93 @@ Local<Object> StreamBase::GetObject() {
327327
return GetAsyncWrap()->object();
328328
}
329329

330+
void StreamBase::AddMethod(Environment* env,
331+
Local<Signature> signature,
332+
enum PropertyAttribute attributes,
333+
Local<FunctionTemplate> t,
334+
JSMethodFunction* stream_method,
335+
Local<String> string) {
336+
Local<FunctionTemplate> templ =
337+
env->NewFunctionTemplate(stream_method,
338+
signature,
339+
v8::ConstructorBehavior::kThrow,
340+
v8::SideEffectType::kHasNoSideEffect);
341+
t->PrototypeTemplate()->SetAccessorProperty(
342+
string, templ, Local<FunctionTemplate>(), attributes);
343+
}
344+
345+
void StreamBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
346+
HandleScope scope(env->isolate());
347+
348+
enum PropertyAttribute attributes = static_cast<PropertyAttribute>(
349+
v8::ReadOnly | v8::DontDelete | v8::DontEnum);
350+
Local<Signature> sig = Signature::New(env->isolate(), t);
351+
352+
AddMethod(env, sig, attributes, t, GetFD, env->fd_string());
353+
AddMethod(
354+
env, sig, attributes, t, GetExternal, env->external_stream_string());
355+
AddMethod(env, sig, attributes, t, GetBytesRead, env->bytes_read_string());
356+
AddMethod(
357+
env, sig, attributes, t, GetBytesWritten, env->bytes_written_string());
358+
env->SetProtoMethod(t, "readStart", JSMethod<&StreamBase::ReadStartJS>);
359+
env->SetProtoMethod(t, "readStop", JSMethod<&StreamBase::ReadStopJS>);
360+
env->SetProtoMethod(t, "shutdown", JSMethod<&StreamBase::Shutdown>);
361+
env->SetProtoMethod(t, "writev", JSMethod<&StreamBase::Writev>);
362+
env->SetProtoMethod(t, "writeBuffer", JSMethod<&StreamBase::WriteBuffer>);
363+
env->SetProtoMethod(
364+
t, "writeAsciiString", JSMethod<&StreamBase::WriteString<ASCII>>);
365+
env->SetProtoMethod(
366+
t, "writeUtf8String", JSMethod<&StreamBase::WriteString<UTF8>>);
367+
env->SetProtoMethod(
368+
t, "writeUcs2String", JSMethod<&StreamBase::WriteString<UCS2>>);
369+
env->SetProtoMethod(
370+
t, "writeLatin1String", JSMethod<&StreamBase::WriteString<LATIN1>>);
371+
}
372+
373+
void StreamBase::GetFD(const FunctionCallbackInfo<Value>& args) {
374+
// Mimic implementation of StreamBase::GetFD() and UDPWrap::GetFD().
375+
StreamBase* wrap = StreamBase::FromObject(args.This().As<Object>());
376+
if (wrap == nullptr) return args.GetReturnValue().Set(UV_EINVAL);
377+
378+
if (!wrap->IsAlive()) return args.GetReturnValue().Set(UV_EINVAL);
379+
380+
args.GetReturnValue().Set(wrap->GetFD());
381+
}
382+
383+
void StreamBase::GetBytesRead(const FunctionCallbackInfo<Value>& args) {
384+
StreamBase* wrap = StreamBase::FromObject(args.This().As<Object>());
385+
if (wrap == nullptr) return args.GetReturnValue().Set(0);
386+
387+
// uint64_t -> double. 53bits is enough for all real cases.
388+
args.GetReturnValue().Set(static_cast<double>(wrap->bytes_read_));
389+
}
390+
391+
void StreamBase::GetBytesWritten(const FunctionCallbackInfo<Value>& args) {
392+
StreamBase* wrap = StreamBase::FromObject(args.This().As<Object>());
393+
if (wrap == nullptr) return args.GetReturnValue().Set(0);
394+
395+
// uint64_t -> double. 53bits is enough for all real cases.
396+
args.GetReturnValue().Set(static_cast<double>(wrap->bytes_written_));
397+
}
398+
399+
void StreamBase::GetExternal(const FunctionCallbackInfo<Value>& args) {
400+
StreamBase* wrap = StreamBase::FromObject(args.This().As<Object>());
401+
if (wrap == nullptr) return;
402+
403+
Local<External> ext = External::New(args.GetIsolate(), wrap);
404+
args.GetReturnValue().Set(ext);
405+
}
406+
407+
template <int (StreamBase::*Method)(const FunctionCallbackInfo<Value>& args)>
408+
void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) {
409+
StreamBase* wrap = StreamBase::FromObject(args.Holder().As<Object>());
410+
if (wrap == nullptr) return;
411+
412+
if (!wrap->IsAlive()) return args.GetReturnValue().Set(UV_EINVAL);
413+
414+
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap->GetAsyncWrap());
415+
args.GetReturnValue().Set((wrap->*Method)(args));
416+
}
330417

331418
int StreamResource::DoTryWrite(uv_buf_t** bufs, size_t* count) {
332419
// No TryWrite by default

Diff for: src/stream_base.h

+14-12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct StreamWriteResult {
2525
size_t bytes;
2626
};
2727

28+
using JSMethodFunction = void(const v8::FunctionCallbackInfo<v8::Value>& args);
2829

2930
class StreamReq {
3031
public:
@@ -259,9 +260,9 @@ class StreamResource {
259260

260261
class StreamBase : public StreamResource {
261262
public:
262-
template <class Base>
263-
static inline void AddMethods(Environment* env,
264-
v8::Local<v8::FunctionTemplate> target);
263+
static constexpr int kStreamBaseField = 1;
264+
static void AddMethods(Environment* env,
265+
v8::Local<v8::FunctionTemplate> target);
265266

266267
virtual bool IsAlive() = 0;
267268
virtual bool IsClosing() = 0;
@@ -305,6 +306,8 @@ class StreamBase : public StreamResource {
305306
virtual AsyncWrap* GetAsyncWrap() = 0;
306307
virtual v8::Local<v8::Object> GetObject();
307308

309+
static StreamBase* FromObject(v8::Local<v8::Object> obj);
310+
308311
protected:
309312
explicit StreamBase(Environment* env);
310313

@@ -317,20 +320,13 @@ class StreamBase : public StreamResource {
317320
template <enum encoding enc>
318321
int WriteString(const v8::FunctionCallbackInfo<v8::Value>& args);
319322

320-
template <class Base>
321323
static void GetFD(const v8::FunctionCallbackInfo<v8::Value>& args);
322-
323-
template <class Base>
324324
static void GetExternal(const v8::FunctionCallbackInfo<v8::Value>& args);
325-
326-
template <class Base>
327325
static void GetBytesRead(const v8::FunctionCallbackInfo<v8::Value>& args);
328-
329-
template <class Base>
330326
static void GetBytesWritten(const v8::FunctionCallbackInfo<v8::Value>& args);
327+
void AttachToObject(v8::Local<v8::Object> obj);
331328

332-
template <class Base,
333-
int (StreamBase::*Method)(
329+
template <int (StreamBase::*Method)(
334330
const v8::FunctionCallbackInfo<v8::Value>& args)>
335331
static void JSMethod(const v8::FunctionCallbackInfo<v8::Value>& args);
336332

@@ -348,6 +344,12 @@ class StreamBase : public StreamResource {
348344
EmitToJSStreamListener default_listener_;
349345

350346
void SetWriteResult(const StreamWriteResult& res);
347+
static void AddMethod(Environment* env,
348+
v8::Local<v8::Signature> sig,
349+
enum v8::PropertyAttribute attributes,
350+
v8::Local<v8::FunctionTemplate> t,
351+
JSMethodFunction* stream_method,
352+
v8::Local<v8::String> str);
351353

352354
friend class WriteWrap;
353355
friend class ShutdownWrap;

0 commit comments

Comments
 (0)