diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index b7d3ef9ae6da..d8dc327f3711 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -1708,12 +1708,13 @@ void NativeKeyObject::CreateNativeKeyObjectClass( Local callback = args[0]; CHECK(callback->IsFunction()); - Local t = - NewFunctionTemplate(isolate, NativeKeyObject::New); - t->InstanceTemplate()->SetInternalFieldCount( - NativeKeyObject::kInternalFieldCount); - CHECK(env->crypto_key_object_constructor_template().IsEmpty()); - env->set_crypto_key_object_constructor_template(t); + Local t = env->crypto_key_object_constructor_template(); + if (t.IsEmpty()) { + t = NewFunctionTemplate(isolate, NativeKeyObject::New); + t->InstanceTemplate()->SetInternalFieldCount( + NativeKeyObject::kInternalFieldCount); + env->set_crypto_key_object_constructor_template(t); + } Local ctor; if (!t->GetFunction(env->context()).ToLocal(&ctor)) @@ -1945,12 +1946,13 @@ void NativeCryptoKey::CreateCryptoKeyClass( Local callback = args[0]; CHECK(callback->IsFunction()); - Local t = - NewFunctionTemplate(isolate, NativeCryptoKey::New); - t->InstanceTemplate()->SetInternalFieldCount( - NativeCryptoKey::kInternalFieldCount); - CHECK(env->crypto_cryptokey_constructor_template().IsEmpty()); - env->set_crypto_cryptokey_constructor_template(t); + Local t = env->crypto_cryptokey_constructor_template(); + if (t.IsEmpty()) { + t = NewFunctionTemplate(isolate, NativeCryptoKey::New); + t->InstanceTemplate()->SetInternalFieldCount( + NativeCryptoKey::kInternalFieldCount); + env->set_crypto_cryptokey_constructor_template(t); + } Local ctor; if (!t->GetFunction(env->context()).ToLocal(&ctor)) return; diff --git a/src/dtls/dtls_context.cc b/src/dtls/dtls_context.cc index b5ee22fb6475..b3f40a16abcc 100644 --- a/src/dtls/dtls_context.cc +++ b/src/dtls/dtls_context.cc @@ -106,8 +106,11 @@ Local DTLSContext::GetConstructorTemplate(Environment* env) { void DTLSContext::InitPerContext(Local target, Local context, Environment* env) { - SetConstructorFunction( - context, target, "DTLSContext", GetConstructorTemplate(env)); + SetConstructorFunction(context, + target, + "DTLSContext", + GetConstructorTemplate(env), + SetConstructorFunctionFlag::NONE); } void DTLSContext::RegisterExternalReferences( diff --git a/src/dtls/dtls_endpoint.cc b/src/dtls/dtls_endpoint.cc index 44279399e478..dff59e7df5c9 100644 --- a/src/dtls/dtls_endpoint.cc +++ b/src/dtls/dtls_endpoint.cc @@ -102,8 +102,11 @@ Local DTLSEndpoint::GetConstructorTemplate(Environment* env) { void DTLSEndpoint::InitPerContext(Local target, Local context, Environment* env) { - SetConstructorFunction( - context, target, "DTLSEndpoint", GetConstructorTemplate(env)); + SetConstructorFunction(context, + target, + "DTLSEndpoint", + GetConstructorTemplate(env), + SetConstructorFunctionFlag::NONE); } void DTLSEndpoint::RegisterExternalReferences( diff --git a/src/dtls/dtls_session.cc b/src/dtls/dtls_session.cc index bd4034414414..e6550b310ee1 100644 --- a/src/dtls/dtls_session.cc +++ b/src/dtls/dtls_session.cc @@ -131,8 +131,11 @@ Local DTLSSession::GetConstructorTemplate(Environment* env) { void DTLSSession::InitPerContext(Local target, Local context, Environment* env) { - SetConstructorFunction( - context, target, "DTLSSession", GetConstructorTemplate(env)); + SetConstructorFunction(context, + target, + "DTLSSession", + GetConstructorTemplate(env), + SetConstructorFunctionFlag::NONE); } void DTLSSession::RegisterExternalReferences( diff --git a/src/env_properties.h b/src/env_properties.h index 4838d25910ab..3e7fb2c20d9b 100644 --- a/src/env_properties.h +++ b/src/env_properties.h @@ -454,7 +454,7 @@ V(v8_heap_statistics_template, v8::DictionaryTemplate) \ V(histogram_ctor_template, v8::FunctionTemplate) \ V(http2settings_constructor_template, v8::ObjectTemplate) \ - V(http2stream_constructor_template, v8::ObjectTemplate) \ + V(http2stream_constructor_template, v8::FunctionTemplate) \ V(http2ping_constructor_template, v8::ObjectTemplate) \ V(i18n_converter_template, v8::ObjectTemplate) \ V(intervalhistogram_constructor_template, v8::FunctionTemplate) \ @@ -475,7 +475,7 @@ V(pipe_constructor_template, v8::FunctionTemplate) \ V(script_context_constructor_template, v8::FunctionTemplate) \ V(secure_context_constructor_template, v8::FunctionTemplate) \ - V(shutdown_wrap_template, v8::ObjectTemplate) \ + V(shutdown_wrap_template, v8::FunctionTemplate) \ V(soa_record_template, v8::DictionaryTemplate) \ V(socketaddress_constructor_template, v8::FunctionTemplate) \ V(space_stats_template, v8::DictionaryTemplate) \ @@ -494,7 +494,7 @@ V(urlpatterncomponentresult_template, v8::DictionaryTemplate) \ V(urlpatterninit_template, v8::DictionaryTemplate) \ V(urlpatternresult_template, v8::DictionaryTemplate) \ - V(write_wrap_template, v8::ObjectTemplate) \ + V(write_wrap_template, v8::FunctionTemplate) \ V(worker_cpu_profile_taker_template, v8::ObjectTemplate) \ V(worker_cpu_usage_taker_template, v8::ObjectTemplate) \ V(worker_heap_profile_taker_template, v8::ObjectTemplate) \ diff --git a/src/node_ffi.cc b/src/node_ffi.cc index 88327f1f1c47..2555e0aa7968 100644 --- a/src/node_ffi.cc +++ b/src/node_ffi.cc @@ -1237,6 +1237,7 @@ Local DynamicLibrary::GetConstructorTemplate( static_cast(ReadOnly | DontDelete); tmpl = NewFunctionTemplate(isolate, DynamicLibrary::New); + tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "DynamicLibrary")); tmpl->InstanceTemplate()->SetInternalFieldCount( DynamicLibrary::kInternalFieldCount); Local signature = Signature::New(isolate, tmpl); @@ -1308,7 +1309,11 @@ static void Initialize(Local target, // Create the DynamicLibrary template Local dl_tmpl = DynamicLibrary::GetConstructorTemplate(env); - SetConstructorFunction(context, target, "DynamicLibrary", dl_tmpl); + SetConstructorFunction(context, + target, + "DynamicLibrary", + dl_tmpl, + SetConstructorFunctionFlag::NONE); SetMethod(context, target, "toString", ToString); SetMethod(context, target, "toBuffer", ToBuffer); SetMethod(context, target, "toArrayBuffer", ToArrayBuffer); diff --git a/src/node_http2.cc b/src/node_http2.cc index f5018d10d7ee..83cc63e1a6ec 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -2264,6 +2264,7 @@ Http2Stream* Http2Stream::New(Http2Session* session, Local obj; if (!session->env() ->http2stream_constructor_template() + ->InstanceTemplate() ->NewInstance(session->env()->context()) .ToLocal(&obj)) { return nullptr; @@ -3614,37 +3615,48 @@ void Initialize(Local target, SetMethod(context, target, "packSettings", PackSettings); SetMethod(context, target, "setCallbackFunctions", SetCallbackFunctions); - Local ping = FunctionTemplate::New(env->isolate()); - ping->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Ping")); - ping->Inherit(AsyncWrap::GetConstructorTemplate(env)); - Local pingt = ping->InstanceTemplate(); - pingt->SetInternalFieldCount(Http2Ping::kInternalFieldCount); - env->set_http2ping_constructor_template(pingt); - - Local setting = FunctionTemplate::New(env->isolate()); - setting->Inherit(AsyncWrap::GetConstructorTemplate(env)); - Local settingt = setting->InstanceTemplate(); - settingt->SetInternalFieldCount(Http2Settings::kInternalFieldCount); - env->set_http2settings_constructor_template(settingt); - - Local stream = FunctionTemplate::New(env->isolate()); - SetProtoMethod(isolate, stream, "id", Http2Stream::GetID); - SetProtoMethod(isolate, stream, "destroy", Http2Stream::Destroy); - SetProtoMethod(isolate, stream, "priority", Http2Stream::Priority); - SetProtoMethod(isolate, stream, "pushPromise", Http2Stream::PushPromise); - SetProtoMethod(isolate, stream, "info", Http2Stream::Info); - SetProtoMethod(isolate, stream, "trailers", Http2Stream::Trailers); - SetProtoMethod( - isolate, stream, "disableAutoTrailers", Http2Stream::DisableAutoTrailers); - SetProtoMethod(isolate, stream, "respond", Http2Stream::Respond); - SetProtoMethod(isolate, stream, "rstStream", Http2Stream::RstStream); - SetProtoMethod(isolate, stream, "refreshState", Http2Stream::RefreshState); - stream->Inherit(AsyncWrap::GetConstructorTemplate(env)); - StreamBase::AddMethods(env, stream); - Local streamt = stream->InstanceTemplate(); - streamt->SetInternalFieldCount(Http2Stream::kInternalFieldCount); - env->set_http2stream_constructor_template(streamt); - SetConstructorFunction(context, target, "Http2Stream", stream); + if (env->http2ping_constructor_template().IsEmpty()) { + Local ping = FunctionTemplate::New(env->isolate()); + ping->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Ping")); + ping->Inherit(AsyncWrap::GetConstructorTemplate(env)); + Local pingt = ping->InstanceTemplate(); + pingt->SetInternalFieldCount(Http2Ping::kInternalFieldCount); + env->set_http2ping_constructor_template(pingt); + } + + if (env->http2settings_constructor_template().IsEmpty()) { + Local setting = FunctionTemplate::New(env->isolate()); + setting->Inherit(AsyncWrap::GetConstructorTemplate(env)); + Local settingt = setting->InstanceTemplate(); + settingt->SetInternalFieldCount(Http2Settings::kInternalFieldCount); + env->set_http2settings_constructor_template(settingt); + } + + Local stream = env->http2stream_constructor_template(); + if (stream.IsEmpty()) { + stream = FunctionTemplate::New(env->isolate()); + SetProtoMethod(isolate, stream, "id", Http2Stream::GetID); + SetProtoMethod(isolate, stream, "destroy", Http2Stream::Destroy); + SetProtoMethod(isolate, stream, "priority", Http2Stream::Priority); + SetProtoMethod(isolate, stream, "pushPromise", Http2Stream::PushPromise); + SetProtoMethod(isolate, stream, "info", Http2Stream::Info); + SetProtoMethod(isolate, stream, "trailers", Http2Stream::Trailers); + SetProtoMethod(isolate, + stream, + "disableAutoTrailers", + Http2Stream::DisableAutoTrailers); + SetProtoMethod(isolate, stream, "respond", Http2Stream::Respond); + SetProtoMethod(isolate, stream, "rstStream", Http2Stream::RstStream); + SetProtoMethod(isolate, stream, "refreshState", Http2Stream::RefreshState); + stream->Inherit(AsyncWrap::GetConstructorTemplate(env)); + StreamBase::AddMethods(env, stream); + stream->InstanceTemplate()->SetInternalFieldCount( + Http2Stream::kInternalFieldCount); + stream->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "Http2Stream")); + env->set_http2stream_constructor_template(stream); + } + SetConstructorFunction( + context, target, "Http2Stream", stream, SetConstructorFunctionFlag::NONE); Local session = NewFunctionTemplate(isolate, Http2Session::New); diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index 9ad04eae0878..372606eb6de0 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -4632,9 +4632,13 @@ static void Initialize(Local target, SetConstructorFunction(context, target, "StatementSync", - StatementSync::GetConstructorTemplate(env)); - SetConstructorFunction( - context, target, "Session", Session::GetConstructorTemplate(env)); + StatementSync::GetConstructorTemplate(env), + SetConstructorFunctionFlag::NONE); + SetConstructorFunction(context, + target, + "Session", + Session::GetConstructorTemplate(env), + SetConstructorFunctionFlag::NONE); target->Set(context, env->constants_string(), constants).Check(); diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 48bd22e301d8..99e5729cfc19 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -71,24 +71,28 @@ void PipeWrap::Initialize(Local target, Environment* env = Environment::GetCurrent(context); Isolate* isolate = env->isolate(); - Local t = NewFunctionTemplate(isolate, New); - t->InstanceTemplate()->SetInternalFieldCount(PipeWrap::kInternalFieldCount); + Local t = env->pipe_constructor_template(); + if (t.IsEmpty()) { + t = NewFunctionTemplate(isolate, New); + t->InstanceTemplate()->SetInternalFieldCount(PipeWrap::kInternalFieldCount); - t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); + t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); - SetProtoMethod(isolate, t, "bind", Bind); - SetProtoMethod(isolate, t, "listen", Listen); - SetProtoMethod(isolate, t, "connect", Connect); - SetProtoMethod(isolate, t, "open", Open); + SetProtoMethod(isolate, t, "bind", Bind); + SetProtoMethod(isolate, t, "listen", Listen); + SetProtoMethod(isolate, t, "connect", Connect); + SetProtoMethod(isolate, t, "open", Open); #ifdef _WIN32 - SetProtoMethod(isolate, t, "setPendingInstances", SetPendingInstances); + SetProtoMethod(isolate, t, "setPendingInstances", SetPendingInstances); #endif - SetProtoMethod(isolate, t, "fchmod", Fchmod); - - SetConstructorFunction(context, target, "Pipe", t); - env->set_pipe_constructor_template(t); + SetProtoMethod(isolate, t, "fchmod", Fchmod); + t->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "Pipe")); + env->set_pipe_constructor_template(t); + } + SetConstructorFunction( + context, target, "Pipe", t, SetConstructorFunctionFlag::NONE); // Create FunctionTemplate for PipeConnectWrap. auto cwt = AsyncWrap::MakeLazilyInitializedJSTemplate(env); diff --git a/src/stream_base.cc b/src/stream_base.cc index e0f3b941ae67..a73a39513fb0 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -48,6 +48,7 @@ int StreamBase::Shutdown(v8::Local req_wrap_obj) { if (req_wrap_obj.IsEmpty()) { if (!env->shutdown_wrap_template() + ->InstanceTemplate() ->NewInstance(env->context()) .ToLocal(&req_wrap_obj)) { return UV_EBUSY; @@ -103,6 +104,7 @@ StreamWriteResult StreamBase::Write(uv_buf_t* bufs, if (req_wrap_obj.IsEmpty()) { if (!env->write_wrap_template() + ->InstanceTemplate() ->NewInstance(env->context()) .ToLocal(&req_wrap_obj)) { return StreamWriteResult{false, UV_EBUSY, nullptr, 0, {}}; @@ -332,6 +334,7 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo& args) { if (lazy_req) { // Sending a handle requires a request object up front to reference it. if (!env->write_wrap_template() + ->InstanceTemplate() ->NewInstance(env->context()) .ToLocal(&req_wrap_obj)) { return UV_EBUSY; @@ -447,6 +450,7 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { if (lazy_req && req_wrap_obj.IsEmpty()) { // Sending a handle requires a request object up front to reference it. if (!env->write_wrap_template() + ->InstanceTemplate() ->NewInstance(env->context()) .ToLocal(&req_wrap_obj)) { return UV_EBUSY; diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index c7d3c4745511..b874367e6549 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -53,6 +53,7 @@ using v8::Maybe; using v8::MaybeLocal; using v8::Nothing; using v8::Object; +using v8::ObjectTemplate; using v8::PropertyAttribute; using v8::ReadOnly; using v8::Signature; @@ -70,48 +71,54 @@ void LibuvStreamWrap::Initialize(Local target, Environment* env = Environment::GetCurrent(context); Isolate* isolate = env->isolate(); - Local sw = - NewFunctionTemplate(isolate, IsConstructCallCallback); - sw->InstanceTemplate()->SetInternalFieldCount( - ShutdownWrap::kInternalFieldCount); - - // we need to set handle and callback to null, - // so that those fields are created and functions - // do not become megamorphic - // Fields: - // - oncomplete - // - callback - // - handle - sw->InstanceTemplate()->Set(env->oncomplete_string(), v8::Null(isolate)); - sw->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(isolate, "callback"), - v8::Null(isolate)); - sw->InstanceTemplate()->Set(env->handle_string(), v8::Null(isolate)); - - sw->Inherit(AsyncWrap::GetConstructorTemplate(env)); - - SetConstructorFunction(context, target, "ShutdownWrap", sw); - env->set_shutdown_wrap_template(sw->InstanceTemplate()); - - Local ww = - FunctionTemplate::New(isolate, IsConstructCallCallback); - ww->InstanceTemplate()->SetInternalFieldCount(WriteWrap::kInternalFieldCount); - // Pre-create the fields that JS attaches to write requests, so that they - // are in-object properties and the object shape stays monomorphic. - ww->InstanceTemplate()->Set(env->oncomplete_string(), v8::Null(isolate)); - ww->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(isolate, "callback"), - v8::Null(isolate)); - ww->InstanceTemplate()->Set(env->handle_string(), v8::Null(isolate)); - ww->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(isolate, "async"), - v8::False(isolate)); - ww->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(isolate, "bytes"), - v8::Integer::New(isolate, 0)); - ww->InstanceTemplate()->Set(env->buffer_string(), v8::Null(isolate)); - // Slot for a completion that fires before JS attaches `oncomplete`; see - // ReportWritesToJSStreamListener::OnStreamAfterReqFinished(). - ww->InstanceTemplate()->Set(env->write_status_string(), v8::Null(isolate)); - ww->Inherit(AsyncWrap::GetConstructorTemplate(env)); - SetConstructorFunction(context, target, "WriteWrap", ww); - env->set_write_wrap_template(ww->InstanceTemplate()); + Local sw = env->shutdown_wrap_template(); + if (sw.IsEmpty()) { + sw = NewFunctionTemplate(isolate, IsConstructCallCallback); + sw->InstanceTemplate()->SetInternalFieldCount( + ShutdownWrap::kInternalFieldCount); + + // we need to set handle and callback to null, + // so that those fields are created and functions + // do not become megamorphic + // Fields: + // - oncomplete + // - callback + // - handle + sw->InstanceTemplate()->Set(env->oncomplete_string(), v8::Null(isolate)); + sw->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(isolate, "callback"), + v8::Null(isolate)); + sw->InstanceTemplate()->Set(env->handle_string(), v8::Null(isolate)); + + sw->Inherit(AsyncWrap::GetConstructorTemplate(env)); + sw->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "ShutdownWrap")); + env->set_shutdown_wrap_template(sw); + } + SetConstructorFunction( + context, target, "ShutdownWrap", sw, SetConstructorFunctionFlag::NONE); + + Local ww = env->write_wrap_template(); + if (ww.IsEmpty()) { + ww = FunctionTemplate::New(isolate, IsConstructCallCallback); + Local wwt = ww->InstanceTemplate(); + wwt->SetInternalFieldCount(WriteWrap::kInternalFieldCount); + // Pre-create the fields that JS attaches to write requests, so that they + // are in-object properties and the object shape stays monomorphic. + wwt->Set(env->oncomplete_string(), v8::Null(isolate)); + wwt->Set(FIXED_ONE_BYTE_STRING(isolate, "callback"), v8::Null(isolate)); + wwt->Set(env->handle_string(), v8::Null(isolate)); + wwt->Set(FIXED_ONE_BYTE_STRING(isolate, "async"), v8::False(isolate)); + wwt->Set(FIXED_ONE_BYTE_STRING(isolate, "bytes"), + v8::Integer::New(isolate, 0)); + wwt->Set(env->buffer_string(), v8::Null(isolate)); + // Slot for a completion that fires before JS attaches `oncomplete`; see + // ReportWritesToJSStreamListener::OnStreamAfterReqFinished(). + wwt->Set(env->write_status_string(), v8::Null(isolate)); + ww->Inherit(AsyncWrap::GetConstructorTemplate(env)); + ww->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "WriteWrap")); + env->set_write_wrap_template(ww); + } + SetConstructorFunction( + context, target, "WriteWrap", ww, SetConstructorFunctionFlag::NONE); NODE_DEFINE_CONSTANT(target, kReadBytesOrError); NODE_DEFINE_CONSTANT(target, kArrayBufferOffset); diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 9bb742fb3edc..68f28e3dc872 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -88,43 +88,49 @@ void TCPWrap::Initialize(Local target, Environment* env = Environment::GetCurrent(context); Isolate* isolate = env->isolate(); - Local t = NewFunctionTemplate(isolate, New); - t->InstanceTemplate()->SetInternalFieldCount(TCPWrap::kInternalFieldCount); - - // Init properties - t->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "reading"), - Boolean::New(env->isolate(), false)); - t->InstanceTemplate()->Set(env->owner_symbol(), Null(env->isolate())); - t->InstanceTemplate()->Set(env->onconnection_string(), Null(env->isolate())); - - t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); - - SetProtoMethod(isolate, t, "open", Open); - SetProtoMethod(isolate, t, "bind", Bind); - SetProtoMethod(isolate, t, "listen", Listen); - SetProtoMethod(isolate, t, "connect", Connect); - SetProtoMethod(isolate, t, "bind6", Bind6); - SetProtoMethod(isolate, t, "connect6", Connect6); - SetProtoMethod(isolate, - t, - "getsockname", - GetSockOrPeerName); - SetProtoMethod(isolate, - t, - "getpeername", - GetSockOrPeerName); - SetProtoMethod(isolate, t, "setNoDelay", SetNoDelay); - SetProtoMethod(isolate, t, "setKeepAlive", SetKeepAlive); - SetProtoMethod(isolate, t, "setTypeOfService", SetTypeOfService); - SetProtoMethod(isolate, t, "getTypeOfService", GetTypeOfService); - SetProtoMethod(isolate, t, "reset", Reset); + Local t = env->tcp_constructor_template(); + if (t.IsEmpty()) { + t = NewFunctionTemplate(isolate, New); + t->InstanceTemplate()->SetInternalFieldCount(TCPWrap::kInternalFieldCount); + + // Init properties + t->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(isolate, "reading"), + Boolean::New(isolate, false)); + t->InstanceTemplate()->Set(env->owner_symbol(), Null(isolate)); + t->InstanceTemplate()->Set(env->onconnection_string(), Null(isolate)); + + t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); + + SetProtoMethod(isolate, t, "open", Open); + SetProtoMethod(isolate, t, "bind", Bind); + SetProtoMethod(isolate, t, "listen", Listen); + SetProtoMethod(isolate, t, "connect", Connect); + SetProtoMethod(isolate, t, "bind6", Bind6); + SetProtoMethod(isolate, t, "connect6", Connect6); + SetProtoMethod(isolate, + t, + "getsockname", + GetSockOrPeerName); + SetProtoMethod(isolate, + t, + "getpeername", + GetSockOrPeerName); + SetProtoMethod(isolate, t, "setNoDelay", SetNoDelay); + SetProtoMethod(isolate, t, "setKeepAlive", SetKeepAlive); + SetProtoMethod(isolate, t, "setTypeOfService", SetTypeOfService); + SetProtoMethod(isolate, t, "getTypeOfService", GetTypeOfService); + SetProtoMethod(isolate, t, "reset", Reset); #ifdef _WIN32 - SetProtoMethod(isolate, t, "setSimultaneousAccepts", SetSimultaneousAccepts); + SetProtoMethod( + isolate, t, "setSimultaneousAccepts", SetSimultaneousAccepts); #endif - SetConstructorFunction(context, target, "TCP", t); - env->set_tcp_constructor_template(t); + t->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "TCP")); + env->set_tcp_constructor_template(t); + } + SetConstructorFunction( + context, target, "TCP", t, SetConstructorFunctionFlag::NONE); // Create FunctionTemplate for TCPConnectWrap. Local cwt = AsyncWrap::MakeLazilyInitializedJSTemplate(env); diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index c605ab2fcc11..0c4c02f6aa40 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -58,14 +58,18 @@ void TTYWrap::Initialize(Local target, Local ttyString = FIXED_ONE_BYTE_STRING(env->isolate(), "TTY"); - Local t = NewFunctionTemplate(isolate, New); - t->SetClassName(ttyString); - t->InstanceTemplate()->SetInternalFieldCount(TTYWrap::kInternalFieldCount); - t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); - - SetProtoMethodNoSideEffect( - isolate, t, "getWindowSize", TTYWrap::GetWindowSize); - SetProtoMethod(isolate, t, "setRawMode", SetRawMode); + Local t = env->tty_constructor_template(); + if (t.IsEmpty()) { + t = NewFunctionTemplate(isolate, New); + t->SetClassName(ttyString); + t->InstanceTemplate()->SetInternalFieldCount(TTYWrap::kInternalFieldCount); + t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); + + SetProtoMethodNoSideEffect( + isolate, t, "getWindowSize", TTYWrap::GetWindowSize); + SetProtoMethod(isolate, t, "setRawMode", SetRawMode); + env->set_tty_constructor_template(t); + } SetMethodNoSideEffect(context, target, "isTTY", IsTTY); NODE_DEFINE_CONSTANT(target, UV_TTY_MODE_NORMAL); @@ -73,9 +77,8 @@ void TTYWrap::Initialize(Local target, NODE_DEFINE_CONSTANT(target, UV_TTY_MODE_RAW_VT); Local func; - if (t->GetFunction(context).ToLocal(&func) && - target->Set(context, ttyString, func).IsJust()) { - env->set_tty_constructor_template(t); + if (t->GetFunction(context).ToLocal(&func)) { + target->Set(context, ttyString, func).Check(); } } diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc index e00ea5951244..96259ec50227 100644 --- a/test/cctest/test_environment.cc +++ b/test/cctest/test_environment.cc @@ -411,6 +411,27 @@ TEST_F(EnvironmentTest, CollectExternalReferencesFromSeveralThreads) { EXPECT_EQ(node::SnapshotBuilder::CollectExternalReferences().back(), 0); } +TEST_F(EnvironmentTest, SharedIsolateDataLoadsBindingsTwice) { + const v8::HandleScope handle_scope(isolate_); + const Argv argv; + const char* script = + "for (const m of require('module').builtinModules) {" + " try { require(m); } catch {}" + "}" + "new (require('net').Socket)();" +#if HAVE_OPENSSL + "require('tls').createSecureContext();" + "require('crypto').createSecretKey(Buffer.alloc(8));" +#endif + "new (require('worker_threads').MessageChannel)().port1.close();"; + Env env1{handle_scope, argv}; + node::LoadEnvironment(*env1, script).ToLocalChecked(); + EXPECT_EQ(node::SpinEventLoop(*env1).FromJust(), 0); + Env env2{handle_scope, argv, node::EnvironmentFlags::kNoCreateInspector}; + node::LoadEnvironment(*env2, script).ToLocalChecked(); + EXPECT_EQ(node::SpinEventLoop(*env2).FromJust(), 0); +} + TEST_F(EnvironmentTest, NoEnvironmentSanity) { const v8::HandleScope handle_scope(isolate_); v8::Local context = v8::Context::New(isolate_);