Skip to content

Commit 6ba38e8

Browse files
Gabriel SchulhofMylesBorins
Gabriel Schulhof
authored andcommittedApr 16, 2018
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) Backport-PR-URL: #19447 PR-URL: #13999 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.co> Reviewed-By: Hitesh Kanwathirtha <digitalinfinity@gmail.com>
1 parent 7f126c2 commit 6ba38e8

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
@@ -36,14 +36,32 @@ struct napi_env__ {
3636
~napi_env__() {
3737
last_exception.Reset();
3838
has_instance.Reset();
39+
wrap_template.Reset();
40+
function_data_template.Reset();
41+
accessor_data_template.Reset();
3942
}
4043
v8::Isolate* isolate;
4144
v8::Persistent<v8::Value> last_exception;
4245
v8::Persistent<v8::Value> has_instance;
46+
v8::Persistent<v8::ObjectTemplate> wrap_template;
47+
v8::Persistent<v8::ObjectTemplate> function_data_template;
48+
v8::Persistent<v8::ObjectTemplate> accessor_data_template;
4349
bool has_instance_available;
4450
napi_extended_error_info last_error;
4551
};
4652

53+
#define ENV_OBJECT_TEMPLATE(env, prefix, destination, field_count) \
54+
do { \
55+
if ((env)->prefix ## _template.IsEmpty()) { \
56+
(destination) = v8::ObjectTemplate::New(isolate); \
57+
(destination)->SetInternalFieldCount((field_count)); \
58+
(env)->prefix ## _template.Reset(isolate, (destination)); \
59+
} else { \
60+
(destination) = env->prefix ## _template.Get(isolate); \
61+
} \
62+
} while (0)
63+
64+
4765
#define RETURN_STATUS_IF_FALSE(env, condition, status) \
4866
do { \
4967
if (!(condition)) { \
@@ -608,8 +626,8 @@ v8::Local<v8::Object> CreateFunctionCallbackData(napi_env env,
608626
v8::Isolate* isolate = env->isolate;
609627
v8::Local<v8::Context> context = isolate->GetCurrentContext();
610628

611-
v8::Local<v8::ObjectTemplate> otpl = v8::ObjectTemplate::New(isolate);
612-
otpl->SetInternalFieldCount(v8impl::kFunctionFieldCount);
629+
v8::Local<v8::ObjectTemplate> otpl;
630+
ENV_OBJECT_TEMPLATE(env, function_data, otpl, v8impl::kFunctionFieldCount);
613631
v8::Local<v8::Object> cbdata = otpl->NewInstance(context).ToLocalChecked();
614632

615633
cbdata->SetInternalField(
@@ -634,8 +652,8 @@ v8::Local<v8::Object> CreateAccessorCallbackData(napi_env env,
634652
v8::Isolate* isolate = env->isolate;
635653
v8::Local<v8::Context> context = isolate->GetCurrentContext();
636654

637-
v8::Local<v8::ObjectTemplate> otpl = v8::ObjectTemplate::New(isolate);
638-
otpl->SetInternalFieldCount(v8impl::kAccessorFieldCount);
655+
v8::Local<v8::ObjectTemplate> otpl;
656+
ENV_OBJECT_TEMPLATE(env, accessor_data, otpl, v8impl::kAccessorFieldCount);
639657
v8::Local<v8::Object> cbdata = otpl->NewInstance(context).ToLocalChecked();
640658

641659
cbdata->SetInternalField(
@@ -2011,11 +2029,10 @@ napi_status napi_wrap(napi_env env,
20112029
v8::Local<v8::Object> obj = value.As<v8::Object>();
20122030

20132031
// Create a wrapper object with an internal field to hold the wrapped pointer.
2014-
v8::Local<v8::ObjectTemplate> wrapperTemplate =
2015-
v8::ObjectTemplate::New(isolate);
2016-
wrapperTemplate->SetInternalFieldCount(1);
2032+
v8::Local<v8::ObjectTemplate> wrapper_template;
2033+
ENV_OBJECT_TEMPLATE(env, wrap, wrapper_template, 1);
20172034
v8::Local<v8::Object> wrapper =
2018-
wrapperTemplate->NewInstance(context).ToLocalChecked();
2035+
wrapper_template->NewInstance(context).ToLocalChecked();
20192036
wrapper->SetInternalField(0, v8::External::New(isolate, native_object));
20202037

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

0 commit comments

Comments
 (0)
Please sign in to comment.