Skip to content

Commit 77df31f

Browse files
committed
node-api: disambiguate napi_add_finalizer
napi_add_finalizer doesn't support any operations related to napi_wrap. Remove the ambiguous statements in the doc about napi_wrap and avoid reusing the v8impl::Wrap call.
1 parent 7b1e153 commit 77df31f

File tree

3 files changed

+49
-50
lines changed

3 files changed

+49
-50
lines changed

doc/api/n-api.md

+5-11
Original file line numberDiff line numberDiff line change
@@ -5285,7 +5285,7 @@ napiVersion: 5
52855285
```c
52865286
napi_status napi_add_finalizer(napi_env env,
52875287
napi_value js_object,
5288-
void* native_object,
5288+
void* finalize_data,
52895289
napi_finalize finalize_cb,
52905290
void* finalize_hint,
52915291
napi_ref* result);
@@ -5294,10 +5294,9 @@ napi_status napi_add_finalizer(napi_env env,
52945294
* `[in] env`: The environment that the API is invoked under.
52955295
* `[in] js_object`: The JavaScript object to which the native data will be
52965296
attached.
5297-
* `[in] native_object`: The native data that will be attached to the JavaScript
5298-
object.
5297+
* `[in] finalize_data`: Optional data to be passed to `finalize_cb`.
52995298
* `[in] finalize_cb`: Native callback that will be used to free the
5300-
native data when the JavaScript object is ready for garbage-collection.
5299+
native data when the JavaScript object is been garbage-collected.
53015300
[`napi_finalize`][] provides more details.
53025301
* `[in] finalize_hint`: Optional contextual hint that is passed to the
53035302
finalize callback.
@@ -5306,14 +5305,9 @@ napi_status napi_add_finalizer(napi_env env,
53065305
Returns `napi_ok` if the API succeeded.
53075306

53085307
Adds a `napi_finalize` callback which will be called when the JavaScript object
5309-
in `js_object` is ready for garbage collection. This API is similar to
5310-
`napi_wrap()` except that:
5308+
in `js_object` is been garbage-collected.
53115309

5312-
* the native data cannot be retrieved later using `napi_unwrap()`,
5313-
* nor can it be removed later using `napi_remove_wrap()`, and
5314-
* the API can be called multiple times with different data items in order to
5315-
attach each of them to the JavaScript object, and
5316-
* the object manipulated by the API can be used with `napi_wrap()`.
5310+
This API can be called multiple times on a single JavaScript object.
53175311

53185312
_Caution_: The optional returned reference (if obtained) should be deleted via
53195313
[`napi_delete_reference`][] ONLY in response to the finalize callback

src/js_native_api.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_get_date_value(napi_env env,
492492
// Add finalizer for pointer
493493
NAPI_EXTERN napi_status NAPI_CDECL napi_add_finalizer(napi_env env,
494494
napi_value js_object,
495-
void* native_object,
495+
void* finalize_data,
496496
napi_finalize finalize_cb,
497497
void* finalize_hint,
498498
napi_ref* result);

src/js_native_api_v8.cc

+43-38
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,6 @@ class FunctionCallbackWrapper : public CallbackWrapperBase {
392392
}
393393
};
394394

395-
enum WrapType { retrievable, anonymous };
396-
397-
template <WrapType wrap_type>
398395
inline napi_status Wrap(napi_env env,
399396
napi_value js_object,
400397
void* native_object,
@@ -410,47 +407,36 @@ inline napi_status Wrap(napi_env env,
410407
RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
411408
v8::Local<v8::Object> obj = value.As<v8::Object>();
412409

413-
if (wrap_type == retrievable) {
414-
// If we've already wrapped this object, we error out.
415-
RETURN_STATUS_IF_FALSE(
416-
env,
417-
!obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
418-
.FromJust(),
419-
napi_invalid_arg);
420-
} else if (wrap_type == anonymous) {
421-
// If no finalize callback is provided, we error out.
422-
CHECK_ARG(env, finalize_cb);
423-
}
410+
// If we've already wrapped this object, we error out.
411+
RETURN_STATUS_IF_FALSE(
412+
env,
413+
!obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper)).FromJust(),
414+
napi_invalid_arg);
424415

425-
v8impl::Reference* reference = nullptr;
416+
// Create a self-deleting reference if the optional out-param result is not
417+
// set.
418+
bool delete_self = true;
426419
if (result != nullptr) {
427420
// The returned reference should be deleted via napi_delete_reference()
428421
// ONLY in response to the finalize callback invocation. (If it is deleted
429422
// before then, then the finalize callback will never be invoked.)
430423
// Therefore a finalize callback is required when returning a reference.
431424
CHECK_ARG(env, finalize_cb);
432-
reference = v8impl::Reference::New(
433-
env, obj, 0, false, finalize_cb, native_object, finalize_hint);
425+
delete_self = false;
426+
}
427+
428+
v8impl::Reference* reference = v8impl::Reference::New(
429+
env, obj, 0, delete_self, finalize_cb, native_object, finalize_hint);
430+
431+
if (result != nullptr) {
434432
*result = reinterpret_cast<napi_ref>(reference);
435-
} else {
436-
// Create a self-deleting reference.
437-
reference = v8impl::Reference::New(
438-
env,
439-
obj,
440-
0,
441-
true,
442-
finalize_cb,
443-
native_object,
444-
finalize_cb == nullptr ? nullptr : finalize_hint);
445-
}
446-
447-
if (wrap_type == retrievable) {
448-
CHECK(obj->SetPrivate(context,
449-
NAPI_PRIVATE_KEY(context, wrapper),
450-
v8::External::New(env->isolate, reference))
451-
.FromJust());
452433
}
453434

435+
CHECK(obj->SetPrivate(context,
436+
NAPI_PRIVATE_KEY(context, wrapper),
437+
v8::External::New(env->isolate, reference))
438+
.FromJust());
439+
454440
return GET_RETURN_STATUS(env);
455441
}
456442

@@ -2360,7 +2346,7 @@ napi_status NAPI_CDECL napi_wrap(napi_env env,
23602346
napi_finalize finalize_cb,
23612347
void* finalize_hint,
23622348
napi_ref* result) {
2363-
return v8impl::Wrap<v8impl::retrievable>(
2349+
return v8impl::Wrap(
23642350
env, js_object, native_object, finalize_cb, finalize_hint, result);
23652351
}
23662352

@@ -3176,12 +3162,31 @@ napi_status NAPI_CDECL napi_run_script(napi_env env,
31763162

31773163
napi_status NAPI_CDECL napi_add_finalizer(napi_env env,
31783164
napi_value js_object,
3179-
void* native_object,
3165+
void* finalize_data,
31803166
napi_finalize finalize_cb,
31813167
void* finalize_hint,
31823168
napi_ref* result) {
3183-
return v8impl::Wrap<v8impl::anonymous>(
3184-
env, js_object, native_object, finalize_cb, finalize_hint, result);
3169+
// Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
3170+
// JS exceptions.
3171+
CHECK_ENV(env);
3172+
CHECK_ARG(env, js_object);
3173+
CHECK_ARG(env, finalize_cb);
3174+
3175+
v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(js_object);
3176+
if (!(v8_value->IsObject() || v8_value->IsFunction())) {
3177+
return napi_set_last_error(env, napi_invalid_arg);
3178+
}
3179+
3180+
// Create a self-deleting reference if the optional out-param result is not
3181+
// set.
3182+
bool delete_self = result == nullptr;
3183+
v8impl::Reference* reference = v8impl::Reference::New(
3184+
env, v8_value, 0, delete_self, finalize_cb, finalize_data, finalize_hint);
3185+
3186+
if (result != nullptr) {
3187+
*result = reinterpret_cast<napi_ref>(reference);
3188+
}
3189+
return napi_clear_last_error(env);
31853190
}
31863191

31873192
napi_status NAPI_CDECL napi_adjust_external_memory(napi_env env,

0 commit comments

Comments
 (0)