Skip to content

Commit

Permalink
Add additional comments
Browse files Browse the repository at this point in the history
  • Loading branch information
kjvalencik committed Nov 17, 2021
1 parent 5e16313 commit 53cf8f9
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 0 deletions.
5 changes: 5 additions & 0 deletions crates/neon-runtime/src/napi/fun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,17 @@ where
ptr::null_mut(),
);

// If adding the finalizer fails the closure will leak, but it would
// be unsafe to drop it because there's no guarantee V8 won't use the
// pointer.
assert_eq!(status, napi::Status::Ok);
}

Ok(out)
}

// C ABI compatible function for invoking a boxed closure from the data field
// of a Node-API JavaScript function
unsafe extern "C" fn call_boxed<F>(env: Env, info: napi::CallbackInfo) -> Local
where
F: Fn(Env, napi::CallbackInfo) -> Local + 'static,
Expand Down
2 changes: 2 additions & 0 deletions test/napi/lib/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ describe('JsFunction', function() {
});

(global.gc ? it : it.skip)('should drop function when going out of scope', function(cb) {
// Run from an `IIFE` to ensure that `f` is out of scope and eligible for garbage
// collection when `global.gc()` is executed.
(() => {
const msg = "Hello, World!";
const f = addon.caller_with_drop_callback(() => msg, cb);
Expand Down
11 changes: 11 additions & 0 deletions test/napi/src/js/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,23 @@ pub fn is_construct(mut cx: FunctionContext) -> JsResult<JsObject> {
Ok(this)
}

// `function caller_with_drop_callback(wrappedCallback, dropCallback)`
//
// `wrappedCallback` will be called each time the returned function is
// called to verify we have successfully dynamically created a function
// from a closure.
//
// `dropCallback` will be called when the closure is dropped to test that
// closures are not leaking. The unit test should pass the test callback here.
pub fn caller_with_drop_callback(mut cx: FunctionContext) -> JsResult<JsFunction> {
struct Callback {
f: Root<JsFunction>,
drop: Option<Root<JsFunction>>,
channel: Channel,
}

// Call `dropCallback` when `Callback` is dropped as a sentinel to observe
// the closure isn't leaked when the function is garbage collected
impl Drop for Callback {
fn drop(&mut self) {
let callback = self.drop.take();
Expand All @@ -163,6 +173,7 @@ pub fn caller_with_drop_callback(mut cx: FunctionContext) -> JsResult<JsFunction
let this = cx.undefined();
let args: [Handle<JsValue>; 0] = [];

// Execute the unit test callback to end the test successfully
callback
.unwrap()
.into_inner(&mut cx)
Expand Down

0 comments on commit 53cf8f9

Please sign in to comment.