Skip to content

Commit 8de356a

Browse files
author
Gabriel Schulhof
committed
napi: cache Symbol.hasInstance (#209)
Fixes #209 Closes #214
1 parent e06795b commit 8de356a

1 file changed

Lines changed: 42 additions & 20 deletions

File tree

src/node_api.cc

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@ void napi_clear_last_error(napi_env env);
2323

2424
class napi_env__ {
2525
public:
26-
explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), last_error() {}
26+
explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate),
27+
has_instance_available(true), last_error() {}
2728
~napi_env__() {
2829
last_exception.Reset();
30+
has_instance.Reset();
2931
}
3032
v8::Isolate* isolate;
3133
v8::Persistent<v8::Value> last_exception;
34+
v8::Persistent<v8::Value> has_instance;
35+
bool has_instance_available;
3236
napi_extended_error_info last_error;
3337
};
3438

@@ -2129,28 +2133,44 @@ napi_status napi_instanceof(napi_env env,
21292133
return napi_set_last_error(env, napi_function_expected);
21302134
}
21312135

2132-
napi_value value, js_result;
2133-
napi_status status;
2134-
napi_valuetype value_type;
2136+
if (env->has_instance_available) {
2137+
napi_value value, js_result, has_instance = nullptr;
2138+
napi_status status;
2139+
napi_valuetype value_type;
21352140

2136-
// Get "Symbol" from the global object
2137-
status = napi_get_global(env, &value);
2138-
if (status != napi_ok) return status;
2139-
status = napi_get_named_property(env, value, "Symbol", &value);
2140-
if (status != napi_ok) return status;
2141-
status = napi_typeof(env, value, &value_type);
2142-
if (status != napi_ok) return status;
2141+
if (env->has_instance.IsEmpty()) {
21432142

2144-
// Get "hasInstance" from Symbol
2145-
if (value_type == napi_function) {
2146-
status = napi_get_named_property(env, value, "hasInstance", &value);
2147-
if (status != napi_ok) return status;
2148-
status = napi_typeof(env, value, &value_type);
2149-
if (status != napi_ok) return status;
2143+
// Get "Symbol" from the global object
2144+
status = napi_get_global(env, &value);
2145+
if (status != napi_ok) return status;
2146+
status = napi_get_named_property(env, value, "Symbol", &value);
2147+
if (status != napi_ok) return status;
2148+
status = napi_typeof(env, value, &value_type);
2149+
if (status != napi_ok) return status;
21502150

2151-
// Retrieve the function at the Symbol(hasInstance) key of the constructor
2152-
if (value_type == napi_symbol) {
2153-
status = napi_get_property(env, constructor, value, &value);
2151+
// Get "hasInstance" from Symbol
2152+
if (value_type == napi_function) {
2153+
status = napi_get_named_property(env, value, "hasInstance", &value);
2154+
if (status != napi_ok) return status;
2155+
status = napi_typeof(env, value, &value_type);
2156+
if (status != napi_ok) return status;
2157+
2158+
// Store Symbol.hasInstance in a global persistent reference
2159+
if (value_type == napi_symbol) {
2160+
env->has_instance.Reset(env->isolate,
2161+
v8impl::V8LocalValueFromJsValue(value));
2162+
if (status != napi_ok) return status;
2163+
has_instance = value;
2164+
}
2165+
}
2166+
} else {
2167+
has_instance = v8impl::JsValueFromV8LocalValue(
2168+
v8::Local<v8::Value>::New(env->isolate, env->has_instance));
2169+
if (status != napi_ok) return status;
2170+
}
2171+
2172+
if (has_instance) {
2173+
status = napi_get_property(env, constructor, has_instance, &value);
21542174
if (status != napi_ok) return status;
21552175
status = napi_typeof(env, value, &value_type);
21562176
if (status != napi_ok) return status;
@@ -2164,6 +2184,8 @@ napi_status napi_instanceof(napi_env env,
21642184
return napi_get_value_bool(env, js_result, result);
21652185
}
21662186
}
2187+
2188+
env->has_instance_available = false;
21672189
}
21682190

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

0 commit comments

Comments
 (0)