Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Fix napi_create_reference to work correctly with integers #380

Closed
kfarnung opened this issue Aug 26, 2017 · 5 comments · Fixed by #406
Closed

Fix napi_create_reference to work correctly with integers #380

kfarnung opened this issue Aug 26, 2017 · 5 comments · Fixed by #406
Assignees

Comments

@kfarnung
Copy link
Contributor

  • Version: master
  • Platform: windows (probably others)
  • Subsystem: n-api

The N-API implementation of napi_create_reference uses JsCreateWeakReference. If a reference is created for an integer then there is an access violation during the GC update of the weak reference map. I proposed a possible fix in chakra-core/ChakraCore#3591, but once an approved fix is found we'll need to re-enable test_general/test.

kfarnung added a commit to kfarnung/node-chakracore that referenced this issue Aug 26, 2017
Marking test_general/test flaky until
nodejs#380 is fixed.
@MSLaguana
Copy link
Contributor

It looks like test_general/test has continued to evolve and is broken for an additional reason now: It attempts to create an object, wrap it, lose the JS reference to the object, force a GC, and ensure that the finalizer passed when wrapping was called. At the moment it looks like we might be mid-gc when the JS tries to force a gc, and so we complete that GC but it doesn't delete the only-just-now-created object.

Other than that, there is some discussion about whether it makes sense to create references to primitive values at nodejs/node-addon-api#131

@gabrielschulhof
Copy link

gabrielschulhof commented Sep 7, 2017 via email

@digitalinfinity
Copy link
Contributor

@gabrielschulhof semantically, what does a reference to a primitive mean if a primitive is not heap allocated? ChakraCore's JSRT returns JsValueRefs that are opaque (can be either pointers to heap allocated objects or primitive values)- are you suggesting in the case of primitive values, we always return boxed (heap allocated) values? That seems to be a rather expensive perf cost for supporting obscure cases, no? Alternatively, if you're not suggesting that, then when you say that we create references to primitive values, are you suggesting that we box the value as part of the CreateWeakReference api? That also seems fraught since that value would get collected at the next GC since no one would have a strong handle to that, just a weak one.

So it's unclear what the desired behavior should be. My instinct is that if napi has a chance to define this behavior more concretely right now, we should just say that napi_create_weakreference can return an error if the napi_value passed in can't be weakly referenced- that exposes some concept of VM internals but then again, so does napi_create_weakreference, and this approach allows VM vendors to not be "boxed in" 😄

@gabrielschulhof
Copy link

I think it's pretty safe to return napi_invalid_arg for values that cannot be referenced. Any engine worth its salt should be able to provide persistent references to objects and functions. V8 is known to have features that are redundant, or have been rendered redundant by its evolution.

We might even go so far as to document that only objects and functions can be retained as napi_refs. After all, primitive values are better stored as their native equivalents.

@gabrielschulhof
Copy link

In fact, we document that the napi_value to which a reference is created must be an object. So, I was basically abusing the napi_create_reference() mechanism. My bad.

gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Sep 9, 2017
The binding testing napi_wrap() creates references to primitives passed
into the binding in its second parameter. This is unnecessary and not
at all the point of the test. Additionally, creating persistent
references to primitive values may not be supported by all VMs, since
primitives are best persisted in their native form.

Instead, the point of the test is to make sure that the finalize
callback gets called when it should get called, that it gets called
with the correct pointer, and that it does not get called when it
should not get called. Creating persistent references is not necessary
for verifying this.

Re: nodejs/node-chakracore#380
gabrielschulhof pushed a commit to nodejs/node that referenced this issue Sep 13, 2017
The binding testing napi_wrap() creates references to primitives passed
into the binding in its second parameter. This is unnecessary and not
at all the point of the test. Additionally, creating persistent
references to primitive values may not be supported by all VMs, since
primitives are best persisted in their native form.

Instead, the point of the test is to make sure that the finalize
callback gets called when it should get called, that it gets called
with the correct pointer, and that it does not get called when it
should not get called. Creating persistent references is not necessary
for verifying this.

PR-URL: #15289
Reviewed-By: Jason Ginchereau <jasongin@microsoft.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Re: nodejs/node-chakracore#380
addaleax pushed a commit to addaleax/node that referenced this issue Sep 13, 2017
The binding testing napi_wrap() creates references to primitives passed
into the binding in its second parameter. This is unnecessary and not
at all the point of the test. Additionally, creating persistent
references to primitive values may not be supported by all VMs, since
primitives are best persisted in their native form.

Instead, the point of the test is to make sure that the finalize
callback gets called when it should get called, that it gets called
with the correct pointer, and that it does not get called when it
should not get called. Creating persistent references is not necessary
for verifying this.

PR-URL: nodejs#15289
Reviewed-By: Jason Ginchereau <jasongin@microsoft.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Re: nodejs/node-chakracore#380
jasnell pushed a commit to nodejs/node that referenced this issue Sep 20, 2017
The binding testing napi_wrap() creates references to primitives passed
into the binding in its second parameter. This is unnecessary and not
at all the point of the test. Additionally, creating persistent
references to primitive values may not be supported by all VMs, since
primitives are best persisted in their native form.

Instead, the point of the test is to make sure that the finalize
callback gets called when it should get called, that it gets called
with the correct pointer, and that it does not get called when it
should not get called. Creating persistent references is not necessary
for verifying this.

PR-URL: #15289
Reviewed-By: Jason Ginchereau <jasongin@microsoft.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Re: nodejs/node-chakracore#380
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Apr 10, 2018
The binding testing napi_wrap() creates references to primitives passed
into the binding in its second parameter. This is unnecessary and not
at all the point of the test. Additionally, creating persistent
references to primitive values may not be supported by all VMs, since
primitives are best persisted in their native form.

Instead, the point of the test is to make sure that the finalize
callback gets called when it should get called, that it gets called
with the correct pointer, and that it does not get called when it
should not get called. Creating persistent references is not necessary
for verifying this.

PR-URL: nodejs#15289
Reviewed-By: Jason Ginchereau <jasongin@microsoft.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Re: nodejs/node-chakracore#380
MylesBorins pushed a commit to nodejs/node that referenced this issue Apr 16, 2018
The binding testing napi_wrap() creates references to primitives passed
into the binding in its second parameter. This is unnecessary and not
at all the point of the test. Additionally, creating persistent
references to primitive values may not be supported by all VMs, since
primitives are best persisted in their native form.

Instead, the point of the test is to make sure that the finalize
callback gets called when it should get called, that it gets called
with the correct pointer, and that it does not get called when it
should not get called. Creating persistent references is not necessary
for verifying this.

Backport-PR-URL: #19447
PR-URL: #15289
Reviewed-By: Jason Ginchereau <jasongin@microsoft.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Re: nodejs/node-chakracore#380
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants