Skip to content

Commit

Permalink
src: factor out Node.js-agnostic N-APIs
Browse files Browse the repository at this point in the history
Split the Node.js ECMAScript API (N-EAPI?) into its own header and
implementation files. The motivation is that the ECMAScript API stand
on its own so it might be embedded separately, implementation and all.

Portions of the implementation used by both files are stored in
`node_api_impl.h`.

The checked boxes below indicate that the given API remains in
`node_api.h`, whereas the lack of a checkbox indicates that the API was
moved to `node_ecma_api.h`.

* [x] NAPI_MODULE
* [x] NAPI_MODULE_INIT
* [x] napi_acquire_threadsafe_function
* [x] napi_add_env_cleanup_hook
* [x] napi_adjust_external_memory
* [x] napi_async_destroy
* [x] napi_async_init
* [x] napi_call_threadsafe_function
* [x] napi_cancel_async_work
* [x] napi_close_callback_scope
* [x] napi_create_async_work
* [x] napi_create_buffer
* [x] napi_create_buffer_copy
* [x] napi_create_external_buffer
* [x] napi_create_threadsafe_function
* [x] napi_delete_async_work
* [x] napi_fatal_error
* [x] napi_fatal_exception
* [x] napi_get_buffer_info
* [x] napi_get_node_version
* [x] napi_get_threadsafe_function_context
* [x] napi_get_uv_event_loop
* [x] napi_is_buffer
* [x] napi_make_callback
* [x] napi_module_register
* [x] napi_open_callback_scope
* [x] napi_queue_async_work
* [x] napi_ref_threadsafe_function
* [x] napi_release_threadsafe_function
* [x] napi_remove_env_cleanup_hook
* [x] napi_unref_threadsafe_function
* [ ] napi_add_finalizer
* [ ] napi_call_function
* [ ] napi_close_escapable_handle_scope
* [ ] napi_close_handle_scope
* [ ] napi_coerce_to_bool
* [ ] napi_coerce_to_number
* [ ] napi_coerce_to_object
* [ ] napi_coerce_to_string
* [ ] napi_create_array
* [ ] napi_create_arraybuffer
* [ ] napi_create_array_with_length
* [ ] napi_create_bigint_int64
* [ ] napi_create_bigint_uint64
* [ ] napi_create_bigint_words
* [ ] napi_create_dataview
* [ ] napi_create_double
* [ ] napi_create_error
* [ ] napi_create_external
* [ ] napi_create_external_arraybuffer
* [ ] napi_create_function
* [ ] napi_create_int32
* [ ] napi_create_int64
* [ ] napi_create_object
* [ ] napi_create_promise
* [ ] napi_create_range_error
* [ ] napi_create_reference
* [ ] napi_create_string_latin1
* [ ] napi_create_string_utf16
* [ ] napi_create_string_utf8
* [ ] napi_create_symbol
* [ ] napi_create_typedarray
* [ ] napi_create_type_error
* [ ] napi_create_uint32
* [ ] napi_define_class
* [ ] napi_define_properties
* [ ] napi_delete_element
* [ ] napi_delete_property
* [ ] napi_delete_reference
* [ ] napi_escape_handle
* [ ] napi_get_and_clear_last_exception
* [ ] napi_get_arraybuffer_info
* [ ] napi_get_array_length
* [ ] napi_get_boolean
* [ ] napi_get_cb_info
* [ ] napi_get_dataview_info
* [ ] napi_get_element
* [ ] napi_get_global
* [ ] napi_get_last_error_info
* [ ] napi_get_named_property
* [ ] napi_get_new_target
* [ ] napi_get_null
* [ ] napi_get_property
* [ ] napi_get_property_names
* [ ] napi_get_prototype
* [ ] napi_get_reference_value
* [ ] napi_get_typedarray_info
* [ ] napi_get_undefined
* [ ] napi_get_value_bigint_int64
* [ ] napi_get_value_bigint_uint64
* [ ] napi_get_value_bigint_words
* [ ] napi_get_value_bool
* [ ] napi_get_value_double
* [ ] napi_get_value_external
* [ ] napi_get_value_int32
* [ ] napi_get_value_int64
* [ ] napi_get_value_string_latin1
* [ ] napi_get_value_string_utf16
* [ ] napi_get_value_string_utf8
* [ ] napi_get_value_uint32
* [ ] napi_get_version
* [ ] napi_has_element
* [ ] napi_has_named_property
* [ ] napi_has_own_property
* [ ] napi_has_property
* [ ] napi_instanceof
* [ ] napi_is_array
* [ ] napi_is_arraybuffer
* [ ] napi_is_dataview
* [ ] napi_is_error
* [ ] napi_is_exception_pending
* [ ] napi_is_promise
* [ ] napi_is_typedarray
* [ ] napi_new_instance
* [ ] napi_open_escapable_handle_scope
* [ ] napi_open_handle_scope
* [ ] napi_reference_ref
* [ ] napi_reference_unref
* [ ] napi_reject_deferred
* [ ] napi_remove_wrap
* [ ] napi_resolve_deferred
* [ ] napi_run_script
* [ ] napi_set_element
* [ ] napi_set_named_property
* [ ] napi_set_property
* [ ] napi_strict_equals
* [ ] napi_throw
* [ ] napi_throw_error
* [ ] napi_throw_range_error
* [ ] napi_throw_type_error
* [ ] napi_typeof
* [ ] napi_unwrap
* [ ] napi_wrap
  • Loading branch information
