Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using v8::Private::ForApi for N-API object wrapping #14367

Closed
TimothyGu opened this issue Jul 19, 2017 · 10 comments
Closed

Using v8::Private::ForApi for N-API object wrapping #14367

TimothyGu opened this issue Jul 19, 2017 · 10 comments
Labels
node-api Issues and PRs related to the Node-API.

Comments

@TimothyGu
Copy link
Member

TimothyGu commented Jul 19, 2017

  • Version: master
  • Platform: all
  • Subsystem: n-api

Currently, N-API's object wrapping uses v8::External with a const char* as a brand check. However, v8::Externals are known to be inefficient, and the fact that one such External is created for every wrapped object only worsens the problem. On the other hand, V8 provides the mechanism necessary for cross-napi_env brand checks in v8::Private::ForApi, which is like a C++-private version of Symbol.for(), and v8::Object::HasPrivate/SetPrivate. Handles to these v8::Privates can then be cached per napi_env in a Persistent. Similar features are also available in earlier V8 versions, as implemented in @kkoopa's NAN.

I'd be willing to cook up a PR for this.

/cc @nodejs/n-api @gabrielschulhof @jasongin

@TimothyGu TimothyGu added the node-api Issues and PRs related to the Node-API. label Jul 19, 2017
@gabrielschulhof
Copy link
Contributor

@TimothyGu

I'm thinking that we can use this mechanism to attach a hidden property to isolate->GetCurrentContext()->Global() such that its value is an External containing the napi_env. That way we could achieve napi_env sharing across modules without the need for a std::map and a node::Mutex.

How kosher is it to attach such hidden properties to the global object?

@addaleax
Copy link
Member

@gabrielschulhof I’m not sure how that relates to the issue above, but in any case: That sounds fine as long as you’re aware that Node code can run in different contexts with different globals.

@gabrielschulhof
Copy link
Contributor

@addaleax are modules loaded per-context or per-isolate? That is, if there is one isolate with two different contexts, can the same module instance be used in both?

The relation to this issue is that ideally, we'd type-check via FunctionTemplate::HasInstance() and we'd store FunctionTemplates in the napi_env for the various object instances we need to create. We currently store ObjectTemplate instances in the napi_env, and that forces us to use weaker type checking.

However, we need to make sure that we never end up with a situation where an instance created from one FunctionTemplate in one module ends up being used in a different module wherein there is another napi_env with its own copy of a FunctionTemplate serving the same purpose, because then HasInstance() will return false even though it should return true because conceptually the instance is an instance of the FunctionTemplate, just the one from a different napi_env.

@gabrielschulhof
Copy link
Contributor

Aha!

// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
// when two contexts try to load the same shared object. Maybe have a shadow
// cache that's a plain C list or hash table that's shared across contexts?

@TimothyGu
Copy link
Member Author

@gabrielschulhof Well, can't comment about the process of dynamic loading from different contexts, but v8::Private::ForApi() is isolate-global so the v8::Private you get in one context is the exact same as the v8::Private you get from another context.

About reusing napi_env for the purpose of using FunctionTemplate::HasInstance, beware that IIRC HasInstance doesn't check prototypes of the object like n-api currently does.

I don't see any problem with attaching hidden properties to the global object. Not like hidden properties are, you know, visible from JS, or even C++ if the consumer is not actively trying to find it.

@gabrielschulhof
Copy link
Contributor

@addaleax under what circumstances does Node create multiple contexts and run JS code in them?

@addaleax
Copy link
Member

@gabrielschulhof It’s programatically available in the built-in vm module, anybody can create new contexts as they wish

@bnoordhuis
Copy link
Member

It's also used in projects like electron and nw.js that create a context per tab.

TimothyGu pushed a commit that referenced this issue Jul 26, 2017
Store the `napi_env` on the global object at a private key. This gives
us one `napi_env` per context.

Refs: #14367
PR-URL: #14217
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Timothy Gu <[email protected]>
addaleax pushed a commit that referenced this issue Jul 27, 2017
Store the `napi_env` on the global object at a private key. This gives
us one `napi_env` per context.

Refs: #14367
PR-URL: #14217
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Timothy Gu <[email protected]>
@TimothyGu
Copy link
Member Author

@gabrielschulhof I think this issue could be closed now, right?

@gabrielschulhof
Copy link
Contributor

gabrielschulhof commented Aug 9, 2017 via email

gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Feb 2, 2018
MylesBorins pushed a commit that referenced this issue Feb 20, 2018
PR-URL: #18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: #14367
MylesBorins pushed a commit that referenced this issue Feb 21, 2018
PR-URL: #18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: #14367
MylesBorins pushed a commit that referenced this issue Feb 21, 2018
PR-URL: #18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: #14367
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Apr 10, 2018
Store the `napi_env` on the global object at a private key. This gives
us one `napi_env` per context.

Refs: nodejs#14367
PR-URL: nodejs#14217
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Timothy Gu <[email protected]>
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Apr 12, 2018
PR-URL: nodejs#18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: nodejs#14367
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Apr 16, 2018
PR-URL: nodejs#18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: nodejs#14367
MylesBorins pushed a commit that referenced this issue Apr 16, 2018
Store the `napi_env` on the global object at a private key. This gives
us one `napi_env` per context.

Refs: #14367
Backport-PR-URL: #19447
PR-URL: #14217
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Timothy Gu <[email protected]>
MylesBorins pushed a commit that referenced this issue Apr 16, 2018
Backport-PR-URL: #19447
PR-URL: #18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: #14367
MylesBorins pushed a commit that referenced this issue May 1, 2018
Backport-PR-URL: #19265
PR-URL: #18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: #14367
MayaLekova pushed a commit to MayaLekova/node that referenced this issue May 8, 2018
PR-URL: nodejs#18311
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Fixes: nodejs#14367
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
node-api Issues and PRs related to the Node-API.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants