You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Is it possible to determine the type of an NAPI::Object in a non-global context? #764
The code to determine if source is a Date object is failing apparently because source has been allocated outside the global context.
The author of the node-sqlite3 issue has identified the IsDate method as a way to address this issue. But is there another more general approach that would work to identify type of an NAPI::Object in a non-global context?
Object.InstanceOf ends up calling napi_instanceof which has the following implementation
napi_status napi_instanceof(napi_env env,
napi_value object,
napi_value constructor,
bool* result) {
NAPI_PREAMBLE(env);
CHECK_ARG(env, object);
CHECK_ARG(env, result);
*result = false;
v8::Local<v8::Object> ctor;
v8::Local<v8::Context> context = env->context();
CHECK_TO_OBJECT(env, context, ctor, constructor);
if (!ctor->IsFunction()) {
napi_throw_type_error(env,
"ERR_NAPI_CONS_FUNCTION",
"Constructor must be a function");
returnnapi_set_last_error(env, napi_function_expected);
}
napi_status status = napi_generic_failure;
v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(object);
auto maybe_result = val->InstanceOf(context, ctor);
CHECK_MAYBE_NOTHING(env, maybe_result, status);
*result = maybe_result.FromJust();
returnGET_RETURN_STATUS(env);
}
I assume the problem is that mismatch between the context that was active when the env was created and the context active when the call is made.
@gabrielschulhof, @addaleax some methods call v8::Local<v8::Context> context = env->isolate->GetCurrentContext(); instead of v8::Localv8::Context context = env->context();` do you remember off hand why we would use one in some places and the other for other cases?
I'm wondering if for napi_instanceof we should be using env->isolate->GetCurrentContext(); but then that lead to the question if why/when we would use env->context().
I assume the problem is that mismatch between the context that was active when the env was created and the context active when the call is made.
Yes. The instanceof operator checks whether the .prototype property of the right-hand side appears in the prototype chain of the left-hand side. Each vm Context comes with its own set of builtins, including Date and Date.prototype. As a consequence, the Date.prototype from one Context does not show up in the prototype chain of a Date instance from another context, and instanceof returns false. In particular, this is not specific to N-API.
do you remember off hand why we would use one in some places and the other for other cases?
I'm wondering if for napi_instanceof we should be using env->isolate->GetCurrentContext(); but then that lead to the question if why/when we would use env->context().
Currently, this is irrelevant because Node.js is not actually supporting multi-Context addons. Once we do, using env->isolate->GetCurrentContext() (or storing the context on the env itself) would be the right thing in a lot of situations. However, that mismatch is not related to this issue, passing either context would result in the same return value.
(For the most part, passing a context to V8 functions is relevant for cases in which a new Error object is being thrown – e.g. because the right-hand side isn’t a constructor.)
The author of the node-sqlite3 issue has identified the IsDate method as a way to address this issue. But is there another more general approach that would work to identify type of an NAPI::Object in a non-global context?
napi_typeof and the napi_is_... family are the only native brand checks that I know of. However, the relevant question is what you are actually wanting to find out about the object – if you want napi_get_date_value(), then yes, napi_is_date() will give you the right answer. But if you want to use some other API, e.g. date.getUTCDay(), then you’d best check for the presence of that method (since it can be overriden or removed, and napi_is_date does not provide that information).
Thanks for the clarification on contexts. Would you agree that the 2 places we env->isolate->GetCurrentContext() should be updated to use env->context() to be consistent with the rest of the places we use the context?
Would you agree that the 2 places we env->isolate->GetCurrentContext() should be updated to use env->context() to be consistent with the rest of the places we use the context?
Activity
mhdawson commentedon Jul 14, 2020
Object.InstanceOf ends up calling
napi_instanceofwhich has the following implementationI assume the problem is that mismatch between the context that was active when the env was created and the context active when the call is made.
@gabrielschulhof, @addaleax some methods call
v8::Local<v8::Context> context = env->isolate->GetCurrentContext();instead of v8::Localv8::Context context = env->context();` do you remember off hand why we would use one in some places and the other for other cases?I'm wondering if for napi_instanceof we should be using
env->isolate->GetCurrentContext();but then that lead to the question if why/when we would use env->context().addaleax commentedon Jul 14, 2020
Yes. The
instanceofoperator checks whether the.prototypeproperty of the right-hand side appears in the prototype chain of the left-hand side. Each vm Context comes with its own set of builtins, includingDateandDate.prototype. As a consequence, theDate.prototypefrom one Context does not show up in the prototype chain of aDateinstance from another context, andinstanceofreturns false. In particular, this is not specific to N-API.Currently, this is irrelevant because Node.js is not actually supporting multi-Context addons. Once we do, using
env->isolate->GetCurrentContext()(or storing the context on theenvitself) would be the right thing in a lot of situations. However, that mismatch is not related to this issue, passing either context would result in the same return value.(For the most part, passing a context to V8 functions is relevant for cases in which a new Error object is being thrown – e.g. because the right-hand side isn’t a constructor.)
napi_typeofand thenapi_is_...family are the only native brand checks that I know of. However, the relevant question is what you are actually wanting to find out about the object – if you wantnapi_get_date_value(), then yes,napi_is_date()will give you the right answer. But if you want to use some other API, e.g.date.getUTCDay(), then you’d best check for the presence of that method (since it can be overriden or removed, andnapi_is_datedoes not provide that information).mhdawson commentedon Jul 15, 2020
Thanks for the clarification on contexts. Would you agree that the 2 places we
env->isolate->GetCurrentContext()should be updated to useenv->context()to be consistent with the rest of the places we use the context?addaleax commentedon Jul 15, 2020
I think that would be fine, yes.
gabrielschulhof commentedon Aug 3, 2020
In summary, it sounds like proper support for native add-ons to correctly support
vm.runInNewContext()needs to be built from the core on up.mhdawson commentedon Nov 10, 2020
@jschlight I think this has been answered, is it ok to close ?
n-api: improve consistency of how we get context
n-api: improve consistency of how we get context
n-api: improve consistency of how we get context
jschlight commentedon Nov 25, 2020
Yes @mhdawson Thanks for the ping.
n-api: improve consistency of how we get context
n-api: improve consistency of how we get context
n-api: improve consistency of how we get context