diff --git a/src/node_api.cc b/src/node_api.cc index be30a8461ac3cc..cac4c113dc78ec 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -23,12 +23,16 @@ void napi_clear_last_error(napi_env env); class napi_env__ { public: - explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), last_error() {} + explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), + has_instance_available(true), last_error() {} ~napi_env__() { last_exception.Reset(); + has_instance.Reset(); } v8::Isolate* isolate; v8::Persistent last_exception; + v8::Persistent has_instance; + bool has_instance_available; napi_extended_error_info last_error; }; @@ -2156,28 +2160,43 @@ napi_status napi_instanceof(napi_env env, return napi_set_last_error(env, napi_function_expected); } - napi_value value, js_result; - napi_status status; - napi_valuetype value_type; + if (env->has_instance_available) { + napi_value value, js_result, has_instance = nullptr; + napi_status status; + napi_valuetype value_type; - // Get "Symbol" from the global object - status = napi_get_global(env, &value); - if (status != napi_ok) return status; - status = napi_get_named_property(env, value, "Symbol", &value); - if (status != napi_ok) return status; - status = napi_typeof(env, value, &value_type); - if (status != napi_ok) return status; + // Get "Symbol" from the global object + if (env->has_instance.IsEmpty()) { + status = napi_get_global(env, &value); + if (status != napi_ok) return status; + status = napi_get_named_property(env, value, "Symbol", &value); + if (status != napi_ok) return status; + status = napi_typeof(env, value, &value_type); + if (status != napi_ok) return status; - // Get "hasInstance" from Symbol - if (value_type == napi_function) { - status = napi_get_named_property(env, value, "hasInstance", &value); - if (status != napi_ok) return status; - status = napi_typeof(env, value, &value_type); - if (status != napi_ok) return status; + // Get "hasInstance" from Symbol + if (value_type == napi_function) { + status = napi_get_named_property(env, value, "hasInstance", &value); + if (status != napi_ok) return status; + status = napi_typeof(env, value, &value_type); + if (status != napi_ok) return status; + + // Store Symbol.hasInstance in a global persistent reference + if (value_type == napi_symbol) { + env->has_instance.Reset(env->isolate, + v8impl::V8LocalValueFromJsValue(value)); + if (status != napi_ok) return status; + has_instance = value; + } + } + } else { + has_instance = v8impl::JsValueFromV8LocalValue( + v8::Local::New(env->isolate, env->has_instance)); + if (status != napi_ok) return status; + } - // Retrieve the function at the Symbol(hasInstance) key of the constructor - if (value_type == napi_symbol) { - status = napi_get_property(env, constructor, value, &value); + if (has_instance) { + status = napi_get_property(env, constructor, has_instance, &value); if (status != napi_ok) return status; status = napi_typeof(env, value, &value_type); if (status != napi_ok) return status; @@ -2191,6 +2210,8 @@ napi_status napi_instanceof(napi_env env, return napi_get_value_bool(env, js_result, result); } } + + env->has_instance_available = false; } // If running constructor[Symbol.hasInstance](object) did not work, we perform