Skip to content

Commit ae5cbda

Browse files
authored
node-api: add napi_set_prototype
PR-URL: #60711 Refs: #60670 Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Vladimir Morozov <vmorozov@microsoft.com>
1 parent 9458e45 commit ae5cbda

File tree

6 files changed

+110
-27
lines changed

6 files changed

+110
-27
lines changed

doc/api/n-api.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5059,6 +5059,28 @@ added to it, as well as marking all existing properties as non-configurable.
50595059
This is described in [Section 19.1.2.20](https://tc39.es/ecma262/#sec-object.seal)
50605060
of the ECMA-262 specification.
50615061

5062+
#### `node_api_set_prototype`
5063+
5064+
<!-- YAML
5065+
added: REPLACEME
5066+
-->
5067+
5068+
> Stability: 1 - Experimental
5069+
5070+
```c
5071+
napi_status node_api_set_prototype(napi_env env,
5072+
napi_value object,
5073+
napi_value value);
5074+
```
5075+
5076+
* `[in] env`: The environment that the Node-API call is invoked under.
5077+
* `[in] object`: The object on which to set the prototype.
5078+
* `[in] value`: The prototype value.
5079+
5080+
Returns `napi_ok` if the API succeeded.
5081+
5082+
This API sets the prototype of the `Object` passed in.
5083+
50625084
## Working with JavaScript functions
50635085

50645086
Node-API provides a set of APIs that allow JavaScript code to

src/js_native_api.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_coerce_to_string(napi_env env,
197197
napi_value* result);
198198

199199
// Methods to work with Objects
200+
#ifdef NAPI_EXPERIMENTAL
201+
#define NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE
202+
NAPI_EXTERN napi_status NAPI_CDECL node_api_set_prototype(napi_env env,
203+
napi_value object,
204+
napi_value value);
205+
#endif
200206
NAPI_EXTERN napi_status NAPI_CDECL napi_get_prototype(napi_env env,
201207
napi_value object,
202208
napi_value* result);

src/js_native_api_v8.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,26 @@ napi_status NAPI_CDECL napi_strict_equals(napi_env env,
15671567
return GET_RETURN_STATUS(env);
15681568
}
15691569

1570+
napi_status NAPI_CDECL node_api_set_prototype(napi_env env,
1571+
napi_value object,
1572+
napi_value value) {
1573+
NAPI_PREAMBLE(env);
1574+
CHECK_ARG(env, value);
1575+
1576+
v8::Local<v8::Context> context = env->context();
1577+
v8::Local<v8::Object> obj;
1578+
1579+
CHECK_TO_OBJECT(env, context, obj, object);
1580+
1581+
v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1582+
1583+
v8::Maybe<bool> set_maybe = obj->SetPrototypeV2(context, val);
1584+
1585+
RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(
1586+
env, set_maybe.FromMaybe(false), napi_generic_failure);
1587+
return GET_RETURN_STATUS(env);
1588+
}
1589+
15701590
napi_status NAPI_CDECL napi_get_prototype(napi_env env,
15711591
napi_value object,
15721592
napi_value* result) {

test/js-native-api/test_general/binding.gyp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
"target_name": "test_general",
55
"sources": [
66
"test_general.c"
7-
]
7+
],
8+
"defines": [
9+
"NAPI_EXPERIMENTAL"
10+
],
811
}
912
]
1013
}

