@@ -228,27 +228,18 @@ void Http2Session::Http2Settings::Init() {
228228 count_ = n;
229229}
230230
231- Http2Session::Http2Settings::Http2Settings (Environment* env,
232- Http2Session* session, uint64_t start_time)
233- : AsyncWrap(env,
234- env->http2settings_constructor_template ()
235- ->NewInstance(env->context ())
236- .ToLocalChecked(),
237- PROVIDER_HTTP2SETTINGS),
238- session_(session),
239- startTime_(start_time) {
240- Init ();
241- }
242-
243-
244- Http2Session::Http2Settings::Http2Settings (Environment* env)
245- : Http2Settings(env, nullptr , 0 ) {}
246-
247231// The Http2Settings class is used to configure a SETTINGS frame that is
248232// to be sent to the connected peer. The settings are set using a TypedArray
249233// that is shared with the JavaScript side.
250- Http2Session::Http2Settings::Http2Settings (Http2Session* session)
251- : Http2Settings(session->env (), session, uv_hrtime()) {}
234+ Http2Session::Http2Settings::Http2Settings (Environment* env,
235+ Http2Session* session,
236+ Local<Object> obj,
237+ uint64_t start_time)
238+ : AsyncWrap(env, obj, PROVIDER_HTTP2SETTINGS),
239+ session_ (session),
240+ startTime_(start_time) {
241+ Init ();
242+ }
252243
253244// Generates a Buffer that contains the serialized payload of a SETTINGS
254245// frame. This can be used, for instance, to create the Base64-encoded
@@ -916,13 +907,14 @@ int Http2Session::OnBeginHeadersCallback(nghttp2_session* handle,
916907 // The common case is that we're creating a new stream. The less likely
917908 // case is that we're receiving a set of trailers
918909 if (LIKELY (stream == nullptr )) {
919- if (UNLIKELY (!session->CanAddStream ())) {
910+ if (UNLIKELY (!session->CanAddStream () ||
911+ Http2Stream::New (session, id, frame->headers .cat ) ==
912+ nullptr )) {
920913 // Too many concurrent streams being opened
921914 nghttp2_submit_rst_stream (**session, NGHTTP2_FLAG_NONE, id,
922915 NGHTTP2_ENHANCE_YOUR_CALM);
923916 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
924917 }
925- new Http2Stream (session, id, frame->headers .cat );
926918 } else if (!stream->IsDestroyed ()) {
927919 stream->StartHeaders (frame->headers .cat );
928920 }
@@ -1789,7 +1781,7 @@ Http2Stream* Http2Session::SubmitRequest(
17891781 *ret = nghttp2_submit_request (session_, prispec, nva, len, *prov, nullptr );
17901782 CHECK_NE (*ret, NGHTTP2_ERR_NOMEM);
17911783 if (LIKELY (*ret > 0 ))
1792- stream = new Http2Stream (this , *ret, NGHTTP2_HCAT_HEADERS, options);
1784+ stream = Http2Stream::New (this , *ret, NGHTTP2_HCAT_HEADERS, options);
17931785 return stream;
17941786}
17951787
@@ -1875,20 +1867,30 @@ void Http2Session::Consume(Local<External> external) {
18751867 Debug (this , " i/o stream consumed" );
18761868}
18771869
1878-
1879- Http2Stream::Http2Stream (
1880- Http2Session* session,
1881- int32_t id,
1882- nghttp2_headers_category category,
1883- int options) : AsyncWrap(session->env (),
1884- session->env()->http2stream_constructor_template()
1885- ->NewInstance(session->env ()->context())
1886- .ToLocalChecked(),
1887- AsyncWrap::PROVIDER_HTTP2STREAM),
1888- StreamBase(session->env ()),
1889- session_(session),
1890- id_(id),
1891- current_headers_category_(category) {
1870+ Http2Stream* Http2Stream::New (Http2Session* session,
1871+ int32_t id,
1872+ nghttp2_headers_category category,
1873+ int options) {
1874+ Local<Object> obj;
1875+ if (!session->env ()
1876+ ->http2stream_constructor_template ()
1877+ ->NewInstance (session->env ()->context ())
1878+ .ToLocal (&obj)) {
1879+ return nullptr ;
1880+ }
1881+ return new Http2Stream (session, obj, id, category, options);
1882+ }
1883+
1884+ Http2Stream::Http2Stream (Http2Session* session,
1885+ Local<Object> obj,
1886+ int32_t id,
1887+ nghttp2_headers_category category,
1888+ int options)
1889+ : AsyncWrap(session->env (), obj, AsyncWrap::PROVIDER_HTTP2STREAM),
1890+ StreamBase(session->env ()),
1891+ session_(session),
1892+ id_(id),
1893+ current_headers_category_(category) {
18921894 MakeWeak ();
18931895 statistics_.start_time = uv_hrtime ();
18941896
@@ -2132,7 +2134,7 @@ Http2Stream* Http2Stream::SubmitPushPromise(nghttp2_nv* nva,
21322134 CHECK_NE (*ret, NGHTTP2_ERR_NOMEM);
21332135 Http2Stream* stream = nullptr ;
21342136 if (*ret > 0 )
2135- stream = new Http2Stream (session_, *ret, NGHTTP2_HCAT_HEADERS, options);
2137+ stream = Http2Stream::New (session_, *ret, NGHTTP2_HCAT_HEADERS, options);
21362138
21372139 return stream;
21382140}
@@ -2354,7 +2356,14 @@ void HttpErrorString(const FunctionCallbackInfo<Value>& args) {
23542356// output for an HTTP2-Settings header field.
23552357void PackSettings (const FunctionCallbackInfo<Value>& args) {
23562358 Environment* env = Environment::GetCurrent (args);
2357- Http2Session::Http2Settings settings (env);
2359+ // TODO(addaleax): We should not be creating a full AsyncWrap for this.
2360+ Local<Object> obj;
2361+ if (!env->http2settings_constructor_template ()
2362+ ->NewInstance (env->context ())
2363+ .ToLocal (&obj)) {
2364+ return ;
2365+ }
2366+ Http2Session::Http2Settings settings (env, nullptr , obj);
23582367 args.GetReturnValue ().Set (settings.Pack ());
23592368}
23602369
@@ -2483,7 +2492,7 @@ void Http2Session::Request(const FunctionCallbackInfo<Value>& args) {
24832492 session->Http2Session ::SubmitRequest (*priority, *list, list.length (),
24842493 &ret, options);
24852494
2486- if (ret <= 0 ) {
2495+ if (ret <= 0 || stream == nullptr ) {
24872496 Debug (session, " could not submit request: %s" , nghttp2_strerror (ret));
24882497 return args.GetReturnValue ().Set (ret);
24892498 }
@@ -2656,7 +2665,7 @@ void Http2Stream::PushPromise(const FunctionCallbackInfo<Value>& args) {
26562665 int32_t ret = 0 ;
26572666 Http2Stream* stream = parent->SubmitPushPromise (*list, list.length (),
26582667 &ret, options);
2659- if (ret <= 0 ) {
2668+ if (ret <= 0 || stream == nullptr ) {
26602669 Debug (parent, " failed to create push stream: %d" , ret);
26612670 return args.GetReturnValue ().Set (ret);
26622671 }
@@ -2792,9 +2801,15 @@ void Http2Session::Ping(const FunctionCallbackInfo<Value>& args) {
27922801 CHECK_EQ (Buffer::Length (args[0 ]), 8 );
27932802 }
27942803
2795- Http2Session::Http2Ping* ping = new Http2Ping (session);
2796- Local<Object> obj = ping->object ();
2797- obj->Set (env->context (), env->ondone_string (), args[1 ]).FromJust ();
2804+ Local<Object> obj;
2805+ if (!env->http2ping_constructor_template ()
2806+ ->NewInstance (env->context ())
2807+ .ToLocal (&obj)) {
2808+ return ;
2809+ }
2810+ if (obj->Set (env->context (), env->ondone_string (), args[1 ]).IsNothing ())
2811+ return ;
2812+ Http2Session::Http2Ping* ping = new Http2Ping (session, obj);
27982813
27992814 // To prevent abuse, we strictly limit the number of unacknowledged PING
28002815 // frames that may be sent at any given time. This is configurable in the
@@ -2818,10 +2833,17 @@ void Http2Session::Settings(const FunctionCallbackInfo<Value>& args) {
28182833 Http2Session* session;
28192834 ASSIGN_OR_RETURN_UNWRAP (&session, args.Holder ());
28202835
2821- Http2Session::Http2Settings* settings = new Http2Settings (session);
2822- Local<Object> obj = settings->object ();
2823- obj->Set (env->context (), env->ondone_string (), args[0 ]).FromJust ();
2836+ Local<Object> obj;
2837+ if (!env->http2settings_constructor_template ()
2838+ ->NewInstance (env->context ())
2839+ .ToLocal (&obj)) {
2840+ return ;
2841+ }
2842+ if (obj->Set (env->context (), env->ondone_string (), args[0 ]).IsNothing ())
2843+ return ;
28242844
2845+ Http2Session::Http2Settings* settings =
2846+ new Http2Settings (session->env (), session, obj, 0 );
28252847 if (!session->AddSettings (settings)) {
28262848 settings->Done (false );
28272849 return args.GetReturnValue ().Set (false );
@@ -2868,15 +2890,10 @@ bool Http2Session::AddSettings(Http2Session::Http2Settings* settings) {
28682890 return true ;
28692891}
28702892
2871- Http2Session::Http2Ping::Http2Ping (
2872- Http2Session* session)
2873- : AsyncWrap(session->env (),
2874- session->env()->http2ping_constructor_template()
2875- ->NewInstance(session->env ()->context())
2876- .ToLocalChecked(),
2877- AsyncWrap::PROVIDER_HTTP2PING),
2878- session_(session),
2879- startTime_(uv_hrtime()) { }
2893+ Http2Session::Http2Ping::Http2Ping (Http2Session* session, Local<Object> obj)
2894+ : AsyncWrap(session->env (), obj, AsyncWrap::PROVIDER_HTTP2PING),
2895+ session_(session),
2896+ startTime_(uv_hrtime()) {}
28802897
28812898void Http2Session::Http2Ping::Send (uint8_t * payload) {
28822899 uint8_t data[8 ];
0 commit comments