Gabriel Schulhof committed Nov 13, 2018
1 parent 60eca6a commit f69d030
Show file tree
Hide file tree
Showing 18 changed files with 3,900 additions and 3,775 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ ADDONS_NAPI_BINDING_SOURCES := \
# Implicitly depends on $(NODE_EXE), see the build-addons-napi rule for rationale.
test/addons-napi/.buildstamp: $(ADDONS_PREREQS) \
$(ADDONS_NAPI_BINDING_GYPS) $(ADDONS_NAPI_BINDING_SOURCES) \
src/node_api.h src/node_api_types.h
src/node_api.h src/node_api_types.h src/js_native_api.h \
src/js_native_api_types.h src/js_native_api_v8.h src/js_native_api_v8_internals.h
@$(call run_build_addons,"$$PWD/test/addons-napi",$@)

.PHONY: build-addons-napi
Expand Down
55 changes: 55 additions & 0 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,61 @@ available to the module code.

\* Indicates that the N-API version was released as experimental

The N-APIs associated strictly with accessing ECMAScript features from native
code can be found separately in `js_native_api.h` and `js_native_api_types.h`.
The APIS defined in these headers are included in `node_api.h` and
`node_api_types.h`. The separate headers exist to provide for the possibility of
multiple implementations of N-API.

The Node.js-specific parts of an addon can be separated from the code that
exposes the actual functionality to the JavaScript environment so that the
latter may be used with multiple implementations of N-API:

```C
// addon.h
#ifndef _ADDON_H_
#define _ADDON_H_
#include <js_native_api.h>
napi_value create_addon(napi_env env);
#endif // _ADDON_H_
```

```C
// addon.c
#include "addon.h"
napi_value create_addon(napi_env env) {
napi_value result;
assert(napi_create_object(env, &result) == napi_ok);
napi_value exported_function;
assert(napi_create_function(env,
"doSomethingUseful",
NAPI_AUTO_LENGTH,
DoSomethingUseful,
NULL,
&exported_function) == napi_ok);
assert(napi_set_named_property(env,
result,
"doSomethingUseful",
exported_function) == napi_ok);
return result;
}
```

```C
// addon_node.c
#include <node_api.h>

static napi_value Init(napi_env env, napi_value exports) {
return create_addon(env);
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
```

With files arranged in this fashion it is possible to build the addon for
Node.js, and also to reuse the code in `addon.c` and `addon.h` for a potential
implementation of N-API outside of Node.js.

## Basic N-API Data Types

N-API exposes the following fundamental datatypes as abstractions that are
Expand Down
5 changes: 5 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,11 @@
'src/fs_event_wrap.cc',
'src/handle_wrap.cc',
'src/heap_utils.cc',
'src/js_native_api.h',
'src/js_native_api_types.h',
'src/js_native_api_v8.cc',
'src/js_native_api_v8.h',
'src/js_native_api_v8_internals.h',
'src/js_stream.cc',
'src/module_wrap.cc',
'src/node.cc',
Expand Down
480 changes: 480 additions & 0 deletions src/js_native_api.h

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions src/js_native_api_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#ifndef SRC_JS_NATIVE_API_TYPES_H_
#define SRC_JS_NATIVE_API_TYPES_H_

#include <stddef.h>
#include <stdint.h>

#if !defined __cplusplus || (defined(_MSC_VER) && _MSC_VER < 1900)
typedef uint16_t char16_t;
#endif

// JSVM API types are all opaque pointers for ABI stability
// typedef undefined structs instead of void* for compile time type safety
typedef struct napi_env__* napi_env;
typedef struct napi_value__* napi_value;
typedef struct napi_ref__* napi_ref;
typedef struct napi_handle_scope__* napi_handle_scope;
typedef struct napi_escapable_handle_scope__* napi_escapable_handle_scope;
typedef struct napi_callback_info__* napi_callback_info;
typedef struct napi_deferred__* napi_deferred;

typedef enum {
napi_default = 0,
napi_writable = 1 << 0,
napi_enumerable = 1 << 1,
napi_configurable = 1 << 2,

// Used with napi_define_class to distinguish static properties
// from instance properties. Ignored by napi_define_properties.
napi_static = 1 << 10,
} napi_property_attributes;

typedef enum {
// ES6 types (corresponds to typeof)
napi_undefined,
napi_null,
napi_boolean,
napi_number,
napi_string,
napi_symbol,
napi_object,
napi_function,
napi_external,
napi_bigint,
} napi_valuetype;

typedef enum {
napi_int8_array,
napi_uint8_array,
napi_uint8_clamped_array,
napi_int16_array,
napi_uint16_array,
napi_int32_array,
napi_uint32_array,
napi_float32_array,
napi_float64_array,
napi_bigint64_array,
napi_biguint64_array,
} napi_typedarray_type;

typedef enum {
napi_ok,
napi_invalid_arg,
napi_object_expected,
napi_string_expected,
napi_name_expected,
napi_function_expected,
napi_number_expected,
napi_boolean_expected,
napi_array_expected,
napi_generic_failure,
napi_pending_exception,
napi_cancelled,
napi_escape_called_twice,
napi_handle_scope_mismatch,
napi_callback_scope_mismatch,
napi_queue_full,
napi_closing,
napi_bigint_expected,
} napi_status;

typedef napi_value (*napi_callback)(napi_env env,
napi_callback_info info);
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint);

typedef struct {
// One of utf8name or name should be NULL.
const char* utf8name;
napi_value name;

napi_callback method;
napi_callback getter;
napi_callback setter;
napi_value value;

napi_property_attributes attributes;
void* data;
} napi_property_descriptor;

typedef struct {
const char* error_message;
void* engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
} napi_extended_error_info;

#endif // SRC_JS_NATIVE_API_TYPES_H_
Loading

0 comments on commit f69d030

Please sign in to comment.