Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions deps/crates/crates.gyp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
'variables': {
'cargo_vendor_dir': './vendor',
'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/>(cargo_build_mode)/<(STATIC_LIB_PREFIX)node_crates<(STATIC_LIB_SUFFIX)',
},
'targets': [
{
Expand All @@ -14,7 +15,15 @@
],
'link_settings': {
'libraries': [
'<(SHARED_INTERMEDIATE_DIR)/>(cargo_build_mode)/libnode_crates.a',
'<(node_crates_libpath)',
],
'conditions': [
['OS=="win"', {
'libraries': [
'-lntdll',
'-luserenv'
],
}],
],
},
'actions': [
Expand All @@ -24,7 +33,7 @@
'<@(_sources)'
],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/>(cargo_build_mode)/libnode_crates.a'
'<(node_crates_libpath)'
],
'action': [
'cargo',
Expand Down
22 changes: 22 additions & 0 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5059,6 +5059,28 @@ added to it, as well as marking all existing properties as non-configurable.
This is described in [Section 19.1.2.20](https://tc39.es/ecma262/#sec-object.seal)
of the ECMA-262 specification.

#### `node_api_set_prototype`

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental

```c
napi_status node_api_set_prototype(napi_env env,
napi_value object,
napi_value value);
```

* `[in] env`: The environment that the Node-API call is invoked under.
* `[in] object`: The object on which to set the prototype.
* `[in] value`: The prototype value.

Returns `napi_ok` if the API succeeded.

This API sets the prototype of the `Object` passed in.

## Working with JavaScript functions

Node-API provides a set of APIs that allow JavaScript code to
Expand Down
6 changes: 6 additions & 0 deletions src/js_native_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_coerce_to_string(napi_env env,
napi_value* result);

// Methods to work with Objects
#ifdef NAPI_EXPERIMENTAL
#define NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE
NAPI_EXTERN napi_status NAPI_CDECL node_api_set_prototype(napi_env env,
napi_value object,
napi_value value);
#endif
NAPI_EXTERN napi_status NAPI_CDECL napi_get_prototype(napi_env env,
napi_value object,
napi_value* result);
Expand Down
20 changes: 20 additions & 0 deletions src/js_native_api_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,26 @@ napi_status NAPI_CDECL napi_strict_equals(napi_env env,
return GET_RETURN_STATUS(env);
}

napi_status NAPI_CDECL node_api_set_prototype(napi_env env,
napi_value object,
napi_value value) {
NAPI_PREAMBLE(env);
CHECK_ARG(env, value);

v8::Local<v8::Context> context = env->context();
v8::Local<v8::Object> obj;

CHECK_TO_OBJECT(env, context, obj, object);

v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);

v8::Maybe<bool> set_maybe = obj->SetPrototypeV2(context, val);

RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(
env, set_maybe.FromMaybe(false), napi_generic_failure);
return GET_RETURN_STATUS(env);
}

napi_status NAPI_CDECL napi_get_prototype(napi_env env,
napi_value object,
napi_value* result) {
Expand Down
21 changes: 21 additions & 0 deletions test/es-module/test-esm-import-meta-resolve-hooks.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Flags: --experimental-import-meta-resolve
import '../common/index.mjs';
import assert from 'node:assert';
import { registerHooks } from 'node:module';

// Asserts that import.meta.resolve invokes loader hooks registered via `registerHooks`.

registerHooks({
resolve(specifier, context, defaultResolve) {
if (specifier === 'custom:hooked') {
return {
shortCircuit: true,
url: new URL('./test-esm-import-meta.mjs', import.meta.url).href,
};
}
return defaultResolve(specifier, context);
},
});

assert.strictEqual(import.meta.resolve('custom:hooked'),
new URL('./test-esm-import-meta.mjs', import.meta.url).href);
5 changes: 4 additions & 1 deletion test/js-native-api/test_general/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"target_name": "test_general",
"sources": [
"test_general.c"
]
],
"defines": [
"NAPI_EXPERIMENTAL"
],
}
]
}
6 changes: 6 additions & 0 deletions test/js-native-api/test_general/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,18 @@ class ExtendedClass extends BaseClass {

const baseObject = new BaseClass();
const extendedObject = new ExtendedClass();
const nullProtoObject = { __proto__: null };

// Test napi_strict_equals
assert.ok(test_general.testStrictEquals(val1, val1));
assert.strictEqual(test_general.testStrictEquals(val1, val2), false);
assert.ok(test_general.testStrictEquals(val2, val3));

// Test napi_set_prototype
test_general.testSetPrototype(nullProtoObject, Object.prototype);
assert.strictEqual(Object.getPrototypeOf(nullProtoObject),
Object.prototype);

// Test napi_get_prototype
assert.strictEqual(test_general.testGetPrototype(baseObject),
Object.getPrototypeOf(baseObject));
Expand Down
78 changes: 52 additions & 26 deletions test/js-native-api/test_general/test_general.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ static napi_value testStrictEquals(napi_env env, napi_callback_info info) {
return result;
}

static napi_value testSetPrototype(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));

NODE_API_CALL(env, node_api_set_prototype(env, args[0], args[1]));

return NULL;
}

