Skip to content

Commit c81fd7c

Browse files
hashseedfhinkel
authored andcommitted
n-api: reimplement instanceof using V8 API
This uses the v8::Value::InstanceOf API exposed in V8 6.0 and should be performance neutral, if not improve it. By using V8's API, there is no longer the need to cache Symbol.hasInstance. PR-URL: #16143 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Franziska Hinkelmann <[email protected]> Reviewed-By: Timothy Gu <[email protected]>
1 parent 7832e69 commit c81fd7c

File tree

1 file changed

+6
-95
lines changed

1 file changed

+6
-95
lines changed

src/node_api.cc

+6-95
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,18 @@ napi_status napi_clear_last_error(napi_env env);
2929

3030
struct napi_env__ {
3131
explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate),
32-
has_instance_available(true), last_error() {}
32+
last_error() {}
3333
~napi_env__() {
3434
last_exception.Reset();
35-
has_instance.Reset();
3635
wrap_template.Reset();
3736
function_data_template.Reset();
3837
accessor_data_template.Reset();
3938
}
4039
v8::Isolate* isolate;
4140
v8::Persistent<v8::Value> last_exception;
42-
v8::Persistent<v8::Value> has_instance;
4341
v8::Persistent<v8::ObjectTemplate> wrap_template;
4442
v8::Persistent<v8::ObjectTemplate> function_data_template;
4543
v8::Persistent<v8::ObjectTemplate> accessor_data_template;
46-
bool has_instance_available;
4744
napi_extended_error_info last_error;
4845
};
4946

@@ -2693,98 +2690,12 @@ napi_status napi_instanceof(napi_env env,
26932690
return napi_set_last_error(env, napi_function_expected);
26942691
}
26952692

2696-
if (env->has_instance_available) {
2697-
napi_value value, js_result = nullptr, has_instance = nullptr;
2698-
napi_status status = napi_generic_failure;
2699-
napi_valuetype value_type;
2700-
2701-
// Get "Symbol" from the global object
2702-
if (env->has_instance.IsEmpty()) {
2703-
status = napi_get_global(env, &value);
2704-
if (status != napi_ok) return status;
2705-
status = napi_get_named_property(env, value, "Symbol", &value);
2706-
if (status != napi_ok) return status;
2707-
status = napi_typeof(env, value, &value_type);
2708-
if (status != napi_ok) return status;
2709-
2710-
// Get "hasInstance" from Symbol
2711-
if (value_type == napi_function) {
2712-
status = napi_get_named_property(env, value, "hasInstance", &value);
2713-
if (status != napi_ok) return status;
2714-
status = napi_typeof(env, value, &value_type);
2715-
if (status != napi_ok) return status;
2716-
2717-
// Store Symbol.hasInstance in a global persistent reference
2718-
if (value_type == napi_symbol) {
2719-
env->has_instance.Reset(env->isolate,
2720-
v8impl::V8LocalValueFromJsValue(value));
2721-
has_instance = value;
2722-
}
2723-
}
2724-
} else {
2725-
has_instance = v8impl::JsValueFromV8LocalValue(
2726-
v8::Local<v8::Value>::New(env->isolate, env->has_instance));
2727-
}
2728-
2729-
if (has_instance) {
2730-
status = napi_get_property(env, constructor, has_instance, &value);
2731-
if (status != napi_ok) return status;
2732-
status = napi_typeof(env, value, &value_type);
2733-
if (status != napi_ok) return status;
2734-
2735-
// Call the function to determine whether the object is an instance of the
2736-
// constructor
2737-
if (value_type == napi_function) {
2738-
status = napi_call_function(env, constructor, value, 1, &object,
2739-
&js_result);
2740-
if (status != napi_ok) return status;
2741-
return napi_get_value_bool(env, js_result, result);
2742-
}
2743-
}
2744-
2745-
env->has_instance_available = false;
2746-
}
2747-
2748-
// If running constructor[Symbol.hasInstance](object) did not work, we perform
2749-
// a traditional instanceof (early Node.js 6.x).
2750-
2751-
v8::Local<v8::String> prototype_string;
2752-
CHECK_NEW_FROM_UTF8(env, prototype_string, "prototype");
2753-
2754-
auto maybe_prototype = ctor->Get(context, prototype_string);
2755-
CHECK_MAYBE_EMPTY(env, maybe_prototype, napi_generic_failure);
2756-
2757-
v8::Local<v8::Value> prototype_property = maybe_prototype.ToLocalChecked();
2758-
if (!prototype_property->IsObject()) {
2759-
napi_throw_type_error(
2760-
env,
2761-
"ERR_NAPI_CONS_PROTOTYPE_OBJECT",
2762-
"Constructor.prototype must be an object");
2763-
2764-
return napi_set_last_error(env, napi_object_expected);
2765-
}
2766-
2767-
auto maybe_ctor = prototype_property->ToObject(context);
2768-
CHECK_MAYBE_EMPTY(env, maybe_ctor, napi_generic_failure);
2769-
ctor = maybe_ctor.ToLocalChecked();
2770-
2771-
v8::Local<v8::Value> current_obj = v8impl::V8LocalValueFromJsValue(object);
2772-
if (!current_obj->StrictEquals(ctor)) {
2773-
for (v8::Local<v8::Value> original_obj = current_obj;
2774-
!(current_obj->IsNull() || current_obj->IsUndefined());) {
2775-
if (current_obj->StrictEquals(ctor)) {
2776-
*result = !(original_obj->IsNumber() ||
2777-
original_obj->IsBoolean() ||
2778-
original_obj->IsString());
2779-
break;
2780-
}
2781-
v8::Local<v8::Object> obj;
2782-
CHECK_TO_OBJECT(env, context, obj, v8impl::JsValueFromV8LocalValue(
2783-
current_obj));
2784-
current_obj = obj->GetPrototype();
2785-
}
2786-
}
2693+
napi_status status = napi_generic_failure;
27872694

2695+
v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(object);
2696+
auto maybe_result = val->InstanceOf(context, ctor);
2697+
CHECK_MAYBE_NOTHING(env, maybe_result, status);
2698+
*result = maybe_result.FromJust();
27882699
return GET_RETURN_STATUS(env);
27892700
}
27902701

0 commit comments

Comments
 (0)