Skip to content

Commit 952cb0d

Browse files
author
Gabriel Schulhof
committed
napi: cache Symbol.hasInstance (nodejs#209)
Fixes nodejs#209
1 parent ce80f95 commit 952cb0d

File tree

1 file changed

+42
-22
lines changed

1 file changed

+42
-22
lines changed

src/node_api.cc

+42-22
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ class napi_env__ {
2626
explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), last_error() {}
2727
~napi_env__() {
2828
last_exception.Reset();
29+
has_instance.Reset();
2930
}
3031
v8::Isolate* isolate;
3132
v8::Persistent<v8::Value> last_exception;
33+
v8::Persistent<v8::Value> has_instance;
3234
napi_extended_error_info last_error;
3335
};
3436

@@ -2113,41 +2115,59 @@ napi_status napi_instanceof(napi_env env,
21132115
return napi_set_last_error(env, napi_function_expected);
21142116
}
21152117

2116-
napi_value value, js_result;
2118+
napi_value value, js_result, has_instance = nullptr;
21172119
napi_status status;
21182120
napi_valuetype value_type;
21192121

2120-
// Get "Symbol" from the global object
2121-
status = napi_get_global(env, &value);
2122-
if (status != napi_ok) return status;
2123-
status = napi_get_named_property(env, value, "Symbol", &value);
2124-
if (status != napi_ok) return status;
2125-
status = napi_typeof(env, value, &value_type);
2126-
if (status != napi_ok) return status;
2127-
2128-
// Get "hasInstance" from Symbol
2129-
if (value_type == napi_function) {
2130-
status = napi_get_named_property(env, value, "hasInstance", &value);
2122+
fprintf(stderr, "Checking env->has_instance\n");
2123+
2124+
if (env->has_instance.IsEmpty()) {
2125+
2126+
fprintf(stderr, "env->has_instance is empty\n");
2127+
2128+
// Get "Symbol" from the global object
2129+
status = napi_get_global(env, &value);
2130+
if (status != napi_ok) return status;
2131+
status = napi_get_named_property(env, value, "Symbol", &value);
21312132
if (status != napi_ok) return status;
21322133
status = napi_typeof(env, value, &value_type);
21332134
if (status != napi_ok) return status;
21342135

2135-
// Retrieve the function at the Symbol(hasInstance) key of the constructor
2136-
if (value_type == napi_symbol) {
2137-
status = napi_get_property(env, constructor, value, &value);
2136+
// Get "hasInstance" from Symbol
2137+
if (value_type == napi_function) {
2138+
status = napi_get_named_property(env, value, "hasInstance", &value);
21382139
if (status != napi_ok) return status;
21392140
status = napi_typeof(env, value, &value_type);
21402141
if (status != napi_ok) return status;
21412142

2142-
// Call the function to determine whether the object is an instance of the
2143-
// constructor
2144-
if (value_type == napi_function) {
2145-
status = napi_call_function(env, constructor, value, 1, &object,
2146-
&js_result);
2147-
if (status != napi_ok) return status;
2148-
return napi_get_value_bool(env, js_result, result);
2143+
// If Symbol.hasInstance is of type symbol we've found it
2144+
if (value_type == napi_symbol) {
2145+
has_instance = value;
2146+
env->has_instance.Reset(env->isolate,
2147+
v8impl::V8LocalValueFromJsValue(value));
21492148
}
21502149
}
2150+
} else {
2151+
fprintf(stderr, "env->has_instance is not empty\n");
2152+
has_instance = v8impl::JsValueFromV8LocalValue(
2153+
v8::Local<v8::Value>::New(env->isolate, env->has_instance));
2154+
fprintf(stderr, "env->has_instance assigned from cache\n");
2155+
}
2156+
2157+
if (has_instance) {
2158+
status = napi_get_property(env, constructor, value, &value);
2159+
if (status != napi_ok) return status;
2160+
status = napi_typeof(env, value, &value_type);
2161+
if (status != napi_ok) return status;
2162+
2163+
// Call the function to determine whether the object is an instance of the
2164+
// constructor
2165+
if (value_type == napi_function) {
2166+
status = napi_call_function(env, constructor, value, 1, &object,
2167+
&js_result);
2168+
if (status != napi_ok) return status;
2169+
return napi_get_value_bool(env, js_result, result);
2170+
}
21512171
}
21522172

21532173
// If running constructor[Symbol.hasInstance](object) did not work, we perform

0 commit comments

Comments
 (0)