static napi_value testGetPrototype(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
Expand Down Expand Up @@ -137,7 +147,7 @@ static napi_value testNapiTypeof(napi_env env, napi_callback_info info) {
}

static bool deref_item_called = false;
static void deref_item(napi_env env, void* data, void* hint) {
static void deref_item(node_api_nogc_env env, void* data, void* hint) {
(void) hint;

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

static napi_value wrap_first_arg(napi_env env,
napi_callback_info info,
napi_finalize finalizer,
node_api_basic_finalize finalizer,
void* data) {
size_t argc = 1;
napi_value to_wrap;
Expand Down Expand Up @@ -195,7 +205,7 @@ static napi_value remove_wrap(napi_env env, napi_callback_info info) {
}

static bool finalize_called = false;
static void test_finalize(napi_env env, void* data, void* hint) {
static void test_finalize(node_api_nogc_env env, void* data, void* hint) {
finalize_called = true;
}

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

static void schedule_finalizer_only_callback(node_api_nogc_env env,
void* data,
void* hint) {
NODE_API_CALL_RETURN_VOID(
(napi_env)env,
node_api_post_finalizer(
(napi_env)env, finalizer_only_callback, data, NULL));
}

static napi_value add_finalizer_only(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value argv[2];
Expand All @@ -250,8 +269,12 @@ static napi_value add_finalizer_only(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_create_reference(env, argv[1], 1, &js_cb_ref));
NODE_API_CALL(env,
napi_add_finalizer(
env, argv[0], js_cb_ref, finalizer_only_callback, NULL, NULL));
napi_add_finalizer(env,
argv[0],
js_cb_ref,
schedule_finalizer_only_callback,
NULL,
NULL));
return NULL;
}

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

static void cleanup_env_finalizer(napi_env env, void* data, void* hint) {
static void cleanup_env_finalizer(node_api_nogc_env env,
void* data,
void* hint) {
(void) env;
(void) hint;

Expand All @@ -286,26 +311,27 @@ static napi_value env_cleanup_wrap(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("testStrictEquals", testStrictEquals),
DECLARE_NODE_API_PROPERTY("testGetPrototype", testGetPrototype),
DECLARE_NODE_API_PROPERTY("testGetVersion", testGetVersion),
DECLARE_NODE_API_PROPERTY("testNapiRun", testNapiRun),
DECLARE_NODE_API_PROPERTY("doInstanceOf", doInstanceOf),
DECLARE_NODE_API_PROPERTY("getUndefined", getUndefined),
DECLARE_NODE_API_PROPERTY("getNull", getNull),
DECLARE_NODE_API_PROPERTY("createNapiError", createNapiError),
DECLARE_NODE_API_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup),
DECLARE_NODE_API_PROPERTY("testNapiTypeof", testNapiTypeof),
DECLARE_NODE_API_PROPERTY("wrap", wrap),
DECLARE_NODE_API_PROPERTY("envCleanupWrap", env_cleanup_wrap),
DECLARE_NODE_API_PROPERTY("unwrap", unwrap),
DECLARE_NODE_API_PROPERTY("removeWrap", remove_wrap),
DECLARE_NODE_API_PROPERTY("addFinalizerOnly", add_finalizer_only),
DECLARE_NODE_API_PROPERTY("testFinalizeWrap", test_finalize_wrap),
DECLARE_NODE_API_PROPERTY("finalizeWasCalled", finalize_was_called),
DECLARE_NODE_API_PROPERTY("derefItemWasCalled", deref_item_was_called),
DECLARE_NODE_API_PROPERTY("testAdjustExternalMemory", testAdjustExternalMemory)
};
DECLARE_NODE_API_PROPERTY("testStrictEquals", testStrictEquals),
DECLARE_NODE_API_PROPERTY("testSetPrototype", testSetPrototype),
DECLARE_NODE_API_PROPERTY("testGetPrototype", testGetPrototype),
DECLARE_NODE_API_PROPERTY("testGetVersion", testGetVersion),
DECLARE_NODE_API_PROPERTY("testNapiRun", testNapiRun),
DECLARE_NODE_API_PROPERTY("doInstanceOf", doInstanceOf),
DECLARE_NODE_API_PROPERTY("getUndefined", getUndefined),
DECLARE_NODE_API_PROPERTY("getNull", getNull),
DECLARE_NODE_API_PROPERTY("createNapiError", createNapiError),
DECLARE_NODE_API_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup),
DECLARE_NODE_API_PROPERTY("testNapiTypeof", testNapiTypeof),
DECLARE_NODE_API_PROPERTY("wrap", wrap),
DECLARE_NODE_API_PROPERTY("envCleanupWrap", env_cleanup_wrap),
DECLARE_NODE_API_PROPERTY("unwrap", unwrap),
DECLARE_NODE_API_PROPERTY("removeWrap", remove_wrap),
DECLARE_NODE_API_PROPERTY("addFinalizerOnly", add_finalizer_only),
DECLARE_NODE_API_PROPERTY("testFinalizeWrap", test_finalize_wrap),
DECLARE_NODE_API_PROPERTY("finalizeWasCalled", finalize_was_called),
DECLARE_NODE_API_PROPERTY("derefItemWasCalled", deref_item_was_called),
DECLARE_NODE_API_PROPERTY("testAdjustExternalMemory",
testAdjustExternalMemory)};

NODE_API_CALL(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
Expand Down
Loading