summaryrefslogtreecommitdiff
path: root/src/js_native_api_v8.h
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2018-10-19 15:10:59 -0400
committerGabriel Schulhof <gabriel.schulhof@intel.com>2018-11-17 14:38:51 -0800
commit596bd5f1bb64cebc8d9b72c114f78ef9f074863b (patch)
tree183093bab31185abe572f178f9639d0f6d2cc68a /src/js_native_api_v8.h
parent451fb04b3ceb689b5bab697ceeba46a1028410b5 (diff)
downloadandroid-node-v8-596bd5f1bb64cebc8d9b72c114f78ef9f074863b.tar.gz
android-node-v8-596bd5f1bb64cebc8d9b72c114f78ef9f074863b.tar.bz2
android-node-v8-596bd5f1bb64cebc8d9b72c114f78ef9f074863b.zip
src: factor out Node.js-agnostic N-APIs
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_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_adjust_external_memory * [ ] 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 PR-URL: https://github.com/nodejs/node/pull/23786 Reviewed-By: Yazhong Liu <yorkiefixer@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'src/js_native_api_v8.h')
-rw-r--r--src/js_native_api_v8.h202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/js_native_api_v8.h b/src/js_native_api_v8.h
new file mode 100644
index 0000000000..d5402845dc
--- /dev/null
+++ b/src/js_native_api_v8.h
@@ -0,0 +1,202 @@
+#ifndef SRC_JS_NATIVE_API_V8_H_
+#define SRC_JS_NATIVE_API_V8_H_
+
+#include <string.h>
+#include "js_native_api_types.h"
+#include "js_native_api_v8_internals.h"
+
+struct napi_env__ {
+ explicit napi_env__(v8::Local<v8::Context> context)
+ : isolate(context->GetIsolate()),
+ context_persistent(isolate, context) {
+ CHECK_EQ(isolate, context->GetIsolate());
+ }
+ v8::Isolate* const isolate; // Shortcut for context()->GetIsolate()
+ v8impl::Persistent<v8::Context> context_persistent;
+
+ inline v8::Local<v8::Context> context() const {
+ return v8impl::PersistentToLocal::Strong(context_persistent);
+ }
+
+ inline void Ref() { refs++; }
+ inline void Unref() { if ( --refs == 0) delete this; }
+
+ v8impl::Persistent<v8::Value> last_exception;
+ napi_extended_error_info last_error;
+ int open_handle_scopes = 0;
+ int open_callback_scopes = 0;
+ int refs = 1;
+};
+
+static inline napi_status napi_clear_last_error(napi_env env) {
+ env->last_error.error_code = napi_ok;
+
+ // TODO(boingoing): Should this be a callback?
+ env->last_error.engine_error_code = 0;
+ env->last_error.engine_reserved = nullptr;
+ return napi_ok;
+}
+
+static inline
+napi_status napi_set_last_error(napi_env env, napi_status error_code,
+ uint32_t engine_error_code = 0,
+ void* engine_reserved = nullptr) {
+ env->last_error.error_code = error_code;
+ env->last_error.engine_error_code = engine_error_code;
+ env->last_error.engine_reserved = engine_reserved;
+ return error_code;
+}
+
+#define RETURN_STATUS_IF_FALSE(env, condition, status) \
+ do { \
+ if (!(condition)) { \
+ return napi_set_last_error((env), (status)); \
+ } \
+ } while (0)
+
+#define CHECK_ENV(env) \
+ do { \
+ if ((env) == nullptr) { \
+ return napi_invalid_arg; \
+ } \
+ } while (0)
+
+#define CHECK_ARG(env, arg) \
+ RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg)
+
+#define CHECK_MAYBE_EMPTY(env, maybe, status) \
+ RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status))
+
+// NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope
+#define NAPI_PREAMBLE(env) \
+ CHECK_ENV((env)); \
+ RETURN_STATUS_IF_FALSE((env), (env)->last_exception.IsEmpty(), \
+ napi_pending_exception); \
+ napi_clear_last_error((env)); \
+ v8impl::TryCatch try_catch((env))
+
+#define CHECK_TO_TYPE(env, type, context, result, src, status) \
+ do { \
+ CHECK_ARG((env), (src)); \
+ auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \
+ CHECK_MAYBE_EMPTY((env), maybe, (status)); \
+ (result) = maybe.ToLocalChecked(); \
+ } while (0)
+
+#define CHECK_TO_FUNCTION(env, result, src) \
+ do { \
+ CHECK_ARG((env), (src)); \
+ v8::Local<v8::Value> v8value = v8impl::V8LocalValueFromJsValue((src)); \
+ RETURN_STATUS_IF_FALSE((env), v8value->IsFunction(), napi_invalid_arg); \
+ (result) = v8value.As<v8::Function>(); \
+ } while (0)
+
+#define CHECK_TO_OBJECT(env, context, result, src) \
+ CHECK_TO_TYPE((env), Object, (context), (result), (src), napi_object_expected)
+
+#define CHECK_TO_STRING(env, context, result, src) \
+ CHECK_TO_TYPE((env), String, (context), (result), (src), napi_string_expected)
+
+#define GET_RETURN_STATUS(env) \
+ (!try_catch.HasCaught() ? napi_ok \
+ : napi_set_last_error((env), napi_pending_exception))
+
+#define THROW_RANGE_ERROR_IF_FALSE(env, condition, error, message) \
+ do { \
+ if (!(condition)) { \
+ napi_throw_range_error((env), (error), (message)); \
+ return napi_set_last_error((env), napi_generic_failure); \
+ } \
+ } while (0)
+
+#define NAPI_CALL_INTO_MODULE(env, call, handle_exception) \
+ do { \
+ int open_handle_scopes = (env)->open_handle_scopes; \
+ int open_callback_scopes = (env)->open_callback_scopes; \
+ napi_clear_last_error((env)); \
+ call; \
+ CHECK_EQ((env)->open_handle_scopes, open_handle_scopes); \
+ CHECK_EQ((env)->open_callback_scopes, open_callback_scopes); \
+ if (!(env)->last_exception.IsEmpty()) { \
+ handle_exception( \
+ v8::Local<v8::Value>::New((env)->isolate, (env)->last_exception)); \
+ (env)->last_exception.Reset(); \
+ } \
+ } while (0)
+
+#define NAPI_CALL_INTO_MODULE_THROW(env, call) \
+ NAPI_CALL_INTO_MODULE((env), call, (env)->isolate->ThrowException)
+
+namespace v8impl {
+
+//=== Conversion between V8 Handles and napi_value ========================
+
+// This asserts v8::Local<> will always be implemented with a single
+// pointer field so that we can pass it around as a void*.
+static_assert(sizeof(v8::Local<v8::Value>) == sizeof(napi_value),
+ "Cannot convert between v8::Local<v8::Value> and napi_value");
+
+inline napi_value JsValueFromV8LocalValue(v8::Local<v8::Value> local) {
+ return reinterpret_cast<napi_value>(*local);
+}
+
+inline v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v) {
+ v8::Local<v8::Value> local;
+ memcpy(&local, &v, sizeof(v));
+ return local;
+}
+
+// Adapter for napi_finalize callbacks.
+class Finalizer {
+ protected:
+ Finalizer(napi_env env,
+ napi_finalize finalize_callback,
+ void* finalize_data,
+ void* finalize_hint)
+ : _env(env),
+ _finalize_callback(finalize_callback),
+ _finalize_data(finalize_data),
+ _finalize_hint(finalize_hint) {
+ }
+
+ ~Finalizer() {
+ }
+
+ public:
+ static Finalizer* New(napi_env env,
+ napi_finalize finalize_callback = nullptr,
+ void* finalize_data = nullptr,
+ void* finalize_hint = nullptr) {
+ return new Finalizer(
+ env, finalize_callback, finalize_data, finalize_hint);
+ }
+
+ static void Delete(Finalizer* finalizer) {
+ delete finalizer;
+ }
+
+ protected:
+ napi_env _env;
+ napi_finalize _finalize_callback;
+ void* _finalize_data;
+ void* _finalize_hint;
+};
+
+class TryCatch : public v8::TryCatch {
+ public:
+ explicit TryCatch(napi_env env)
+ : v8::TryCatch(env->isolate), _env(env) {}
+
+ ~TryCatch() {
+ if (HasCaught()) {
+ _env->last_exception.Reset(_env->isolate, Exception());
+ }
+ }
+
+ private:
+ napi_env _env;
+};
+
+} // end of namespace v8impl
+
+#endif // SRC_JS_NATIVE_API_V8_H_