test/js-native-api/test_general/test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,18 @@ class ExtendedClass extends BaseClass {
1818

1919
const baseObject = new BaseClass();
2020
const extendedObject = new ExtendedClass();
21+
const nullProtoObject = { __proto__: null };
2122

2223
// Test napi_strict_equals
2324
assert.ok(test_general.testStrictEquals(val1, val1));
2425
assert.strictEqual(test_general.testStrictEquals(val1, val2), false);
2526
assert.ok(test_general.testStrictEquals(val2, val3));
2627

28+
// Test napi_set_prototype
29+
test_general.testSetPrototype(nullProtoObject, Object.prototype);
30+
assert.strictEqual(Object.getPrototypeOf(nullProtoObject),
31+
Object.prototype);
32+
2733
// Test napi_get_prototype
2834
assert.strictEqual(test_general.testGetPrototype(baseObject),
2935
Object.getPrototypeOf(baseObject));

test/js-native-api/test_general/test_general.c

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ static napi_value testStrictEquals(napi_env env, napi_callback_info info) {
2323
return result;
2424
}
2525

26+
static napi_value testSetPrototype(napi_env env, napi_callback_info info) {
27+
size_t argc = 2;
28+
napi_value args[2];
29+
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
30+
31+
NODE_API_CALL(env, node_api_set_prototype(env, args[0], args[1]));
32+
33+
return NULL;
34+
}
35+
2636
static napi_value testGetPrototype(napi_env env, napi_callback_info info) {
2737
size_t argc = 1;
2838
napi_value args[1];
@@ -137,7 +147,7 @@ static napi_value testNapiTypeof(napi_env env, napi_callback_info info) {
137147
}
138148

139149
static bool deref_item_called = false;
140-
static void deref_item(napi_env env, void* data, void* hint) {
150+
static void deref_item(node_api_nogc_env env, void* data, void* hint) {
141151
(void) hint;
142152

143153
NODE_API_ASSERT_RETURN_VOID(env, data == &deref_item_called,
@@ -156,7 +166,7 @@ static napi_value deref_item_was_called(napi_env env, napi_callback_info info) {
156166

157167
static napi_value wrap_first_arg(napi_env env,
158168
napi_callback_info info,
159-
napi_finalize finalizer,
169+
node_api_basic_finalize finalizer,
160170
void* data) {
161171
size_t argc = 1;
162172
napi_value to_wrap;
@@ -195,7 +205,7 @@ static napi_value remove_wrap(napi_env env, napi_callback_info info) {
195205
}
196206

197207
static bool finalize_called = false;
198-
static void test_finalize(napi_env env, void* data, void* hint) {
208+
static void test_finalize(node_api_nogc_env env, void* data, void* hint) {
199209
finalize_called = true;
200210
}
201211

@@ -242,6 +252,15 @@ static void finalizer_only_callback(napi_env env, void* data, void* hint) {
242252
NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, js_cb_ref));
243253
}
244254

255+
static void schedule_finalizer_only_callback(node_api_nogc_env env,
256+
void* data,
257+
void* hint) {
258+
NODE_API_CALL_RETURN_VOID(
259+
(napi_env)env,
260+
node_api_post_finalizer(
261+
(napi_env)env, finalizer_only_callback, data, NULL));
262+
}
263+
245264
static napi_value add_finalizer_only(napi_env env, napi_callback_info info) {
246265
size_t argc = 2;
247266
napi_value argv[2];
@@ -250,8 +269,12 @@ static napi_value add_finalizer_only(napi_env env, napi_callback_info info) {
250269
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
251270
NODE_API_CALL(env, napi_create_reference(env, argv[1], 1, &js_cb_ref));
252271
NODE_API_CALL(env,
253-
napi_add_finalizer(
254-
env, argv[0], js_cb_ref, finalizer_only_callback, NULL, NULL));
272+
napi_add_finalizer(env,
273+
argv[0],
274+
js_cb_ref,
275+
schedule_finalizer_only_callback,
276+
NULL,
277+
NULL));
255278
return NULL;
256279
}
257280

@@ -262,7 +285,9 @@ static const char* env_cleanup_finalizer_messages[] = {
262285
"second wrap"
263286
};
264287

265-
static void cleanup_env_finalizer(napi_env env, void* data, void* hint) {
288+
static void cleanup_env_finalizer(node_api_nogc_env env,
289+
void* data,
290+
void* hint) {
266291
(void) env;
267292
(void) hint;
268293

@@ -286,26 +311,27 @@ static napi_value env_cleanup_wrap(napi_env env, napi_callback_info info) {
286311
EXTERN_C_START
287312
napi_value Init(napi_env env, napi_value exports) {
288313
napi_property_descriptor descriptors[] = {
289-
DECLARE_NODE_API_PROPERTY("testStrictEquals", testStrictEquals),
290-
DECLARE_NODE_API_PROPERTY("testGetPrototype", testGetPrototype),
291-
DECLARE_NODE_API_PROPERTY("testGetVersion", testGetVersion),
292-
DECLARE_NODE_API_PROPERTY("testNapiRun", testNapiRun),
293-
DECLARE_NODE_API_PROPERTY("doInstanceOf", doInstanceOf),
294-
DECLARE_NODE_API_PROPERTY("getUndefined", getUndefined),
295-
DECLARE_NODE_API_PROPERTY("getNull", getNull),
296-
DECLARE_NODE_API_PROPERTY("createNapiError", createNapiError),
297-
DECLARE_NODE_API_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup),
298-
DECLARE_NODE_API_PROPERTY("testNapiTypeof", testNapiTypeof),
299-
DECLARE_NODE_API_PROPERTY("wrap", wrap),
300-
DECLARE_NODE_API_PROPERTY("envCleanupWrap", env_cleanup_wrap),
301-
DECLARE_NODE_API_PROPERTY("unwrap", unwrap),
302-
DECLARE_NODE_API_PROPERTY("removeWrap", remove_wrap),
303-
DECLARE_NODE_API_PROPERTY("addFinalizerOnly", add_finalizer_only),
304-
DECLARE_NODE_API_PROPERTY("testFinalizeWrap", test_finalize_wrap),
305-
DECLARE_NODE_API_PROPERTY("finalizeWasCalled", finalize_was_called),
306-
DECLARE_NODE_API_PROPERTY("derefItemWasCalled", deref_item_was_called),
307-
DECLARE_NODE_API_PROPERTY("testAdjustExternalMemory", testAdjustExternalMemory)
308-
};
314+
DECLARE_NODE_API_PROPERTY("testStrictEquals", testStrictEquals),
315+
DECLARE_NODE_API_PROPERTY("testSetPrototype", testSetPrototype),
316+
DECLARE_NODE_API_PROPERTY("testGetPrototype", testGetPrototype),
317+
DECLARE_NODE_API_PROPERTY("testGetVersion", testGetVersion),
318+
DECLARE_NODE_API_PROPERTY("testNapiRun", testNapiRun),
319+
DECLARE_NODE_API_PROPERTY("doInstanceOf", doInstanceOf),
320+
DECLARE_NODE_API_PROPERTY("getUndefined", getUndefined),
321+
DECLARE_NODE_API_PROPERTY("getNull", getNull),
322+
DECLARE_NODE_API_PROPERTY("createNapiError", createNapiError),
323+
DECLARE_NODE_API_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup),
324+
DECLARE_NODE_API_PROPERTY("testNapiTypeof", testNapiTypeof),
325+
DECLARE_NODE_API_PROPERTY("wrap", wrap),
326+
DECLARE_NODE_API_PROPERTY("envCleanupWrap", env_cleanup_wrap),
327+
DECLARE_NODE_API_PROPERTY("unwrap", unwrap),
328+
DECLARE_NODE_API_PROPERTY("removeWrap", remove_wrap),
329+
DECLARE_NODE_API_PROPERTY("addFinalizerOnly", add_finalizer_only),
330+
DECLARE_NODE_API_PROPERTY("testFinalizeWrap", test_finalize_wrap),
331+
DECLARE_NODE_API_PROPERTY("finalizeWasCalled", finalize_was_called),
332+
DECLARE_NODE_API_PROPERTY("derefItemWasCalled", deref_item_was_called),
333+
DECLARE_NODE_API_PROPERTY("testAdjustExternalMemory",
334+
testAdjustExternalMemory)};
309335

310336
NODE_API_CALL(env, napi_define_properties(
311337
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));

0 commit comments

Comments
 (0)