Skip to content

Commit

Permalink
napi: cache Symbol.hasInstance
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Schulhof committed Mar 29, 2017
1 parent 6541beb commit d88b98b
Showing 1 changed file with 42 additions and 22 deletions.
64 changes: 42 additions & 22 deletions src/node_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ class napi_env__ {
explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), last_error() {}
~napi_env__() {
last_exception.Reset();
has_instance.Reset();
}
v8::Isolate* isolate;
v8::Persistent<v8::Value> last_exception;
v8::Persistent<v8::Value> has_instance;
napi_extended_error_info last_error;
};

Expand Down Expand Up @@ -2109,41 +2111,59 @@ napi_status napi_instanceof(napi_env env,
return napi_set_last_error(env, napi_function_expected);
}

napi_value value, js_result;
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 "hasInstance" from Symbol
if (value_type == napi_function) {
status = napi_get_named_property(env, value, "hasInstance", &value);
fprintf(stderr, "Checking env->has_instance\n");

if (env->has_instance.IsEmpty()) {

fprintf(stderr, "env->has_instance is empty\n");

// 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;

// Retrieve the function at the Symbol(hasInstance) key of the constructor
if (value_type == napi_symbol) {
status = napi_get_property(env, constructor, value, &value);
// 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;

// Call the function to determine whether the object is an instance of the
// constructor
if (value_type == napi_function) {
status = napi_call_function(env, constructor, value, 1, &object,
&js_result);
if (status != napi_ok) return status;
return napi_get_value_bool(env, js_result, result);
// If Symbol.hasInstance is of type symbol we've found it
if (value_type == napi_symbol) {
has_instance = value;
env->has_instance.Reset(env->isolate,
v8impl::V8LocalValueFromJsValue(value));
}
}
} else {
fprintf(stderr, "env->has_instance is not empty\n");
has_instance = v8impl::JsValueFromV8LocalValue(
v8::Local<v8::Value>::New(env->isolate, env->has_instance));
fprintf(stderr, "env->has_instance assigned from cache\n");
}

if (has_instance) {
status = napi_get_property(env, constructor, value, &value);
if (status != napi_ok) return status;
status = napi_typeof(env, value, &value_type);
if (status != napi_ok) return status;

// Call the function to determine whether the object is an instance of the
// constructor
if (value_type == napi_function) {
status = napi_call_function(env, constructor, value, 1, &object,
&js_result);
if (status != napi_ok) return status;
return napi_get_value_bool(env, js_result, result);
}
}

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

0 comments on commit d88b98b

Please sign in to comment.