Skip to content
Closed
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
107 changes: 95 additions & 12 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ tied to the life cycle of the Agent.
### napi_set_instance_data
<!-- YAML
added: v12.8.0
napiVersion: 6
-->

```C
Expand Down Expand Up @@ -401,6 +402,7 @@ by the previous call, it will not be called.
### napi_get_instance_data
<!-- YAML
added: v12.8.0
napiVersion: 6
-->

```C
Expand Down Expand Up @@ -1660,6 +1662,63 @@ However, for better performance, it's better for the caller to make sure that
the `napi_value` in question is of the JavaScript type expected by the API.

### Enum types
#### napi_key_collection_mode
<!-- YAML
added: REPLACEME
napiVersion: 6
-->

```C
typedef enum {
napi_key_include_prototypes,
napi_key_own_only
} napi_key_collection_mode;
```

Describes the `Keys/Properties` filter enums:

`napi_key_collection_mode` limits the range of collected properties.

`napi_key_own_only` limits the collected properties to the given
object only. `napi_key_include_prototypes` will include all keys
of the objects's prototype chain as well.

#### napi_key_filter
<!-- YAML
added: REPLACEME
napiVersion: 6
-->

```C
typedef enum {
napi_key_all_properties = 0,
napi_key_writable = 1,
napi_key_enumerable = 1 << 1,
napi_key_configurable = 1 << 2,
napi_key_skip_strings = 1 << 3,
napi_key_skip_symbols = 1 << 4
} napi_key_filter;
```

Property filter bits. They can be or'ed to build a composite filter.

#### napi_key_conversion
<!-- YAML
added: REPLACEME
napiVersion: 6
-->

```C
typedef enum {
napi_key_keep_numbers,
napi_key_numbers_to_strings
} napi_key_conversion;
```

`napi_key_numbers_to_strings` will convert integer indices to
strings. `napi_key_keep_numbers` will return numbers for integer
indices.

#### napi_valuetype

