Skip to content

Commit 53c52ac

Browse files
Gabriel Schulhofaddaleax
Gabriel Schulhof
authored andcommitted
N-API: Reuse ObjectTemplate instances
V8 caches and does not subsequently release `ObjectTemplate` instances. Thus, we need to store the `ObjectTemplate` from which we derive object instances we use for `napi_wrap()` and function/accessor context in a persistent in the `napi_env`. nodejs/node-addon-api#70 (comment) PR-URL: #13999 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Hitesh Kanwathirtha <[email protected]>
1 parent 9cfa52a commit 53c52ac

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

src/node_api.cc

+25-8
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,32 @@ struct napi_env__ {
3434
~napi_env__() {
3535
last_exception.Reset();
3636
has_instance.Reset();
37+
wrap_template.Reset();
38+
function_data_template.Reset();
39+
accessor_data_template.Reset();
3740
}
3841
v8::Isolate* isolate;
3942
v8::Persistent<v8::Value> last_exception;
4043
v8::Persistent<v8::Value> has_instance;
44+
v8::Persistent<v8::ObjectTemplate> wrap_template;
45+
v8::Persistent<v8::ObjectTemplate> function_data_template;
46+
v8::Persistent<v8::ObjectTemplate> accessor_data_template;
4147
bool has_instance_available;
4248
napi_extended_error_info last_error;
4349
};
4450

51+
#define ENV_OBJECT_TEMPLATE(env, prefix, destination, field_count) \
52+
do { \
53+
if ((env)->prefix ## _template.IsEmpty()) { \
54+
(destination) = v8::ObjectTemplate::New(isolate); \
55+
(destination)->SetInternalFieldCount((field_count)); \
56+
(env)->prefix ## _template.Reset(isolate, (destination)); \
57+
} else { \
58+
(destination) = env->prefix ## _template.Get(isolate); \
59+
} \
60+
} while (0)
61+
62+
4563
#define RETURN_STATUS_IF_FALSE(env, condition, status) \
4664
do { \
4765
if (!(condition)) { \
@@ -603,8 +621,8 @@ v8::Local<v8::Object> CreateFunctionCallbackData(napi_env env,
603621
v8::Isolate* isolate = env->isolate;
604622
v8::Local<v8::Context> context = isolate->GetCurrentContext();
605623

606-
v8::Local<v8::ObjectTemplate> otpl = v8::ObjectTemplate::New(isolate);
607-
otpl->SetInternalFieldCount(v8impl::kFunctionFieldCount);
624+
v8::Local<v8::ObjectTemplate> otpl;
625+
ENV_OBJECT_TEMPLATE(env, function_data, otpl, v8impl::kFunctionFieldCount);
608626
v8::Local<v8::Object> cbdata = otpl->NewInstance(context).ToLocalChecked();
609627

610628
cbdata->SetInternalField(
@@ -629,8 +647,8 @@ v8::Local<v8::Object> CreateAccessorCallbackData(napi_env env,
629647
v8::Isolate* isolate = env->isolate;
630648
v8::Local<v8::Context> context = isolate->GetCurrentContext();
631649

632-
v8::Local<v8::ObjectTemplate> otpl = v8::ObjectTemplate::New(isolate);
633-
otpl->SetInternalFieldCount(v8impl::kAccessorFieldCount);
650+
v8::Local<v8::ObjectTemplate> otpl;
651+
ENV_OBJECT_TEMPLATE(env, accessor_data, otpl, v8impl::kAccessorFieldCount);
634652
v8::Local<v8::Object> cbdata = otpl->NewInstance(context).ToLocalChecked();
635653

636654
cbdata->SetInternalField(
@@ -2008,11 +2026,10 @@ napi_status napi_wrap(napi_env env,
20082026
v8::Local<v8::Object> obj = value.As<v8::Object>();
20092027

20102028
// Create a wrapper object with an internal field to hold the wrapped pointer.
2011-
v8::Local<v8::ObjectTemplate> wrapperTemplate =
2012-
v8::ObjectTemplate::New(isolate);
2013-
wrapperTemplate->SetInternalFieldCount(1);
2029+
v8::Local<v8::ObjectTemplate> wrapper_template;
2030+
ENV_OBJECT_TEMPLATE(env, wrap, wrapper_template, 1);
20142031
v8::Local<v8::Object> wrapper =
2015-
wrapperTemplate->NewInstance(context).ToLocalChecked();
2032+
wrapper_template->NewInstance(context).ToLocalChecked();
20162033
wrapper->SetInternalField(0, v8::External::New(isolate, native_object));
20172034

20182035
// Insert the wrapper into the object's prototype chain.

0 commit comments

Comments
 (0)