From 5bbe733cd380db86b6cb078d29fe0eef0381b296 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 17 Mar 2023 11:52:25 -0700 Subject: [PATCH 1/6] node-api: extend type-tagging to externals Since externals behave as JavaScript objects on the JavaScript side, allow them to be type-tagged. Signed-off-by: Gabriel Schulhof --- doc/api/n-api.md | 31 +++++++++++--------- test/js-native-api/test_object/test.js | 5 ++++ test/js-native-api/test_object/test_object.c | 25 ++++++++++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index bcb53ef8df5b7b..aba9f41d91fce9 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -733,13 +733,13 @@ napiVersion: 8 --> A 128-bit value stored as two unsigned 64-bit integers. It serves as a UUID -with which JavaScript objects can be "tagged" in order to ensure that they are -of a certain type. This is a stronger check than [`napi_instanceof`][], because -the latter can report a false positive if the object's prototype has been -manipulated. Type-tagging is most useful in conjunction with [`napi_wrap`][] -because it ensures that the pointer retrieved from a wrapped object can be -safely cast to the native type corresponding to the type tag that had been -previously applied to the JavaScript object. +with which JavaScript objects or [externals][] can be "tagged" in order to +ensure that they are of a certain type. This is a stronger check than +[`napi_instanceof`][], because the latter can report a false positive if the +object's prototype has been manipulated. Type-tagging is most useful in +conjunction with [`napi_wrap`][] because it ensures that the pointer retrieved +from a wrapped object can be safely cast to the native type corresponding to the +type tag that had been previously applied to the JavaScript object. ```c typedef struct { @@ -4953,7 +4953,7 @@ To this end, Node-API provides type-tagging capabilities. A type tag is a 128-bit integer unique to the addon. Node-API provides the `napi_type_tag` structure for storing a type tag. When such a value is passed -along with a JavaScript object stored in a `napi_value` to +along with a JavaScript object or [external][] stored in a `napi_value` to `napi_type_tag_object()`, the JavaScript object will be "marked" with the type tag. The "mark" is invisible on the JavaScript side. When a JavaScript object arrives into a native binding, `napi_check_object_type_tag()` can be used @@ -5239,15 +5239,15 @@ napi_status napi_type_tag_object(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] js_object`: The JavaScript object to be marked. +* `[in] js_object`: The JavaScript object or [external][] to be marked. * `[in] type_tag`: The tag with which the object is to be marked. Returns `napi_ok` if the API succeeded. -Associates the value of the `type_tag` pointer with the JavaScript object. -`napi_check_object_type_tag()` can then be used to compare the tag that was -attached to the object with one owned by the addon to ensure that the object -has the right type. +Associates the value of the `type_tag` pointer with the JavaScript object or +[external][]. `napi_check_object_type_tag()` can then be used to compare the tag +that was attached to the object with one owned by the addon to ensure that the +object has the right type. If the object already has an associated type tag, this API will return `napi_invalid_arg`. @@ -5269,7 +5269,8 @@ napi_status napi_check_object_type_tag(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] js_object`: The JavaScript object whose type tag to examine. +* `[in] js_object`: The JavaScript object or [external][] whose type tag to + examine. * `[in] type_tag`: The tag with which to compare any tag found on the object. * `[out] result`: Whether the type tag given matched the type tag on the object. `false` is also returned if no type tag was found on the object. @@ -6373,6 +6374,8 @@ the add-on's file name during loading. [`Worker`]: worker_threads.md#class-worker [`async_hooks.executionAsyncResource()`]: async_hooks.md#async_hooksexecutionasyncresource [`global`]: globals.md#global +[external]: #napi_create_external +[externals]: #napi_create_external [`init` hooks]: async_hooks.md#initasyncid-type-triggerasyncid-resource [`napi_add_async_cleanup_hook`]: #napi_add_async_cleanup_hook [`napi_add_env_cleanup_hook`]: #napi_add_env_cleanup_hook diff --git a/test/js-native-api/test_object/test.js b/test/js-native-api/test_object/test.js index 012f737ba74b43..0a78bb594a890c 100644 --- a/test/js-native-api/test_object/test.js +++ b/test/js-native-api/test_object/test.js @@ -165,12 +165,15 @@ assert.strictEqual(newObject.test_string, 'test string'); const obj2 = test_object.TypeTaggedInstance(1); const obj3 = test_object.TypeTaggedInstance(2); const obj4 = test_object.TypeTaggedInstance(3); + const external = test_object.TypeTaggedExternal(12); + const plainExternal = test_object.PlainExternal(); // Verify that type tags are correctly accepted. assert.strictEqual(test_object.CheckTypeTag(0, obj1), true); assert.strictEqual(test_object.CheckTypeTag(1, obj2), true); assert.strictEqual(test_object.CheckTypeTag(2, obj3), true); assert.strictEqual(test_object.CheckTypeTag(3, obj4), true); + assert.strictEqual(test_object.CheckTypeTag(12, external), true); // Verify that wrongly tagged objects are rejected. assert.strictEqual(test_object.CheckTypeTag(0, obj2), false); @@ -180,10 +183,12 @@ assert.strictEqual(newObject.test_string, 'test string'); assert.strictEqual(test_object.CheckTypeTag(2, obj4), false); assert.strictEqual(test_object.CheckTypeTag(3, obj3), false); assert.strictEqual(test_object.CheckTypeTag(4, obj3), false); + assert.strictEqual(test_object.CheckTypeTag(19, external), false); // Verify that untagged objects are rejected. assert.strictEqual(test_object.CheckTypeTag(0, {}), false); assert.strictEqual(test_object.CheckTypeTag(1, {}), false); + assert.strictEqual(test_object.CheckTypeTag(12, plainExternal), false); } { diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index 3ae54a9b7cd65c..f60c8448893c28 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -627,6 +627,29 @@ TypeTaggedInstance(napi_env env, napi_callback_info info) { return instance; } +static napi_value +PlainExternal(napi_env env, napi_callback_info info) { + napi_value instance; + + NODE_API_CALL(env, napi_create_external(env, NULL, NULL, NULL, &instance)); + + return instance; +} + +static napi_value +TypeTaggedExternal(napi_env env, napi_callback_info info) { + size_t argc = 1; + uint32_t type_index; + napi_value instance, which_type; + + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); + NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); + NODE_API_CALL(env, napi_create_external(env, NULL, NULL, NULL, &instance)); + NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index])); + + return instance; +} + static napi_value CheckTypeTag(napi_env env, napi_callback_info info) { size_t argc = 2; @@ -669,6 +692,8 @@ napi_value Init(napi_env env, napi_value exports) { DECLARE_NODE_API_PROPERTY("TestSetProperty", TestSetProperty), DECLARE_NODE_API_PROPERTY("TestHasProperty", TestHasProperty), DECLARE_NODE_API_PROPERTY("TypeTaggedInstance", TypeTaggedInstance), + DECLARE_NODE_API_PROPERTY("TypeTaggedExternal", TypeTaggedExternal), + DECLARE_NODE_API_PROPERTY("PlainExternal", PlainExternal), DECLARE_NODE_API_PROPERTY("CheckTypeTag", CheckTypeTag), DECLARE_NODE_API_PROPERTY("TestGetProperty", TestGetProperty), DECLARE_NODE_API_PROPERTY("TestFreeze", TestFreeze), From 46882345ca4d347871243611de6cb66c31e8be65 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 17 Mar 2023 12:16:24 -0700 Subject: [PATCH 2/6] test: lint Signed-off-by: Gabriel Schulhof --- test/js-native-api/test_object/test_object.c | 69 ++++++++++---------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index f60c8448893c28..68719b8795f9c2 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -627,8 +627,7 @@ TypeTaggedInstance(napi_env env, napi_callback_info info) { return instance; } -static napi_value -PlainExternal(napi_env env, napi_callback_info info) { +static napi_value PlainExternal(napi_env env, napi_callback_info info) { napi_value instance; NODE_API_CALL(env, napi_create_external(env, NULL, NULL, NULL, &instance)); @@ -636,16 +635,17 @@ PlainExternal(napi_env env, napi_callback_info info) { return instance; } -static napi_value -TypeTaggedExternal(napi_env env, napi_callback_info info) { +static napi_value TypeTaggedExternal(napi_env env, napi_callback_info info) { size_t argc = 1; uint32_t type_index; napi_value instance, which_type; - NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); + NODE_API_CALL(env, + napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); NODE_API_CALL(env, napi_create_external(env, NULL, NULL, NULL, &instance)); - NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index])); + NODE_API_CALL(env, + napi_type_tag_object(env, instance, &type_tags[type_index])); return instance; } @@ -671,33 +671,36 @@ CheckTypeTag(napi_env env, napi_callback_info info) { EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NODE_API_PROPERTY("Get", Get), - DECLARE_NODE_API_PROPERTY("GetNamed", GetNamed), - DECLARE_NODE_API_PROPERTY("GetPropertyNames", GetPropertyNames), - DECLARE_NODE_API_PROPERTY("GetSymbolNames", GetSymbolNames), - DECLARE_NODE_API_PROPERTY("GetEnumerableWritableNames", GetEnumerableWritableNames), - DECLARE_NODE_API_PROPERTY("GetOwnWritableNames", GetOwnWritableNames), - DECLARE_NODE_API_PROPERTY("GetEnumerableConfigurableNames", GetEnumerableConfigurableNames), - DECLARE_NODE_API_PROPERTY("GetOwnConfigurableNames", GetOwnConfigurableNames), - DECLARE_NODE_API_PROPERTY("Set", Set), - DECLARE_NODE_API_PROPERTY("SetNamed", SetNamed), - DECLARE_NODE_API_PROPERTY("Has", Has), - DECLARE_NODE_API_PROPERTY("HasNamed", HasNamed), - DECLARE_NODE_API_PROPERTY("HasOwn", HasOwn), - DECLARE_NODE_API_PROPERTY("Delete", Delete), - DECLARE_NODE_API_PROPERTY("New", New), - DECLARE_NODE_API_PROPERTY("Inflate", Inflate), - DECLARE_NODE_API_PROPERTY("Wrap", Wrap), - DECLARE_NODE_API_PROPERTY("Unwrap", Unwrap), - DECLARE_NODE_API_PROPERTY("TestSetProperty", TestSetProperty), - DECLARE_NODE_API_PROPERTY("TestHasProperty", TestHasProperty), - DECLARE_NODE_API_PROPERTY("TypeTaggedInstance", TypeTaggedInstance), - DECLARE_NODE_API_PROPERTY("TypeTaggedExternal", TypeTaggedExternal), - DECLARE_NODE_API_PROPERTY("PlainExternal", PlainExternal), - DECLARE_NODE_API_PROPERTY("CheckTypeTag", CheckTypeTag), - DECLARE_NODE_API_PROPERTY("TestGetProperty", TestGetProperty), - DECLARE_NODE_API_PROPERTY("TestFreeze", TestFreeze), - DECLARE_NODE_API_PROPERTY("TestSeal", TestSeal), + DECLARE_NODE_API_PROPERTY("Get", Get), + DECLARE_NODE_API_PROPERTY("GetNamed", GetNamed), + DECLARE_NODE_API_PROPERTY("GetPropertyNames", GetPropertyNames), + DECLARE_NODE_API_PROPERTY("GetSymbolNames", GetSymbolNames), + DECLARE_NODE_API_PROPERTY("GetEnumerableWritableNames", + GetEnumerableWritableNames), + DECLARE_NODE_API_PROPERTY("GetOwnWritableNames", GetOwnWritableNames), + DECLARE_NODE_API_PROPERTY("GetEnumerableConfigurableNames", + GetEnumerableConfigurableNames), + DECLARE_NODE_API_PROPERTY("GetOwnConfigurableNames", + GetOwnConfigurableNames), + DECLARE_NODE_API_PROPERTY("Set", Set), + DECLARE_NODE_API_PROPERTY("SetNamed", SetNamed), + DECLARE_NODE_API_PROPERTY("Has", Has), + DECLARE_NODE_API_PROPERTY("HasNamed", HasNamed), + DECLARE_NODE_API_PROPERTY("HasOwn", HasOwn), + DECLARE_NODE_API_PROPERTY("Delete", Delete), + DECLARE_NODE_API_PROPERTY("New", New), + DECLARE_NODE_API_PROPERTY("Inflate", Inflate), + DECLARE_NODE_API_PROPERTY("Wrap", Wrap), + DECLARE_NODE_API_PROPERTY("Unwrap", Unwrap), + DECLARE_NODE_API_PROPERTY("TestSetProperty", TestSetProperty), + DECLARE_NODE_API_PROPERTY("TestHasProperty", TestHasProperty), + DECLARE_NODE_API_PROPERTY("TypeTaggedInstance", TypeTaggedInstance), + DECLARE_NODE_API_PROPERTY("TypeTaggedExternal", TypeTaggedExternal), + DECLARE_NODE_API_PROPERTY("PlainExternal", PlainExternal), + DECLARE_NODE_API_PROPERTY("CheckTypeTag", CheckTypeTag), + DECLARE_NODE_API_PROPERTY("TestGetProperty", TestGetProperty), + DECLARE_NODE_API_PROPERTY("TestFreeze", TestFreeze), + DECLARE_NODE_API_PROPERTY("TestSeal", TestSeal), }; init_test_null(env, exports); From e2f4876f399dc5caa169e28116ed6c2b75665c12 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 17 Mar 2023 12:17:25 -0700 Subject: [PATCH 3/6] doc: lint --- doc/api/n-api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index aba9f41d91fce9..1f8b3a1ee2e9b0 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -6374,8 +6374,6 @@ the add-on's file name during loading. [`Worker`]: worker_threads.md#class-worker [`async_hooks.executionAsyncResource()`]: async_hooks.md#async_hooksexecutionasyncresource [`global`]: globals.md#global -[external]: #napi_create_external -[externals]: #napi_create_external [`init` hooks]: async_hooks.md#initasyncid-type-triggerasyncid-resource [`napi_add_async_cleanup_hook`]: #napi_add_async_cleanup_hook [`napi_add_env_cleanup_hook`]: #napi_add_env_cleanup_hook @@ -6441,6 +6439,8 @@ the add-on's file name during loading. [async_hooks `type`]: async_hooks.md#type [context-aware addons]: addons.md#context-aware-addons [docs]: https://github.com/nodejs/node-addon-api#api-documentation +[external]: #napi_create_external +[externals]: #napi_create_external [global scope]: globals.md [gyp-next]: https://github.com/nodejs/gyp-next [module scope]: modules.md#the-module-scope From 7893ae433ea25a383b1d4e5dc018228816409973 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 17 Mar 2023 12:38:14 -0700 Subject: [PATCH 4/6] doc: lint --- doc/api/n-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 1f8b3a1ee2e9b0..a9a59e76d3180a 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -5270,7 +5270,7 @@ napi_status napi_check_object_type_tag(napi_env env, * `[in] env`: The environment that the API is invoked under. * `[in] js_object`: The JavaScript object or [external][] whose type tag to - examine. + examine. * `[in] type_tag`: The tag with which to compare any tag found on the object. * `[out] result`: Whether the type tag given matched the type tag on the object. `false` is also returned if no type tag was found on the object. From ee07cd737dd0cea404e45783ca867963b7e96fd1 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 17 Mar 2023 19:48:00 -0700 Subject: [PATCH 5/6] test: verify type index --- test/js-native-api/test_object/test.js | 26 +++++++++++++++++--- test/js-native-api/test_object/test_object.c | 25 ++++++++++++++----- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/test/js-native-api/test_object/test.js b/test/js-native-api/test_object/test.js index 0a78bb594a890c..670ae200a35bec 100644 --- a/test/js-native-api/test_object/test.js +++ b/test/js-native-api/test_object/test.js @@ -165,15 +165,26 @@ assert.strictEqual(newObject.test_string, 'test string'); const obj2 = test_object.TypeTaggedInstance(1); const obj3 = test_object.TypeTaggedInstance(2); const obj4 = test_object.TypeTaggedInstance(3); - const external = test_object.TypeTaggedExternal(12); + const external = test_object.TypeTaggedExternal(2); const plainExternal = test_object.PlainExternal(); + // Verify that we do not allow type tag indices greater than the largest + // available index. + assert.throws(() => test_object.TypeTaggedInstance(39), { + name: 'RangeError', + message: 'Invalid type index', + }); + assert.throws(() => test_object.TypeTaggedExternal(39), { + name: 'RangeError', + message: 'Invalid type index', + }); + // Verify that type tags are correctly accepted. assert.strictEqual(test_object.CheckTypeTag(0, obj1), true); assert.strictEqual(test_object.CheckTypeTag(1, obj2), true); assert.strictEqual(test_object.CheckTypeTag(2, obj3), true); assert.strictEqual(test_object.CheckTypeTag(3, obj4), true); - assert.strictEqual(test_object.CheckTypeTag(12, external), true); + assert.strictEqual(test_object.CheckTypeTag(2, external), true); // Verify that wrongly tagged objects are rejected. assert.strictEqual(test_object.CheckTypeTag(0, obj2), false); @@ -183,12 +194,19 @@ assert.strictEqual(newObject.test_string, 'test string'); assert.strictEqual(test_object.CheckTypeTag(2, obj4), false); assert.strictEqual(test_object.CheckTypeTag(3, obj3), false); assert.strictEqual(test_object.CheckTypeTag(4, obj3), false); - assert.strictEqual(test_object.CheckTypeTag(19, external), false); + assert.strictEqual(test_object.CheckTypeTag(0, external), false); + assert.strictEqual(test_object.CheckTypeTag(1, external), false); + assert.strictEqual(test_object.CheckTypeTag(3, external), false); + assert.strictEqual(test_object.CheckTypeTag(4, external), false); // Verify that untagged objects are rejected. assert.strictEqual(test_object.CheckTypeTag(0, {}), false); assert.strictEqual(test_object.CheckTypeTag(1, {}), false); - assert.strictEqual(test_object.CheckTypeTag(12, plainExternal), false); + assert.strictEqual(test_object.CheckTypeTag(0, plainExternal), false); + assert.strictEqual(test_object.CheckTypeTag(1, plainExternal), false); + assert.strictEqual(test_object.CheckTypeTag(2, plainExternal), false); + assert.strictEqual(test_object.CheckTypeTag(3, plainExternal), false); + assert.strictEqual(test_object.CheckTypeTag(4, plainExternal), false); } { diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index 68719b8795f9c2..a89c532c793eec 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -605,13 +605,23 @@ static napi_value TestSeal(napi_env env, } // We create two type tags. They are basically 128-bit UUIDs. -static const napi_type_tag type_tags[5] = { - { 0xdaf987b3cc62481a, 0xb745b0497f299531 }, - { 0xbb7936c374084d9b, 0xa9548d0762eeedb9 }, - { 0xa5ed9ce2e4c00c38, 0 }, - { 0, 0 }, - { 0xa5ed9ce2e4c00c38, 0xdaf987b3cc62481a }, +#define TYPE_TAG_COUNT 5 +static const napi_type_tag type_tags[TYPE_TAG_COUNT] = { + {0xdaf987b3cc62481a, 0xb745b0497f299531}, + {0xbb7936c374084d9b, 0xa9548d0762eeedb9}, + {0xa5ed9ce2e4c00c38, 0}, + {0, 0}, + {0xa5ed9ce2e4c00c38, 0xdaf987b3cc62481a}, }; +#define VALIDATE_TYPE_INDEX(env, type_index) \ + do { \ + if ((type_index) >= TYPE_TAG_COUNT) { \ + NODE_API_CALL((env), \ + napi_throw_range_error((env), \ + "NODE_API_TEST_INVALID_TYPE_INDEX", \ + "Invalid type index")); \ + } \ + } while (0) static napi_value TypeTaggedInstance(napi_env env, napi_callback_info info) { @@ -621,6 +631,7 @@ TypeTaggedInstance(napi_env env, napi_callback_info info) { NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); + VALIDATE_TYPE_INDEX(env, type_index); NODE_API_CALL(env, napi_create_object(env, &instance)); NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index])); @@ -643,6 +654,7 @@ static napi_value TypeTaggedExternal(napi_env env, napi_callback_info info) { NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); + VALIDATE_TYPE_INDEX(env, type_index); NODE_API_CALL(env, napi_create_external(env, NULL, NULL, NULL, &instance)); NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index])); @@ -659,6 +671,7 @@ CheckTypeTag(napi_env env, napi_callback_info info) { NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); NODE_API_CALL(env, napi_get_value_uint32(env, argv[0], &type_index)); + VALIDATE_TYPE_INDEX(env, type_index); NODE_API_CALL(env, napi_check_object_type_tag(env, argv[1], &type_tags[type_index], From d2d9cfdfb7a9411cbb309093c3b50c79adbe0dc2 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Sun, 19 Mar 2023 19:35:26 -0700 Subject: [PATCH 6/6] test: Use non-NULL external data --- test/js-native-api/test_object/test_object.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index a89c532c793eec..eb5aa2071e30a3 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -638,10 +638,14 @@ TypeTaggedInstance(napi_env env, napi_callback_info info) { return instance; } +// V8 will not allowe us to construct an external with a NULL data value. +#define IN_LIEU_OF_NULL ((void*)0x1) + static napi_value PlainExternal(napi_env env, napi_callback_info info) { napi_value instance; - NODE_API_CALL(env, napi_create_external(env, NULL, NULL, NULL, &instance)); + NODE_API_CALL( + env, napi_create_external(env, IN_LIEU_OF_NULL, NULL, NULL, &instance)); return instance; } @@ -655,7 +659,8 @@ static napi_value TypeTaggedExternal(napi_env env, napi_callback_info info) { napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL)); NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index)); VALIDATE_TYPE_INDEX(env, type_index); - NODE_API_CALL(env, napi_create_external(env, NULL, NULL, NULL, &instance)); + NODE_API_CALL( + env, napi_create_external(env, IN_LIEU_OF_NULL, NULL, NULL, &instance)); NODE_API_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index]));