```C
Expand Down Expand Up @@ -2202,10 +2261,9 @@ The JavaScript `Number` type is described in
#### napi_create_bigint_int64
<!-- YAML
added: v10.7.0
napiVersion: 6
-->

> Stability: 1 - Experimental

```C
napi_status napi_create_bigint_int64(napi_env env,
int64_t value,
Expand All @@ -2223,10 +2281,9 @@ This API converts the C `int64_t` type to the JavaScript `BigInt` type.
#### napi_create_bigint_uint64
<!-- YAML
added: v10.7.0
napiVersion: 6
-->

> Stability: 1 - Experimental

```C
napi_status napi_create_bigint_uint64(napi_env env,
uint64_t value,
Expand All @@ -2244,10 +2301,9 @@ This API converts the C `uint64_t` type to the JavaScript `BigInt` type.
#### napi_create_bigint_words
<!-- YAML
added: v10.7.0
napiVersion: 6
-->

> Stability: 1 - Experimental

```C
napi_status napi_create_bigint_words(napi_env env,
int sign_bit,
Expand Down Expand Up @@ -2593,10 +2649,9 @@ This API returns the C double primitive equivalent of the given JavaScript
#### napi_get_value_bigint_int64
<!-- YAML
added: v10.7.0
napiVersion: 6
-->

> Stability: 1 - Experimental

```C
napi_status napi_get_value_bigint_int64(napi_env env,
napi_value value,
Expand All @@ -2620,10 +2675,9 @@ This API returns the C `int64_t` primitive equivalent of the given JavaScript
#### napi_get_value_bigint_uint64
<!-- YAML
added: v10.7.0
napiVersion: 6
-->

> Stability: 1 - Experimental

```C
napi_status napi_get_value_bigint_uint64(napi_env env,
napi_value value,
Expand All @@ -2647,10 +2701,9 @@ This API returns the C `uint64_t` primitive equivalent of the given JavaScript
#### napi_get_value_bigint_words
<!-- YAML
added: v10.7.0
napiVersion: 6
-->

> Stability: 1 - Experimental

```C
napi_status napi_get_value_bigint_words(napi_env env,
napi_value value,
Expand Down Expand Up @@ -3532,6 +3585,36 @@ This API returns the names of the enumerable properties of `object` as an array
of strings. The properties of `object` whose key is a symbol will not be
included.

#### napi_get_all_property_names
<!-- YAML
added: REPLACEME
napiVersion: 6
-->

```C
napi_get_all_property_names(napi_env env,
napi_value object,
napi_key_collection_mode key_mode,
napi_key_filter key_filter,
napi_key_conversion key_conversion,
napi_value* result);
```

* `[in] env`: The environment that the N-API call is invoked under.
* `[in] object`: The object from which to retrieve the properties.
* `[in] key_mode`: Whether to retrieve prototype properties as well.
* `[in] key_filter`: Which properties to retrieve
(enumerable/readable/writable).
* `[in] key_conversion`: Whether to convert numbered property keys to strings.
* `[out] result`: A `napi_value` representing an array of JavaScript values
that represent the property names of the object. [`napi_get_array_length`][] and
[`napi_get_element`][] can be used to iterate over `result`.

Returns `napi_ok` if the API succeeded.

This API returns an array containing the names of the available properties
of this object.

#### napi_set_property
<!-- YAML
added: v8.0.0
Expand Down
18 changes: 15 additions & 3 deletions src/js_native_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// This file needs to be compatible with C compilers.
#include <stddef.h> // NOLINT(modernize-deprecated-headers)
#include <stdbool.h> // NOLINT(modernize-deprecated-headers)
#include "js_native_api_types.h"

// Use INT_MAX, this should only be consumed by the pre-processor anyway.
#define NAPI_VERSION_EXPERIMENTAL 2147483647
Expand All @@ -18,10 +17,12 @@
// functions available in a new version of N-API that is not yet ported in all
// LTS versions, they can set NAPI_VERSION knowing that they have specifically
// depended on that version.
#define NAPI_VERSION 5
#define NAPI_VERSION 6
#endif
#endif

#include "js_native_api_types.h"

// If you need __declspec(dllimport), either include <node_api.h> instead, or
// define NAPI_EXTERN as __declspec(dllimport) on the compiler's command line.
#ifndef NAPI_EXTERN
Expand Down Expand Up @@ -478,7 +479,7 @@ NAPI_EXTERN napi_status napi_add_finalizer(napi_env env,

#endif // NAPI_VERSION >= 5

#ifdef NAPI_EXPERIMENTAL
#if NAPI_VERSION >= 6

// BigInt
NAPI_EXTERN napi_status napi_create_bigint_int64(napi_env env,
Expand Down Expand Up @@ -506,6 +507,15 @@ NAPI_EXTERN napi_status napi_get_value_bigint_words(napi_env env,
size_t* word_count,
uint64_t* words);

// Object
NAPI_EXTERN napi_status
napi_get_all_property_names(napi_env env,
napi_value object,
napi_key_collection_mode key_mode,
napi_key_filter key_filter,
napi_key_conversion key_conversion,
napi_value* result);

// Instance data
NAPI_EXTERN napi_status napi_set_instance_data(napi_env env,
void* data,
Expand All @@ -514,7 +524,9 @@ NAPI_EXTERN napi_status napi_set_instance_data(napi_env env,

NAPI_EXTERN napi_status napi_get_instance_data(napi_env env,
void** data);
#endif // NAPI_VERSION >= 6

#ifdef NAPI_EXPERIMENTAL
// ArrayBuffer detaching
NAPI_EXTERN napi_status napi_detach_arraybuffer(napi_env env,
napi_value arraybuffer);
Expand Down
21 changes: 21 additions & 0 deletions src/js_native_api_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,25 @@ typedef struct {
napi_status error_code;
} napi_extended_error_info;

#if NAPI_VERSION >= 6
typedef enum {
napi_key_include_prototypes,
napi_key_own_only
} napi_key_collection_mode;

typedef enum {
napi_key_all_properties = 0,
napi_key_writable = 1,
napi_key_enumerable = 1 << 1,
napi_key_configurable = 1 << 2,
napi_key_skip_strings = 1 << 3,
napi_key_skip_symbols = 1 << 4
} napi_key_filter;

typedef enum {
napi_key_keep_numbers,
napi_key_numbers_to_strings
} napi_key_conversion;
#endif // NAPI_VERSION >= 6

#endif // SRC_JS_NATIVE_API_TYPES_H_
88 changes: 77 additions & 11 deletions src/js_native_api_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -933,26 +933,92 @@ napi_status napi_define_class(napi_env env,
napi_status napi_get_property_names(napi_env env,
napi_value object,
napi_value* result) {
return napi_get_all_property_names(
env,
object,
napi_key_include_prototypes,
static_cast<napi_key_filter>(napi_key_enumerable |
napi_key_skip_symbols),
napi_key_numbers_to_strings,
result);
}

napi_status napi_get_all_property_names(napi_env env,
napi_value object,
napi_key_collection_mode key_mode,
napi_key_filter key_filter,
napi_key_conversion key_conversion,
napi_value* result) {
NAPI_PREAMBLE(env);
CHECK_ARG(env, result);

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

v8::MaybeLocal<v8::Array> maybe_propertynames = obj->GetPropertyNames(
context,
v8::KeyCollectionMode::kIncludePrototypes,
static_cast<v8::PropertyFilter>(
v8::PropertyFilter::ONLY_ENUMERABLE |
v8::PropertyFilter::SKIP_SYMBOLS),
v8::IndexFilter::kIncludeIndices,
v8::KeyConversionMode::kConvertToString);
v8::PropertyFilter filter = v8::PropertyFilter::ALL_PROPERTIES;
if (key_filter & napi_key_writable) {
filter =
static_cast<v8::PropertyFilter>(filter |
v8::PropertyFilter::ONLY_WRITABLE);
}
if (key_filter & napi_key_enumerable) {
filter =
static_cast<v8::PropertyFilter>(filter |
v8::PropertyFilter::ONLY_ENUMERABLE);
}
if (key_filter & napi_key_configurable) {
filter =
static_cast<v8::PropertyFilter>(filter |
v8::PropertyFilter::ONLY_WRITABLE);
}
if (key_filter & napi_key_skip_strings) {
filter =
static_cast<v8::PropertyFilter>(filter |
v8::PropertyFilter::SKIP_STRINGS);
}
if (key_filter & napi_key_skip_symbols) {
filter =
static_cast<v8::PropertyFilter>(filter |
v8::PropertyFilter::SKIP_SYMBOLS);
}
v8::KeyCollectionMode collection_mode;
v8::KeyConversionMode conversion_mode;

switch (key_mode) {
case napi_key_include_prototypes:
collection_mode = v8::KeyCollectionMode::kIncludePrototypes;
break;
case napi_key_own_only:
collection_mode = v8::KeyCollectionMode::kOwnOnly;
break;
default:
return napi_set_last_error(env, napi_invalid_arg);
}

CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure);
switch (key_conversion) {
case napi_key_keep_numbers:
conversion_mode = v8::KeyConversionMode::kKeepNumbers;
break;
case napi_key_numbers_to_strings:
conversion_mode = v8::KeyConversionMode::kConvertToString;
break;
default:
return napi_set_last_error(env, napi_invalid_arg);
}

*result = v8impl::JsValueFromV8LocalValue(
maybe_propertynames.ToLocalChecked());
v8::MaybeLocal<v8::Array> maybe_all_propertynames =
obj->GetPropertyNames(context,
collection_mode,
filter,
v8::IndexFilter::kIncludeIndices,
conversion_mode);

CHECK_MAYBE_EMPTY_WITH_PREAMBLE(
env, maybe_all_propertynames, napi_generic_failure);

*result =
v8impl::JsValueFromV8LocalValue(maybe_all_propertynames.ToLocalChecked());
return GET_RETURN_STATUS(env);
}

Expand Down
11 changes: 11 additions & 0 deletions src/js_native_api_v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,17 @@ napi_status napi_set_last_error(napi_env env, napi_status error_code,
} \
} while (0)

#define RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env, condition, status) \
do { \
if (!(condition)) { \
return napi_set_last_error( \
(env), try_catch.HasCaught() ? napi_pending_exception : (status)); \
} \
} while (0)

#define CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe, status) \
RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsEmpty()), (status))

namespace v8impl {

//=== Conversion between V8 Handles and napi_value ========================
Expand Down
Loading