Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
n-api: add napi_get_all_property_names
Co-Authored-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
  • Loading branch information
himself65 and Gabriel Schulhof committed Dec 10, 2019
commit 06f93b7fc73944ce86c0ff5cb0181122b3bb91e6
85 changes: 85 additions & 0 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,58 @@ functions) that can be passed as parameters when `js_callback` is invoked. This
pointer is managed entirely by the threads and this callback. Thus this callback
should free the data.

#### napi_key_collection_mode
<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental

todo

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

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

> Stability: 1 - Experimental

todo

```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;
```

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

> Stability: 1 - Experimental

todo

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

## Error Handling
N-API uses both return values and JavaScript exceptions for error handling.
The following sections explain the approach for each case.
Expand Down Expand Up @@ -3502,6 +3554,39 @@ 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
-->

> Stability: 1 - Experimental

todo

```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
9 changes: 9 additions & 0 deletions src/js_native_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,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 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;

#ifdef NAPI_EXPERIMENTAL
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

#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 @@ -866,26 +866,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 @@ -165,6 +165,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