From b950daf8368cb9ab7f190b74774e55b20e17dec9 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 22 Mar 2020 18:00:57 +0100 Subject: [PATCH] src: use single ObjectTemplate for TextDecoder `ObjectTemplate`s are not garbage-collected like regular objects (for some reason). It is sufficient to create a single template anyway, so do that to address the memory leak. Fixes: https://github.com/nodejs/node/issues/32424 PR-URL: https://github.com/nodejs/node/pull/32426 Reviewed-By: Gus Caplan Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Ben Noordhuis --- src/env.h | 1 + src/node_i18n.cc | 14 ++++++++++++-- .../test-whatwg-encoding-custom-textdecoder.js | 9 +++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/env.h b/src/env.h index bc4e60e108aa7a..719aca19a13803 100644 --- a/src/env.h +++ b/src/env.h @@ -411,6 +411,7 @@ constexpr size_t kFsStatsBufferLength = V(http2settings_constructor_template, v8::ObjectTemplate) \ V(http2stream_constructor_template, v8::ObjectTemplate) \ V(http2ping_constructor_template, v8::ObjectTemplate) \ + V(i18n_converter_template, v8::ObjectTemplate) \ V(libuv_stream_wrap_ctor_template, v8::FunctionTemplate) \ V(message_port_constructor_template, v8::FunctionTemplate) \ V(pipe_constructor_template, v8::FunctionTemplate) \ diff --git a/src/node_i18n.cc b/src/node_i18n.cc index a32ddf2066be5f..3bf452b6978e6e 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -86,6 +86,7 @@ namespace node { using v8::Context; using v8::FunctionCallbackInfo; +using v8::FunctionTemplate; using v8::HandleScope; using v8::Int32; using v8::Isolate; @@ -171,8 +172,7 @@ class ConverterObject : public BaseObject, Converter { Environment* env = Environment::GetCurrent(args); HandleScope scope(env->isolate()); - Local t = ObjectTemplate::New(env->isolate()); - t->SetInternalFieldCount(ConverterObject::kInternalFieldCount); + Local t = env->i18n_converter_template(); Local obj; if (!t->NewInstance(env->context()).ToLocal(&obj)) return; @@ -821,6 +821,16 @@ void Initialize(Local target, env->SetMethod(target, "transcode", Transcode); // ConverterObject + { + Local t = FunctionTemplate::New(env->isolate()); + t->InstanceTemplate()->SetInternalFieldCount( + ConverterObject::kInternalFieldCount); + Local converter_string = + FIXED_ONE_BYTE_STRING(env->isolate(), "Converter"); + t->SetClassName(converter_string); + env->set_i18n_converter_template(t->InstanceTemplate()); + } + env->SetMethod(target, "getConverter", ConverterObject::Create); env->SetMethod(target, "decode", ConverterObject::Decode); env->SetMethod(target, "hasConverter", ConverterObject::Has); diff --git a/test/parallel/test-whatwg-encoding-custom-textdecoder.js b/test/parallel/test-whatwg-encoding-custom-textdecoder.js index 1430a0daa8eabb..d16fd24bcd3739 100644 --- a/test/parallel/test-whatwg-encoding-custom-textdecoder.js +++ b/test/parallel/test-whatwg-encoding-custom-textdecoder.js @@ -107,8 +107,13 @@ if (common.hasIntl) { if (common.hasIntl) { assert.strictEqual( util.inspect(dec, { showHidden: true }), - 'TextDecoder {\n encoding: \'utf-8\',\n fatal: false,\n ' + - 'ignoreBOM: true,\n [Symbol(flags)]: 4,\n [Symbol(handle)]: {}\n}' + 'TextDecoder {\n' + + ' encoding: \'utf-8\',\n' + + ' fatal: false,\n' + + ' ignoreBOM: true,\n' + + ' [Symbol(flags)]: 4,\n' + + ' [Symbol(handle)]: Converter {}\n' + + '}' ); } else { assert.strictEqual(