diff --git a/src/node_api.cc b/src/node_api.cc index 6c2e70adbaf71e..85b066746d4a0d 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -34,14 +34,32 @@ struct napi_env__ { ~napi_env__() { last_exception.Reset(); has_instance.Reset(); + wrap_template.Reset(); + function_data_template.Reset(); + accessor_data_template.Reset(); } v8::Isolate* isolate; v8::Persistent last_exception; v8::Persistent has_instance; + v8::Persistent wrap_template; + v8::Persistent function_data_template; + v8::Persistent accessor_data_template; bool has_instance_available; napi_extended_error_info last_error; }; +#define ENV_OBJECT_TEMPLATE(env, prefix, destination, field_count) \ + do { \ + if ((env)->prefix ## _template.IsEmpty()) { \ + (destination) = v8::ObjectTemplate::New(isolate); \ + (destination)->SetInternalFieldCount((field_count)); \ + (env)->prefix ## _template.Reset(isolate, (destination)); \ + } else { \ + (destination) = env->prefix ## _template.Get(isolate); \ + } \ + } while (0) + + #define RETURN_STATUS_IF_FALSE(env, condition, status) \ do { \ if (!(condition)) { \ @@ -603,8 +621,8 @@ v8::Local CreateFunctionCallbackData(napi_env env, v8::Isolate* isolate = env->isolate; v8::Local context = isolate->GetCurrentContext(); - v8::Local otpl = v8::ObjectTemplate::New(isolate); - otpl->SetInternalFieldCount(v8impl::kFunctionFieldCount); + v8::Local otpl; + ENV_OBJECT_TEMPLATE(env, function_data, otpl, v8impl::kFunctionFieldCount); v8::Local cbdata = otpl->NewInstance(context).ToLocalChecked(); cbdata->SetInternalField( @@ -629,8 +647,8 @@ v8::Local CreateAccessorCallbackData(napi_env env, v8::Isolate* isolate = env->isolate; v8::Local context = isolate->GetCurrentContext(); - v8::Local otpl = v8::ObjectTemplate::New(isolate); - otpl->SetInternalFieldCount(v8impl::kAccessorFieldCount); + v8::Local otpl; + ENV_OBJECT_TEMPLATE(env, accessor_data, otpl, v8impl::kAccessorFieldCount); v8::Local cbdata = otpl->NewInstance(context).ToLocalChecked(); cbdata->SetInternalField( @@ -2008,11 +2026,10 @@ napi_status napi_wrap(napi_env env, v8::Local obj = value.As(); // Create a wrapper object with an internal field to hold the wrapped pointer. - v8::Local wrapperTemplate = - v8::ObjectTemplate::New(isolate); - wrapperTemplate->SetInternalFieldCount(1); + v8::Local wrapper_template; + ENV_OBJECT_TEMPLATE(env, wrap, wrapper_template, 1); v8::Local wrapper = - wrapperTemplate->NewInstance(context).ToLocalChecked(); + wrapper_template->NewInstance(context).ToLocalChecked(); wrapper->SetInternalField(0, v8::External::New(isolate, native_object)); // Insert the wrapper into the object's prototype chain.