Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
node_api.cc
Go to the documentation of this file.
1 /******************************************************************************
2  * Experimental prototype for demonstrating VM agnostic and ABI stable API
3  * for native modules to use instead of using Nan and V8 APIs directly.
4  *
5  * The current status is "Experimental" and should not be used for
6  * production applications. The API is still subject to change
7  * and as an experimental feature is NOT subject to semver.
8  *
9  ******************************************************************************/
10 
11 #include <node_buffer.h>
12 #include <node_object_wrap.h>
13 #include <string.h>
14 #include <algorithm>
15 #include <cmath>
16 #include <vector>
17 #include "uv.h"
18 #include "node_api.h"
19 #include "node_internals.h"
20 #include "util.h"
21 
22 #define NAPI_VERSION 1
23 
24 static
25 napi_status napi_set_last_error(napi_env env, napi_status error_code,
26  uint32_t engine_error_code = 0,
27  void* engine_reserved = nullptr);
28 static
29 napi_status napi_clear_last_error(napi_env env);
30 
31 struct napi_env__ {
32  explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate),
35  last_exception.Reset();
36  has_instance.Reset();
37  wrap_template.Reset();
38  function_data_template.Reset();
39  accessor_data_template.Reset();
40  }
41  v8::Isolate* isolate;
42  v8::Persistent<v8::Value> last_exception;
43  v8::Persistent<v8::Value> has_instance;
44  v8::Persistent<v8::ObjectTemplate> wrap_template;
45  v8::Persistent<v8::ObjectTemplate> function_data_template;
46  v8::Persistent<v8::ObjectTemplate> accessor_data_template;
49 };
50 
51 #define ENV_OBJECT_TEMPLATE(env, prefix, destination, field_count) \
52  do { \
53  if ((env)->prefix ## _template.IsEmpty()) { \
54  (destination) = v8::ObjectTemplate::New(isolate); \
55  (destination)->SetInternalFieldCount((field_count)); \
56  (env)->prefix ## _template.Reset(isolate, (destination)); \
57  } else { \
58  (destination) = v8::Local<v8::ObjectTemplate>::New( \
59  isolate, env->prefix ## _template); \
60  } \
61  } while (0)
62 
63 
64 #define RETURN_STATUS_IF_FALSE(env, condition, status) \
65  do { \
66  if (!(condition)) { \
67  return napi_set_last_error((env), (status)); \
68  } \
69  } while (0)
70 
71 #define CHECK_ENV(env) \
72  if ((env) == nullptr) { \
73  return napi_invalid_arg; \
74  }
75 
76 #define CHECK_ARG(env, arg) \
77  RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg)
78 
79 #define CHECK_MAYBE_EMPTY(env, maybe, status) \
80  RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status))
81 
82 #define CHECK_MAYBE_NOTHING(env, maybe, status) \
83  RETURN_STATUS_IF_FALSE((env), !((maybe).IsNothing()), (status))
84 
85 // NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope
86 #define NAPI_PREAMBLE(env) \
87  CHECK_ENV((env)); \
88  RETURN_STATUS_IF_FALSE((env), (env)->last_exception.IsEmpty(), \
89  napi_pending_exception); \
90  napi_clear_last_error((env)); \
91  v8impl::TryCatch try_catch((env))
92 
93 #define CHECK_TO_TYPE(env, type, context, result, src, status) \
94  do { \
95  CHECK_ARG((env), (src)); \
96  auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \
97  CHECK_MAYBE_EMPTY((env), maybe, (status)); \
98  (result) = maybe.ToLocalChecked(); \
99  } while (0)
100 
101 #define CHECK_TO_FUNCTION(env, result, src) \
102  do { \
103  CHECK_ARG((env), (src)); \
104  v8::Local<v8::Value> v8value = v8impl::V8LocalValueFromJsValue((src)); \
105  RETURN_STATUS_IF_FALSE((env), v8value->IsFunction(), napi_invalid_arg); \
106  (result) = v8value.As<v8::Function>(); \
107  } while (0)
108 
109 #define CHECK_TO_OBJECT(env, context, result, src) \
110  CHECK_TO_TYPE((env), Object, (context), (result), (src), napi_object_expected)
111 
112 #define CHECK_TO_STRING(env, context, result, src) \
113  CHECK_TO_TYPE((env), String, (context), (result), (src), napi_string_expected)
114 
115 #define CHECK_TO_NUMBER(env, context, result, src) \
116  CHECK_TO_TYPE((env), Number, (context), (result), (src), napi_number_expected)
117 
118 #define CHECK_TO_BOOL(env, context, result, src) \
119  CHECK_TO_TYPE((env), Boolean, (context), (result), (src), \
120  napi_boolean_expected)
121 
122 #define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len) \
123  do { \
124  auto str_maybe = v8::String::NewFromUtf8( \
125  (env)->isolate, (str), v8::NewStringType::kInternalized, (len)); \
126  CHECK_MAYBE_EMPTY((env), str_maybe, napi_generic_failure); \
127  (result) = str_maybe.ToLocalChecked(); \
128  } while (0)
129 
130 #define CHECK_NEW_FROM_UTF8(env, result, str) \
131  CHECK_NEW_FROM_UTF8_LEN((env), (result), (str), -1)
132 
133 #define GET_RETURN_STATUS(env) \
134  (!try_catch.HasCaught() ? napi_ok \
135  : napi_set_last_error((env), napi_pending_exception))
136 
137 namespace {
138 namespace v8impl {
139 
140 // convert from n-api property attributes to v8::PropertyAttribute
141 static inline v8::PropertyAttribute V8PropertyAttributesFromDescriptor(
142  const napi_property_descriptor* descriptor) {
143  unsigned int attribute_flags = v8::PropertyAttribute::None;
144 
145  if (descriptor->getter != nullptr || descriptor->setter != nullptr) {
146  // The napi_writable attribute is ignored for accessor descriptors, but
147  // V8 requires the ReadOnly attribute to match nonexistence of a setter.
148  attribute_flags |= (descriptor->setter == nullptr ?
149  v8::PropertyAttribute::ReadOnly : v8::PropertyAttribute::None);
150  } else if ((descriptor->attributes & napi_writable) == 0) {
151  attribute_flags |= v8::PropertyAttribute::ReadOnly;
152  }
153 
154  if ((descriptor->attributes & napi_enumerable) == 0) {
155  attribute_flags |= v8::PropertyAttribute::DontEnum;
156  }
157  if ((descriptor->attributes & napi_configurable) == 0) {
158  attribute_flags |= v8::PropertyAttribute::DontDelete;
159  }
160 
161  return static_cast<v8::PropertyAttribute>(attribute_flags);
162 }
163 
164 class HandleScopeWrapper {
165  public:
166  explicit HandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {}
167 
168  private:
169  v8::HandleScope scope;
170 };
171 
172 // In node v0.10 version of v8, there is no EscapableHandleScope and the
173 // node v0.10 port use HandleScope::Close(Local<T> v) to mimic the behavior
174 // of a EscapableHandleScope::Escape(Local<T> v), but it is not the same
175 // semantics. This is an example of where the api abstraction fail to work
176 // across different versions.
177 class EscapableHandleScopeWrapper {
178  public:
179  explicit EscapableHandleScopeWrapper(v8::Isolate* isolate)
180  : scope(isolate), escape_called_(false) {}
181  bool escape_called() const {
182  return escape_called_;
183  }
184  template <typename T>
185  v8::Local<T> Escape(v8::Local<T> handle) {
186  escape_called_ = true;
187  return scope.Escape(handle);
188  }
189 
190  private:
191  v8::EscapableHandleScope scope;
192  bool escape_called_;
193 };
194 
195 napi_handle_scope JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s) {
196  return reinterpret_cast<napi_handle_scope>(s);
197 }
198 
199 HandleScopeWrapper* V8HandleScopeFromJsHandleScope(napi_handle_scope s) {
200  return reinterpret_cast<HandleScopeWrapper*>(s);
201 }
202 
203 napi_escapable_handle_scope JsEscapableHandleScopeFromV8EscapableHandleScope(
204  EscapableHandleScopeWrapper* s) {
205  return reinterpret_cast<napi_escapable_handle_scope>(s);
206 }
207 
208 EscapableHandleScopeWrapper*
209 V8EscapableHandleScopeFromJsEscapableHandleScope(
211  return reinterpret_cast<EscapableHandleScopeWrapper*>(s);
212 }
213 
214 //=== Conversion between V8 Handles and napi_value ========================
215 
216 // This asserts v8::Local<> will always be implemented with a single
217 // pointer field so that we can pass it around as a void*.
218 static_assert(sizeof(v8::Local<v8::Value>) == sizeof(napi_value),
219  "Cannot convert between v8::Local<v8::Value> and napi_value");
220 
221 napi_deferred JsDeferredFromV8Persistent(v8::Persistent<v8::Value>* local) {
222  return reinterpret_cast<napi_deferred>(local);
223 }
224 
225 v8::Persistent<v8::Value>* V8PersistentFromJsDeferred(napi_deferred local) {
226  return reinterpret_cast<v8::Persistent<v8::Value>*>(local);
227 }
228 
229 napi_value JsValueFromV8LocalValue(v8::Local<v8::Value> local) {
230  return reinterpret_cast<napi_value>(*local);
231 }
232 
233 v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v) {
234  v8::Local<v8::Value> local;
235  memcpy(&local, &v, sizeof(v));
236  return local;
237 }
238 
239 static inline napi_status V8NameFromPropertyDescriptor(napi_env env,
241  v8::Local<v8::Name>* result) {
242  if (p->utf8name != nullptr) {
243  CHECK_NEW_FROM_UTF8(env, *result, p->utf8name);
244  } else {
245  v8::Local<v8::Value> property_value =
246  v8impl::V8LocalValueFromJsValue(p->name);
247 
248  RETURN_STATUS_IF_FALSE(env, property_value->IsName(), napi_name_expected);
249  *result = property_value.As<v8::Name>();
250  }
251 
252  return napi_ok;
253 }
254 
255 // Adapter for napi_finalize callbacks.
256 class Finalizer {
257  protected:
258  Finalizer(napi_env env,
259  napi_finalize finalize_callback,
260  void* finalize_data,
261  void* finalize_hint)
262  : _env(env),
263  _finalize_callback(finalize_callback),
264  _finalize_data(finalize_data),
265  _finalize_hint(finalize_hint) {
266  }
267 
268  ~Finalizer() {
269  }
270 
271  public:
272  static Finalizer* New(napi_env env,
273  napi_finalize finalize_callback = nullptr,
274  void* finalize_data = nullptr,
275  void* finalize_hint = nullptr) {
276  return new Finalizer(
277  env, finalize_callback, finalize_data, finalize_hint);
278  }
279 
280  static void Delete(Finalizer* finalizer) {
281  delete finalizer;
282  }
283 
284  // node::Buffer::FreeCallback
285  static void FinalizeBufferCallback(char* data, void* hint) {
286  Finalizer* finalizer = static_cast<Finalizer*>(hint);
287  if (finalizer->_finalize_callback != nullptr) {
288  finalizer->_finalize_callback(
289  finalizer->_env,
290  data,
291  finalizer->_finalize_hint);
292  }
293 
294  Delete(finalizer);
295  }
296 
297  protected:
298  napi_env _env;
299  napi_finalize _finalize_callback;
300  void* _finalize_data;
301  void* _finalize_hint;
302 };
303 
304 // Wrapper around v8::Persistent that implements reference counting.
305 class Reference : private Finalizer {
306  private:
307  Reference(napi_env env,
308  v8::Local<v8::Value> value,
309  uint32_t initial_refcount,
310  bool delete_self,
311  napi_finalize finalize_callback,
312  void* finalize_data,
313  void* finalize_hint)
314  : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
315  _persistent(env->isolate, value),
316  _refcount(initial_refcount),
317  _delete_self(delete_self) {
318  if (initial_refcount == 0) {
319  _persistent.SetWeak(
320  this, FinalizeCallback, v8::WeakCallbackType::kParameter);
321  _persistent.MarkIndependent();
322  }
323  }
324 
325  ~Reference() {
326  // The V8 Persistent class currently does not reset in its destructor:
327  // see NonCopyablePersistentTraits::kResetInDestructor = false.
328  // (Comments there claim that might change in the future.)
329  // To avoid memory leaks, it is better to reset at this time, however
330  // care must be taken to avoid attempting this after the Isolate has
331  // shut down, for example via a static (atexit) destructor.
332  _persistent.Reset();
333  }
334 
335  public:
336  static Reference* New(napi_env env,
337  v8::Local<v8::Value> value,
338  uint32_t initial_refcount,
339  bool delete_self,
340  napi_finalize finalize_callback = nullptr,
341  void* finalize_data = nullptr,
342  void* finalize_hint = nullptr) {
343  return new Reference(env,
344  value,
345  initial_refcount,
346  delete_self,
347  finalize_callback,
348  finalize_data,
349  finalize_hint);
350  }
351 
352  static void Delete(Reference* reference) {
353  delete reference;
354  }
355 
356  uint32_t Ref() {
357  if (++_refcount == 1) {
358  _persistent.ClearWeak();
359  }
360 
361  return _refcount;
362  }
363 
364  uint32_t Unref() {
365  if (_refcount == 0) {
366  return 0;
367  }
368  if (--_refcount == 0) {
369  _persistent.SetWeak(
370  this, FinalizeCallback, v8::WeakCallbackType::kParameter);
371  _persistent.MarkIndependent();
372  }
373 
374  return _refcount;
375  }
376 
377  uint32_t RefCount() {
378  return _refcount;
379  }
380 
381  v8::Local<v8::Value> Get() {
382  if (_persistent.IsEmpty()) {
383  return v8::Local<v8::Value>();
384  } else {
385  return v8::Local<v8::Value>::New(_env->isolate, _persistent);
386  }
387  }
388 
389  private:
390  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
391  Reference* reference = data.GetParameter();
392  reference->_persistent.Reset();
393 
394  // Check before calling the finalize callback, because the callback might
395  // delete it.
396  bool delete_self = reference->_delete_self;
397 
398  if (reference->_finalize_callback != nullptr) {
399  reference->_finalize_callback(
400  reference->_env,
401  reference->_finalize_data,
402  reference->_finalize_hint);
403  }
404 
405  if (delete_self) {
406  Delete(reference);
407  }
408  }
409 
410  v8::Persistent<v8::Value> _persistent;
411  uint32_t _refcount;
412  bool _delete_self;
413 };
414 
415 class TryCatch : public v8::TryCatch {
416  public:
417  explicit TryCatch(napi_env env)
418  : v8::TryCatch(env->isolate), _env(env) {}
419 
420  ~TryCatch() {
421  if (HasCaught()) {
422  _env->last_exception.Reset(_env->isolate, Exception());
423  }
424  }
425 
426  private:
427  napi_env _env;
428 };
429 
430 //=== Function napi_callback wrapper =================================
431 
432 static const int kDataIndex = 0;
433 static const int kEnvIndex = 1;
434 
435 static const int kFunctionIndex = 2;
436 static const int kFunctionFieldCount = 3;
437 
438 static const int kGetterIndex = 2;
439 static const int kSetterIndex = 3;
440 static const int kAccessorFieldCount = 4;
441 
442 // Base class extended by classes that wrap V8 function and property callback
443 // info.
444 class CallbackWrapper {
445  public:
446  CallbackWrapper(napi_value this_arg, size_t args_length, void* data)
447  : _this(this_arg), _args_length(args_length), _data(data) {}
448 
449  virtual bool IsConstructCall() = 0;
450  virtual void Args(napi_value* buffer, size_t bufferlength) = 0;
451  virtual void SetReturnValue(napi_value value) = 0;
452 
453  napi_value This() { return _this; }
454 
455  size_t ArgsLength() { return _args_length; }
456 
457  void* Data() { return _data; }
458 
459  protected:
460  const napi_value _this;
461  const size_t _args_length;
462  void* _data;
463 };
464 
465 template <typename Info, int kInternalFieldIndex>
466 class CallbackWrapperBase : public CallbackWrapper {
467  public:
468  CallbackWrapperBase(const Info& cbinfo, const size_t args_length)
469  : CallbackWrapper(JsValueFromV8LocalValue(cbinfo.This()),
470  args_length,
471  nullptr),
472  _cbinfo(cbinfo),
473  _cbdata(v8::Local<v8::Object>::Cast(cbinfo.Data())) {
474  _data = v8::Local<v8::External>::Cast(_cbdata->GetInternalField(kDataIndex))
475  ->Value();
476  }
477 
478  /*virtual*/
479  bool IsConstructCall() override { return false; }
480 
481  protected:
482  void InvokeCallback() {
483  napi_callback_info cbinfo_wrapper = reinterpret_cast<napi_callback_info>(
484  static_cast<CallbackWrapper*>(this));
485  napi_callback cb = reinterpret_cast<napi_callback>(
486  v8::Local<v8::External>::Cast(
487  _cbdata->GetInternalField(kInternalFieldIndex))->Value());
488  v8::Isolate* isolate = _cbinfo.GetIsolate();
489 
490  napi_env env = static_cast<napi_env>(
491  v8::Local<v8::External>::Cast(
492  _cbdata->GetInternalField(kEnvIndex))->Value());
493 
494  // Make sure any errors encountered last time we were in N-API are gone.
495  napi_clear_last_error(env);
496 
497  napi_value result = cb(env, cbinfo_wrapper);
498 
499  if (result != nullptr) {
500  this->SetReturnValue(result);
501  }
502 
503  if (!env->last_exception.IsEmpty()) {
504  isolate->ThrowException(
506  env->last_exception.Reset();
507  }
508  }
509 
510  const Info& _cbinfo;
511  const v8::Local<v8::Object> _cbdata;
512 };
513 
514 class FunctionCallbackWrapper
515  : public CallbackWrapperBase<v8::FunctionCallbackInfo<v8::Value>,
516  kFunctionIndex> {
517  public:
518  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
519  FunctionCallbackWrapper cbwrapper(info);
520  cbwrapper.InvokeCallback();
521  }
522 
523  explicit FunctionCallbackWrapper(
524  const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
525  : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
526 
527  /*virtual*/
528  bool IsConstructCall() override { return _cbinfo.IsConstructCall(); }
529 
530  /*virtual*/
531  void Args(napi_value* buffer, size_t buffer_length) override {
532  size_t i = 0;
533  size_t min = std::min(buffer_length, _args_length);
534 
535  for (; i < min; i += 1) {
536  buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
537  }
538 
539  if (i < buffer_length) {
540  napi_value undefined =
541  v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
542  for (; i < buffer_length; i += 1) {
543  buffer[i] = undefined;
544  }
545  }
546  }
547 
548  /*virtual*/
549  void SetReturnValue(napi_value value) override {
550  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
551  _cbinfo.GetReturnValue().Set(val);
552  }
553 };
554 
555 class GetterCallbackWrapper
556  : public CallbackWrapperBase<v8::PropertyCallbackInfo<v8::Value>,
557  kGetterIndex> {
558  public:
559  static void Invoke(v8::Local<v8::Name> property,
560  const v8::PropertyCallbackInfo<v8::Value>& info) {
561  GetterCallbackWrapper cbwrapper(info);
562  cbwrapper.InvokeCallback();
563  }
564 
565  explicit GetterCallbackWrapper(
566  const v8::PropertyCallbackInfo<v8::Value>& cbinfo)
567  : CallbackWrapperBase(cbinfo, 0) {}
568 
569  /*virtual*/
570  void Args(napi_value* buffer, size_t buffer_length) override {
571  if (buffer_length > 0) {
572  napi_value undefined =
573  v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
574  for (size_t i = 0; i < buffer_length; i += 1) {
575  buffer[i] = undefined;
576  }
577  }
578  }
579 
580  /*virtual*/
581  void SetReturnValue(napi_value value) override {
582  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
583  _cbinfo.GetReturnValue().Set(val);
584  }
585 };
586 
587 class SetterCallbackWrapper
588  : public CallbackWrapperBase<v8::PropertyCallbackInfo<void>, kSetterIndex> {
589  public:
590  static void Invoke(v8::Local<v8::Name> property,
591  v8::Local<v8::Value> value,
592  const v8::PropertyCallbackInfo<void>& info) {
593  SetterCallbackWrapper cbwrapper(info, value);
594  cbwrapper.InvokeCallback();
595  }
596 
597  SetterCallbackWrapper(const v8::PropertyCallbackInfo<void>& cbinfo,
598  const v8::Local<v8::Value>& value)
599  : CallbackWrapperBase(cbinfo, 1), _value(value) {}
600 
601  /*virtual*/
602  void Args(napi_value* buffer, size_t buffer_length) override {
603  if (buffer_length > 0) {
604  buffer[0] = v8impl::JsValueFromV8LocalValue(_value);
605 
606  if (buffer_length > 1) {
607  napi_value undefined = v8impl::JsValueFromV8LocalValue(
608  v8::Undefined(_cbinfo.GetIsolate()));
609  for (size_t i = 1; i < buffer_length; i += 1) {
610  buffer[i] = undefined;
611  }
612  }
613  }
614  }
615 
616  /*virtual*/
617  void SetReturnValue(napi_value value) override {
618  // Ignore any value returned from a setter callback.
619  }
620 
621  private:
622  const v8::Local<v8::Value>& _value;
623 };
624 
625 // Creates an object to be made available to the static function callback
626 // wrapper, used to retrieve the native callback function and data pointer.
627 v8::Local<v8::Object> CreateFunctionCallbackData(napi_env env,
628  napi_callback cb,
629  void* data) {
630  v8::Isolate* isolate = env->isolate;
631  v8::Local<v8::Context> context = isolate->GetCurrentContext();
632 
633  v8::Local<v8::ObjectTemplate> otpl;
634  ENV_OBJECT_TEMPLATE(env, function_data, otpl, v8impl::kFunctionFieldCount);
635  v8::Local<v8::Object> cbdata = otpl->NewInstance(context).ToLocalChecked();
636 
637  cbdata->SetInternalField(
638  v8impl::kEnvIndex,
639  v8::External::New(isolate, static_cast<void*>(env)));
640  cbdata->SetInternalField(
641  v8impl::kFunctionIndex,
642  v8::External::New(isolate, reinterpret_cast<void*>(cb)));
643  cbdata->SetInternalField(
644  v8impl::kDataIndex,
645  v8::External::New(isolate, data));
646  return cbdata;
647 }
648 
649 // Creates an object to be made available to the static getter/setter
650 // callback wrapper, used to retrieve the native getter/setter callback
651 // function and data pointer.
652 v8::Local<v8::Object> CreateAccessorCallbackData(napi_env env,
653  napi_callback getter,
654  napi_callback setter,
655  void* data) {
656  v8::Isolate* isolate = env->isolate;
657  v8::Local<v8::Context> context = isolate->GetCurrentContext();
658 
659  v8::Local<v8::ObjectTemplate> otpl;
660  ENV_OBJECT_TEMPLATE(env, accessor_data, otpl, v8impl::kAccessorFieldCount);
661  v8::Local<v8::Object> cbdata = otpl->NewInstance(context).ToLocalChecked();
662 
663  cbdata->SetInternalField(
664  v8impl::kEnvIndex,
665  v8::External::New(isolate, static_cast<void*>(env)));
666 
667  if (getter != nullptr) {
668  cbdata->SetInternalField(
669  v8impl::kGetterIndex,
670  v8::External::New(isolate, reinterpret_cast<void*>(getter)));
671  }
672 
673  if (setter != nullptr) {
674  cbdata->SetInternalField(
675  v8impl::kSetterIndex,
676  v8::External::New(isolate, reinterpret_cast<void*>(setter)));
677  }
678 
679  cbdata->SetInternalField(
680  v8impl::kDataIndex,
681  v8::External::New(isolate, data));
682  return cbdata;
683 }
684 
685 int kWrapperFields = 3;
686 
687 // Pointer used to identify items wrapped by N-API. Used by FindWrapper and
688 // napi_wrap().
689 const char napi_wrap_name[] = "N-API Wrapper";
690 
691 // Search the object's prototype chain for the wrapper object. Usually the
692 // wrapper would be the first in the chain, but it is OK for other objects to
693 // be inserted in the prototype chain.
694 bool FindWrapper(v8::Local<v8::Object> obj,
695  v8::Local<v8::Object>* result = nullptr,
696  v8::Local<v8::Object>* parent = nullptr) {
697  v8::Local<v8::Object> wrapper = obj;
698 
699  do {
700  v8::Local<v8::Value> proto = wrapper->GetPrototype();
701  if (proto.IsEmpty() || !proto->IsObject()) {
702  return false;
703  }
704  if (parent != nullptr) {
705  *parent = wrapper;
706  }
707  wrapper = proto.As<v8::Object>();
708  if (wrapper->InternalFieldCount() == kWrapperFields) {
709  v8::Local<v8::Value> external = wrapper->GetInternalField(1);
710  if (external->IsExternal() &&
711  external.As<v8::External>()->Value() == v8impl::napi_wrap_name) {
712  break;
713  }
714  }
715  } while (true);
716 
717  if (result != nullptr) {
718  *result = wrapper;
719  }
720  return true;
721 }
722 
723 static void DeleteEnv(napi_env env, void* data, void* hint) {
724  delete env;
725 }
726 
727 napi_env GetEnv(v8::Local<v8::Context> context) {
728  napi_env result;
729 
730  auto isolate = context->GetIsolate();
731  auto global = context->Global();
732 
733  // In the case of the string for which we grab the private and the value of
734  // the private on the global object we can call .ToLocalChecked() directly
735  // because we need to stop hard if either of them is empty.
736  //
737  // Re https://github.com/nodejs/node/pull/14217#discussion_r128775149
738  auto key = v8::Private::ForApi(isolate,
739  v8::String::NewFromOneByte(isolate,
740  reinterpret_cast<const uint8_t*>("N-API Environment"),
741  v8::NewStringType::kInternalized).ToLocalChecked());
742  auto value = global->GetPrivate(context, key).ToLocalChecked();
743 
744  if (value->IsExternal()) {
745  result = static_cast<napi_env>(value.As<v8::External>()->Value());
746  } else {
747  result = new napi_env__(isolate);
748  auto external = v8::External::New(isolate, result);
749 
750  // We must also stop hard if the result of assigning the env to the global
751  // is either nothing or false.
752  CHECK(global->SetPrivate(context, key, external).FromJust());
753 
754  // Create a self-destructing reference to external that will get rid of the
755  // napi_env when external goes out of scope.
756  Reference::New(result, external, 0, true, DeleteEnv, nullptr, nullptr);
757  }
758 
759  return result;
760 }
761 
762 napi_status Unwrap(napi_env env,
763  napi_value js_object,
764  void** result,
765  v8::Local<v8::Object>* wrapper,
766  v8::Local<v8::Object>* parent = nullptr) {
767  CHECK_ARG(env, js_object);
768  CHECK_ARG(env, result);
769 
770  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
771  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
772  v8::Local<v8::Object> obj = value.As<v8::Object>();
773 
775  env, v8impl::FindWrapper(obj, wrapper, parent), napi_invalid_arg);
776 
777  v8::Local<v8::Value> unwrappedValue = (*wrapper)->GetInternalField(0);
778  RETURN_STATUS_IF_FALSE(env, unwrappedValue->IsExternal(), napi_invalid_arg);
779 
780  *result = unwrappedValue.As<v8::External>()->Value();
781 
782  return napi_ok;
783 }
784 
785 napi_status ConcludeDeferred(napi_env env,
786  napi_deferred deferred,
787  napi_value result,
788  bool is_resolved) {
789  NAPI_PREAMBLE(env);
790  CHECK_ARG(env, result);
791 
792  v8::Local<v8::Context> context = env->isolate->GetCurrentContext();
793  v8::Persistent<v8::Value>* deferred_ref =
794  V8PersistentFromJsDeferred(deferred);
795  v8::Local<v8::Value> v8_deferred =
796  v8::Local<v8::Value>::New(env->isolate, *deferred_ref);
797 
798  auto v8_resolver = v8::Local<v8::Promise::Resolver>::Cast(v8_deferred);
799 
800  v8::Maybe<bool> success = is_resolved ?
801  v8_resolver->Resolve(context, v8impl::V8LocalValueFromJsValue(result)) :
802  v8_resolver->Reject(context, v8impl::V8LocalValueFromJsValue(result));
803 
804  deferred_ref->Reset();
805  delete deferred_ref;
806 
807  RETURN_STATUS_IF_FALSE(env, success.FromMaybe(false), napi_generic_failure);
808 
809  return GET_RETURN_STATUS(env);
810 }
811 
812 } // end of namespace v8impl
813 
814 // Intercepts the Node-V8 module registration callback. Converts parameters
815 // to NAPI equivalents and then calls the registration callback specified
816 // by the NAPI module.
817 void napi_module_register_cb(v8::Local<v8::Object> exports,
818  v8::Local<v8::Value> module,
819  v8::Local<v8::Context> context,
820  void* priv) {
821  napi_module* mod = static_cast<napi_module*>(priv);
822 
823  // Create a new napi_env for this module or reference one if a pre-existing
824  // one is found.
825  napi_env env = v8impl::GetEnv(context);
826 
827  mod->nm_register_func(
828  env,
829  v8impl::JsValueFromV8LocalValue(exports),
830  v8impl::JsValueFromV8LocalValue(module),
831  mod->nm_priv);
832 }
833 
834 } // end of anonymous namespace
835 
836 #ifndef EXTERNAL_NAPI
837 namespace node {
838  // Indicates whether NAPI was enabled/disabled via the node command-line.
839  extern bool load_napi_modules;
840 }
841 #endif // EXTERNAL_NAPI
842 
843 // Registers a NAPI module.
845  // NAPI modules always work with the current node version.
846  int module_version = NODE_MODULE_VERSION;
847 
848 #ifndef EXTERNAL_NAPI
850  // NAPI is disabled, so set the module version to -1 to cause the module
851  // to be unloaded.
852  module_version = -1;
853  }
854 #endif // EXTERNAL_NAPI
855 
857  module_version,
858  mod->nm_flags,
859  nullptr,
860  mod->nm_filename,
861  nullptr,
862  napi_module_register_cb,
863  mod->nm_modname,
864  mod, // priv
865  nullptr,
866  };
868 }
869 
870 // Warning: Keep in-sync with napi_status enum
871 const char* error_messages[] = {nullptr,
872  "Invalid pointer passed as argument",
873  "An object was expected",
874  "A string was expected",
875  "A string or symbol was expected",
876  "A function was expected",
877  "A number was expected",
878  "A boolean was expected",
879  "An array was expected",
880  "Unknown failure",
881  "An exception is pending",
882  "The async work item was cancelled",
883  "napi_escape_handle already called on scope"};
884 
885 static inline napi_status napi_clear_last_error(napi_env env) {
887 
888  // TODO(boingoing): Should this be a callback?
889  env->last_error.engine_error_code = 0;
890  env->last_error.engine_reserved = nullptr;
891  return napi_ok;
892 }
893 
894 static inline
895 napi_status napi_set_last_error(napi_env env, napi_status error_code,
896  uint32_t engine_error_code,
897  void* engine_reserved) {
898  env->last_error.error_code = error_code;
899  env->last_error.engine_error_code = engine_error_code;
900  env->last_error.engine_reserved = engine_reserved;
901  return error_code;
902 }
903 
905  const napi_extended_error_info** result) {
906  CHECK_ENV(env);
907  CHECK_ARG(env, result);
908 
909  // you must update this assert to reference the last message
910  // in the napi_status enum each time a new error message is added.
911  // We don't have a napi_status_last as this would result in an ABI
912  // change each time a message was added.
913  static_assert(
914  node::arraysize(error_messages) == napi_escape_called_twice + 1,
915  "Count of error messages must match count of error values");
917 
918  // Wait until someone requests the last error information to fetch the error
919  // message string
922 
923  *result = &(env->last_error);
924  return napi_ok;
925 }
926 
927 NAPI_NO_RETURN void napi_fatal_error(const char* location,
928  const char* message) {
929  node::FatalError(location, message);
930 }
931 
933  const char* utf8name,
934  napi_callback cb,
935  void* callback_data,
936  napi_value* result) {
937  NAPI_PREAMBLE(env);
938  CHECK_ARG(env, result);
939  CHECK_ARG(env, cb);
940 
941  v8::Isolate* isolate = env->isolate;
942  v8::Local<v8::Function> return_value;
943  v8::EscapableHandleScope scope(isolate);
944  v8::Local<v8::Object> cbdata =
945  v8impl::CreateFunctionCallbackData(env, cb, callback_data);
946 
947  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
948 
949  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(
950  isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
951 
952  v8::Local<v8::Context> context = isolate->GetCurrentContext();
953  v8::MaybeLocal<v8::Function> maybe_function = tpl->GetFunction(context);
954  CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
955 
956  return_value = scope.Escape(maybe_function.ToLocalChecked());
957 
958  if (utf8name != nullptr) {
959  v8::Local<v8::String> name_string;
960  CHECK_NEW_FROM_UTF8(env, name_string, utf8name);
961  return_value->SetName(name_string);
962  }
963 
964  *result = v8impl::JsValueFromV8LocalValue(return_value);
965 
966  return GET_RETURN_STATUS(env);
967 }
968 
970  const char* utf8name,
971  napi_callback constructor,
972  void* callback_data,
973  size_t property_count,
974  const napi_property_descriptor* properties,
975  napi_value* result) {
976  NAPI_PREAMBLE(env);
977  CHECK_ARG(env, result);
978  CHECK_ARG(env, constructor);
979 
980  v8::Isolate* isolate = env->isolate;
981 
982  v8::EscapableHandleScope scope(isolate);
983  v8::Local<v8::Object> cbdata =
984  v8impl::CreateFunctionCallbackData(env, constructor, callback_data);
985 
986  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
987 
988  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(
989  isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
990 
991  v8::Local<v8::String> name_string;
992  CHECK_NEW_FROM_UTF8(env, name_string, utf8name);
993  tpl->SetClassName(name_string);
994 
995  size_t static_property_count = 0;
996  for (size_t i = 0; i < property_count; i++) {
997  const napi_property_descriptor* p = properties + i;
998 
999  if ((p->attributes & napi_static) != 0) {
1000  // Static properties are handled separately below.
1001  static_property_count++;
1002  continue;
1003  }
1004 
1005  v8::Local<v8::Name> property_name;
1007  v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
1008 
1009  if (status != napi_ok) {
1010  return napi_set_last_error(env, status);
1011  }
1012 
1013  v8::PropertyAttribute attributes =
1014  v8impl::V8PropertyAttributesFromDescriptor(p);
1015 
1016  // This code is similar to that in napi_define_properties(); the
1017  // difference is it applies to a template instead of an object.
1018  if (p->getter != nullptr || p->setter != nullptr) {
1019  v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData(
1020  env, p->getter, p->setter, p->data);
1021 
1022  tpl->PrototypeTemplate()->SetAccessor(
1023  property_name,
1024  p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
1025  p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
1026  cbdata,
1027  v8::AccessControl::DEFAULT,
1028  attributes);
1029  } else if (p->method != nullptr) {
1030  v8::Local<v8::Object> cbdata =
1031  v8impl::CreateFunctionCallbackData(env, p->method, p->data);
1032 
1033  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
1034 
1035  v8::Local<v8::FunctionTemplate> t =
1036  v8::FunctionTemplate::New(isolate,
1037  v8impl::FunctionCallbackWrapper::Invoke,
1038  cbdata,
1039  v8::Signature::New(isolate, tpl));
1040 
1041  tpl->PrototypeTemplate()->Set(property_name, t, attributes);
1042  } else {
1043  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1044  tpl->PrototypeTemplate()->Set(property_name, value, attributes);
1045  }
1046  }
1047 
1048  *result = v8impl::JsValueFromV8LocalValue(scope.Escape(tpl->GetFunction()));
1049 
1050  if (static_property_count > 0) {
1051  std::vector<napi_property_descriptor> static_descriptors;
1052  static_descriptors.reserve(static_property_count);
1053 
1054  for (size_t i = 0; i < property_count; i++) {
1055  const napi_property_descriptor* p = properties + i;
1056  if ((p->attributes & napi_static) != 0) {
1057  static_descriptors.push_back(*p);
1058  }
1059  }
1060 
1063  *result,
1064  static_descriptors.size(),
1065  static_descriptors.data());
1066  if (status != napi_ok) return status;
1067  }
1068 
1069  return GET_RETURN_STATUS(env);
1070 }
1071 
1073  napi_value object,
1074  napi_value* result) {
1075  NAPI_PREAMBLE(env);
1076  CHECK_ARG(env, result);
1077 
1078  v8::Isolate* isolate = env->isolate;
1079  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1080  v8::Local<v8::Object> obj;
1081  CHECK_TO_OBJECT(env, context, obj, object);
1082 
1083  auto maybe_propertynames = obj->GetPropertyNames(context);
1084 
1085  CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure);
1086 
1087  *result = v8impl::JsValueFromV8LocalValue(
1088  maybe_propertynames.ToLocalChecked());
1089  return GET_RETURN_STATUS(env);
1090 }
1091 
1093  napi_value object,
1094  napi_value key,
1095  napi_value value) {
1096  NAPI_PREAMBLE(env);
1097  CHECK_ARG(env, key);
1098  CHECK_ARG(env, value);
1099 
1100  v8::Isolate* isolate = env->isolate;
1101  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1102  v8::Local<v8::Object> obj;
1103 
1104  CHECK_TO_OBJECT(env, context, obj, object);
1105 
1106  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1107  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1108 
1109  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
1110 
1111  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1112  return GET_RETURN_STATUS(env);
1113 }
1114 
1116  napi_value object,
1117  napi_value key,
1118  bool* result) {
1119  NAPI_PREAMBLE(env);
1120  CHECK_ARG(env, result);
1121  CHECK_ARG(env, key);
1122 
1123  v8::Isolate* isolate = env->isolate;
1124  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1125  v8::Local<v8::Object> obj;
1126 
1127  CHECK_TO_OBJECT(env, context, obj, object);
1128 
1129  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1130  v8::Maybe<bool> has_maybe = obj->Has(context, k);
1131 
1132  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1133 
1134  *result = has_maybe.FromMaybe(false);
1135  return GET_RETURN_STATUS(env);
1136 }
1137 
1139  napi_value object,
1140  napi_value key,
1141  napi_value* result) {
1142  NAPI_PREAMBLE(env);
1143  CHECK_ARG(env, key);
1144  CHECK_ARG(env, result);
1145 
1146  v8::Isolate* isolate = env->isolate;
1147  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1148  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1149  v8::Local<v8::Object> obj;
1150 
1151  CHECK_TO_OBJECT(env, context, obj, object);
1152 
1153  auto get_maybe = obj->Get(context, k);
1154 
1155  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1156 
1157  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1158  *result = v8impl::JsValueFromV8LocalValue(val);
1159  return GET_RETURN_STATUS(env);
1160 }
1161 
1163  napi_value object,
1164  napi_value key,
1165  bool* result) {
1166  NAPI_PREAMBLE(env);
1167  CHECK_ARG(env, key);
1168 
1169  v8::Isolate* isolate = env->isolate;
1170  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1171  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1172  v8::Local<v8::Object> obj;
1173 
1174  CHECK_TO_OBJECT(env, context, obj, object);
1175  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
1176  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1177 
1178  if (result != NULL)
1179  *result = delete_maybe.FromMaybe(false);
1180 
1181  return GET_RETURN_STATUS(env);
1182 }
1183 
1185  napi_value object,
1186  napi_value key,
1187  bool* result) {
1188  NAPI_PREAMBLE(env);
1189  CHECK_ARG(env, key);
1190 
1191  v8::Isolate* isolate = env->isolate;
1192  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1193  v8::Local<v8::Object> obj;
1194 
1195  CHECK_TO_OBJECT(env, context, obj, object);
1196  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1197  RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected);
1198  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
1199  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1200  *result = has_maybe.FromMaybe(false);
1201 
1202  return GET_RETURN_STATUS(env);
1203 }
1204 
1206  napi_value object,
1207  const char* utf8name,
1208  napi_value value) {
1209  NAPI_PREAMBLE(env);
1210  CHECK_ARG(env, value);
1211 
1212  v8::Isolate* isolate = env->isolate;
1213  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1214  v8::Local<v8::Object> obj;
1215 
1216  CHECK_TO_OBJECT(env, context, obj, object);
1217 
1218  v8::Local<v8::Name> key;
1219  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1220 
1221  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1222 
1223  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1224 
1225  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1226  return GET_RETURN_STATUS(env);
1227 }
1228 
1230  napi_value object,
1231  const char* utf8name,
1232  bool* result) {
1233  NAPI_PREAMBLE(env);
1234  CHECK_ARG(env, result);
1235 
1236  v8::Isolate* isolate = env->isolate;
1237  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1238  v8::Local<v8::Object> obj;
1239 
1240  CHECK_TO_OBJECT(env, context, obj, object);
1241 
1242  v8::Local<v8::Name> key;
1243  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1244 
1245  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1246 
1247  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1248 
1249  *result = has_maybe.FromMaybe(false);
1250  return GET_RETURN_STATUS(env);
1251 }
1252 
1254  napi_value object,
1255  const char* utf8name,
1256  napi_value* result) {
1257  NAPI_PREAMBLE(env);
1258  CHECK_ARG(env, result);
1259 
1260  v8::Isolate* isolate = env->isolate;
1261  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1262 
1263  v8::Local<v8::Name> key;
1264  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1265 
1266  v8::Local<v8::Object> obj;
1267 
1268  CHECK_TO_OBJECT(env, context, obj, object);
1269 
1270  auto get_maybe = obj->Get(context, key);
1271 
1272  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1273 
1274  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1275  *result = v8impl::JsValueFromV8LocalValue(val);
1276  return GET_RETURN_STATUS(env);
1277 }
1278 
1280  napi_value object,
1281  uint32_t index,
1282  napi_value value) {
1283  NAPI_PREAMBLE(env);
1284  CHECK_ARG(env, value);
1285 
1286  v8::Isolate* isolate = env->isolate;
1287  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1288  v8::Local<v8::Object> obj;
1289 
1290  CHECK_TO_OBJECT(env, context, obj, object);
1291 
1292  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1293  auto set_maybe = obj->Set(context, index, val);
1294 
1295  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1296 
1297  return GET_RETURN_STATUS(env);
1298 }
1299 
1301  napi_value object,
1302  uint32_t index,
1303  bool* result) {
1304  NAPI_PREAMBLE(env);
1305  CHECK_ARG(env, result);
1306 
1307  v8::Isolate* isolate = env->isolate;
1308  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1309  v8::Local<v8::Object> obj;
1310 
1311  CHECK_TO_OBJECT(env, context, obj, object);
1312 
1313  v8::Maybe<bool> has_maybe = obj->Has(context, index);
1314 
1315  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1316 
1317  *result = has_maybe.FromMaybe(false);
1318  return GET_RETURN_STATUS(env);
1319 }
1320 
1322  napi_value object,
1323  uint32_t index,
1324  napi_value* result) {
1325  NAPI_PREAMBLE(env);
1326  CHECK_ARG(env, result);
1327 
1328  v8::Isolate* isolate = env->isolate;
1329  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1330  v8::Local<v8::Object> obj;
1331 
1332  CHECK_TO_OBJECT(env, context, obj, object);
1333 
1334  auto get_maybe = obj->Get(context, index);
1335 
1336  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1337 
1338  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
1339  return GET_RETURN_STATUS(env);
1340 }
1341 
1343  napi_value object,
1344  uint32_t index,
1345  bool* result) {
1346  NAPI_PREAMBLE(env);
1347 
1348  v8::Isolate* isolate = env->isolate;
1349  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1350  v8::Local<v8::Object> obj;
1351 
1352  CHECK_TO_OBJECT(env, context, obj, object);
1353  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
1354  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1355 
1356  if (result != NULL)
1357  *result = delete_maybe.FromMaybe(false);
1358 
1359  return GET_RETURN_STATUS(env);
1360 }
1361 
1363  napi_value object,
1364  size_t property_count,
1365  const napi_property_descriptor* properties) {
1366  NAPI_PREAMBLE(env);
1367  if (property_count > 0) {
1368  CHECK_ARG(env, properties);
1369  }
1370 
1371  v8::Isolate* isolate = env->isolate;
1372  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1373 
1374  v8::Local<v8::Object> obj;
1375  CHECK_TO_OBJECT(env, context, obj, object);
1376 
1377  for (size_t i = 0; i < property_count; i++) {
1378  const napi_property_descriptor* p = &properties[i];
1379 
1380  v8::Local<v8::Name> property_name;
1382  v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
1383 
1384  if (status != napi_ok) {
1385  return napi_set_last_error(env, status);
1386  }
1387 
1388  v8::PropertyAttribute attributes =
1389  v8impl::V8PropertyAttributesFromDescriptor(p);
1390 
1391  if (p->getter != nullptr || p->setter != nullptr) {
1392  v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData(
1393  env,
1394  p->getter,
1395  p->setter,
1396  p->data);
1397 
1398  auto set_maybe = obj->SetAccessor(
1399  context,
1400  property_name,
1401  p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
1402  p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
1403  cbdata,
1404  v8::AccessControl::DEFAULT,
1405  attributes);
1406 
1407  if (!set_maybe.FromMaybe(false)) {
1408  return napi_set_last_error(env, napi_invalid_arg);
1409  }
1410  } else if (p->method != nullptr) {
1411  v8::Local<v8::Object> cbdata =
1412  v8impl::CreateFunctionCallbackData(env, p->method, p->data);
1413 
1414  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
1415 
1416  v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(
1417  isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
1418 
1419  auto define_maybe = obj->DefineOwnProperty(
1420  context, property_name, t->GetFunction(), attributes);
1421 
1422  if (!define_maybe.FromMaybe(false)) {
1423  return napi_set_last_error(env, napi_generic_failure);
1424  }
1425  } else {
1426  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1427 
1428  auto define_maybe =
1429  obj->DefineOwnProperty(context, property_name, value, attributes);
1430 
1431  if (!define_maybe.FromMaybe(false)) {
1432  return napi_set_last_error(env, napi_invalid_arg);
1433  }
1434  }
1435  }
1436 
1437  return GET_RETURN_STATUS(env);
1438 }
1439 
1440 napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1441  CHECK_ENV(env);
1442  CHECK_ARG(env, value);
1443  CHECK_ARG(env, result);
1444 
1445  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1446 
1447  *result = val->IsArray();
1448  return napi_clear_last_error(env);
1449 }
1450 
1452  napi_value value,
1453  uint32_t* result) {
1454  NAPI_PREAMBLE(env);
1455  CHECK_ARG(env, value);
1456  CHECK_ARG(env, result);
1457 
1458  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1459  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1460 
1461  v8::Local<v8::Array> arr = val.As<v8::Array>();
1462  *result = arr->Length();
1463 
1464  return GET_RETURN_STATUS(env);
1465 }
1466 
1468  napi_value lhs,
1469  napi_value rhs,
1470  bool* result) {
1471  NAPI_PREAMBLE(env);
1472  CHECK_ARG(env, lhs);
1473  CHECK_ARG(env, rhs);
1474  CHECK_ARG(env, result);
1475 
1476  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1477  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1478 
1479  *result = a->StrictEquals(b);
1480  return GET_RETURN_STATUS(env);
1481 }
1482 
1484  napi_value object,
1485  napi_value* result) {
1486  NAPI_PREAMBLE(env);
1487  CHECK_ARG(env, result);
1488 
1489  v8::Isolate* isolate = env->isolate;
1490  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1491 
1492  v8::Local<v8::Object> obj;
1493  CHECK_TO_OBJECT(env, context, obj, object);
1494 
1495  v8::Local<v8::Value> val = obj->GetPrototype();
1496  *result = v8impl::JsValueFromV8LocalValue(val);
1497  return GET_RETURN_STATUS(env);
1498 }
1499 
1501  CHECK_ENV(env);
1502  CHECK_ARG(env, result);
1503 
1504  *result = v8impl::JsValueFromV8LocalValue(
1505  v8::Object::New(env->isolate));
1506 
1507  return napi_clear_last_error(env);
1508 }
1509 
1511  CHECK_ENV(env);
1512  CHECK_ARG(env, result);
1513 
1514  *result = v8impl::JsValueFromV8LocalValue(
1515  v8::Array::New(env->isolate));
1516 
1517  return napi_clear_last_error(env);
1518 }
1519 
1521  size_t length,
1522  napi_value* result) {
1523  CHECK_ENV(env);
1524  CHECK_ARG(env, result);
1525 
1526  *result = v8impl::JsValueFromV8LocalValue(
1527  v8::Array::New(env->isolate, length));
1528 
1529  return napi_clear_last_error(env);
1530 }
1531 
1533  const char* str,
1534  size_t length,
1535  napi_value* result) {
1536  CHECK_ENV(env);
1537  CHECK_ARG(env, result);
1538 
1539  auto isolate = env->isolate;
1540  auto str_maybe =
1541  v8::String::NewFromOneByte(isolate,
1542  reinterpret_cast<const uint8_t*>(str),
1543  v8::NewStringType::kInternalized,
1544  length);
1545  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1546 
1547  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1548  return napi_clear_last_error(env);
1549 }
1550 
1552  const char* str,
1553  size_t length,
1554  napi_value* result) {
1555  CHECK_ENV(env);
1556  CHECK_ARG(env, result);
1557 
1558  v8::Local<v8::String> s;
1559  CHECK_NEW_FROM_UTF8_LEN(env, s, str, length);
1560 
1561  *result = v8impl::JsValueFromV8LocalValue(s);
1562  return napi_clear_last_error(env);
1563 }
1564 
1566  const char16_t* str,
1567  size_t length,
1568  napi_value* result) {
1569  CHECK_ENV(env);
1570  CHECK_ARG(env, result);
1571 
1572  auto isolate = env->isolate;
1573  auto str_maybe =
1574  v8::String::NewFromTwoByte(isolate,
1575  reinterpret_cast<const uint16_t*>(str),
1576  v8::NewStringType::kInternalized,
1577  length);
1578  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1579 
1580  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1581  return napi_clear_last_error(env);
1582 }
1583 
1585  double value,
1586  napi_value* result) {
1587  CHECK_ENV(env);
1588  CHECK_ARG(env, result);
1589 
1590  *result = v8impl::JsValueFromV8LocalValue(
1591  v8::Number::New(env->isolate, value));
1592 
1593  return napi_clear_last_error(env);
1594 }
1595 
1597  int32_t value,
1598  napi_value* result) {
1599  CHECK_ENV(env);
1600  CHECK_ARG(env, result);
1601 
1602  *result = v8impl::JsValueFromV8LocalValue(
1603  v8::Integer::New(env->isolate, value));
1604 
1605  return napi_clear_last_error(env);
1606 }
1607 
1609  uint32_t value,
1610  napi_value* result) {
1611  CHECK_ENV(env);
1612  CHECK_ARG(env, result);
1613 
1614  *result = v8impl::JsValueFromV8LocalValue(
1615  v8::Integer::NewFromUnsigned(env->isolate, value));
1616 
1617  return napi_clear_last_error(env);
1618 }
1619 
1621  int64_t value,
1622  napi_value* result) {
1623  CHECK_ENV(env);
1624  CHECK_ARG(env, result);
1625 
1626  *result = v8impl::JsValueFromV8LocalValue(
1627  v8::Number::New(env->isolate, static_cast<double>(value)));
1628 
1629  return napi_clear_last_error(env);
1630 }
1631 
1633  CHECK_ENV(env);
1634  CHECK_ARG(env, result);
1635 
1636  v8::Isolate* isolate = env->isolate;
1637 
1638  if (value) {
1639  *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
1640  } else {
1641  *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
1642  }
1643 
1644  return napi_clear_last_error(env);
1645 }
1646 
1648  napi_value description,
1649  napi_value* result) {
1650  CHECK_ENV(env);
1651  CHECK_ARG(env, result);
1652 
1653  v8::Isolate* isolate = env->isolate;
1654 
1655  if (description == nullptr) {
1656  *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
1657  } else {
1658  v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
1659  RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
1660 
1661  *result = v8impl::JsValueFromV8LocalValue(
1662  v8::Symbol::New(isolate, desc.As<v8::String>()));
1663  }
1664 
1665  return napi_clear_last_error(env);
1666 }
1667 
1668 static napi_status set_error_code(napi_env env,
1669  v8::Local<v8::Value> error,
1670  napi_value code,
1671  const char* code_cstring) {
1672  if ((code != nullptr) || (code_cstring != nullptr)) {
1673  v8::Isolate* isolate = env->isolate;
1674  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1675  v8::Local<v8::Object> err_object = error.As<v8::Object>();
1676 
1677  v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1678  if (code != nullptr) {
1679  code_value = v8impl::V8LocalValueFromJsValue(code);
1680  RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1681  } else {
1682  CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
1683  }
1684 
1685  v8::Local<v8::Name> code_key;
1686  CHECK_NEW_FROM_UTF8(env, code_key, "code");
1687 
1688  v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
1690  set_maybe.FromMaybe(false),
1692 
1693  // now update the name to be "name [code]" where name is the
1694  // original name and code is the code associated with the Error
1695  v8::Local<v8::String> name_string;
1696  CHECK_NEW_FROM_UTF8(env, name_string, "");
1697  v8::Local<v8::Name> name_key;
1698  CHECK_NEW_FROM_UTF8(env, name_key, "name");
1699 
1700  auto maybe_name = err_object->Get(context, name_key);
1701  if (!maybe_name.IsEmpty()) {
1702  v8::Local<v8::Value> name = maybe_name.ToLocalChecked();
1703  if (name->IsString()) {
1704  name_string = v8::String::Concat(name_string, name.As<v8::String>());
1705  }
1706  }
1707  name_string = v8::String::Concat(name_string,
1708  FIXED_ONE_BYTE_STRING(isolate, " ["));
1709  name_string = v8::String::Concat(name_string, code_value.As<v8::String>());
1710  name_string = v8::String::Concat(name_string,
1711  FIXED_ONE_BYTE_STRING(isolate, "]"));
1712 
1713  set_maybe = err_object->Set(context, name_key, name_string);
1715  set_maybe.FromMaybe(false),
1717  }
1718  return napi_ok;
1719 }
1720 
1722  napi_value code,
1723  napi_value msg,
1724  napi_value* result) {
1725  CHECK_ENV(env);
1726  CHECK_ARG(env, msg);
1727  CHECK_ARG(env, result);
1728 
1729  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1730  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1731 
1732  v8::Local<v8::Value> error_obj =
1733  v8::Exception::Error(message_value.As<v8::String>());
1734  napi_status status = set_error_code(env, error_obj, code, nullptr);
1735  if (status != napi_ok) return status;
1736 
1737  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1738 
1739  return napi_clear_last_error(env);
1740 }
1741 
1743  napi_value code,
1744  napi_value msg,
1745  napi_value* result) {
1746  CHECK_ENV(env);
1747  CHECK_ARG(env, msg);
1748  CHECK_ARG(env, result);
1749 
1750  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1751  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1752 
1753  v8::Local<v8::Value> error_obj =
1754  v8::Exception::TypeError(message_value.As<v8::String>());
1755  napi_status status = set_error_code(env, error_obj, code, nullptr);
1756  if (status != napi_ok) return status;
1757 
1758  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1759 
1760  return napi_clear_last_error(env);
1761 }
1762 
1764  napi_value code,
1765  napi_value msg,
1766  napi_value* result) {
1767  CHECK_ENV(env);
1768  CHECK_ARG(env, msg);
1769  CHECK_ARG(env, result);
1770 
1771  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1772  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1773 
1774  v8::Local<v8::Value> error_obj =
1775  v8::Exception::RangeError(message_value.As<v8::String>());
1776  napi_status status = set_error_code(env, error_obj, code, nullptr);
1777  if (status != napi_ok) return status;
1778 
1779  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1780 
1781  return napi_clear_last_error(env);
1782 }
1783 
1785  napi_value value,
1786  napi_valuetype* result) {
1787  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1788  // JS exceptions.
1789  CHECK_ENV(env);
1790  CHECK_ARG(env, value);
1791  CHECK_ARG(env, result);
1792 
1793  v8::Local<v8::Value> v = v8impl::V8LocalValueFromJsValue(value);
1794 
1795  if (v->IsNumber()) {
1796  *result = napi_number;
1797  } else if (v->IsString()) {
1798  *result = napi_string;
1799  } else if (v->IsFunction()) {
1800  // This test has to come before IsObject because IsFunction
1801  // implies IsObject
1802  *result = napi_function;
1803  } else if (v->IsExternal()) {
1804  // This test has to come before IsObject because IsExternal
1805  // implies IsObject
1806  *result = napi_external;
1807  } else if (v->IsObject()) {
1808  *result = napi_object;
1809  } else if (v->IsBoolean()) {
1810  *result = napi_boolean;
1811  } else if (v->IsUndefined()) {
1812  *result = napi_undefined;
1813  } else if (v->IsSymbol()) {
1814  *result = napi_symbol;
1815  } else if (v->IsNull()) {
1816  *result = napi_null;
1817  } else {
1818  // Should not get here unless V8 has added some new kind of value.
1819  return napi_set_last_error(env, napi_invalid_arg);
1820  }
1821 
1822  return napi_clear_last_error(env);
1823 }
1824 
1826  CHECK_ENV(env);
1827  CHECK_ARG(env, result);
1828 
1829  *result = v8impl::JsValueFromV8LocalValue(
1830  v8::Undefined(env->isolate));
1831 
1832  return napi_clear_last_error(env);
1833 }
1834 
1836  CHECK_ENV(env);
1837  CHECK_ARG(env, result);
1838 
1839  *result = v8impl::JsValueFromV8LocalValue(
1840  v8::Null(env->isolate));
1841 
1842  return napi_clear_last_error(env);
1843 }
1844 
1845 // Gets all callback info in a single call. (Ugly, but faster.)
1847  napi_env env, // [in] NAPI environment handle
1848  napi_callback_info cbinfo, // [in] Opaque callback-info handle
1849  size_t* argc, // [in-out] Specifies the size of the provided argv array
1850  // and receives the actual count of args.
1851  napi_value* argv, // [out] Array of values
1852  napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
1853  void** data) { // [out] Receives the data pointer for the callback.
1854  CHECK_ENV(env);
1855  CHECK_ARG(env, cbinfo);
1856 
1857  v8impl::CallbackWrapper* info =
1858  reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1859 
1860  if (argv != nullptr) {
1861  CHECK_ARG(env, argc);
1862  info->Args(argv, *argc);
1863  }
1864  if (argc != nullptr) {
1865  *argc = info->ArgsLength();
1866  }
1867  if (this_arg != nullptr) {
1868  *this_arg = info->This();
1869  }
1870  if (data != nullptr) {
1871  *data = info->Data();
1872  }
1873 
1874  return napi_clear_last_error(env);
1875 }
1876 
1878  napi_callback_info cbinfo,
1879  bool* result) {
1880  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
1881  CHECK_ENV(env);
1882  CHECK_ARG(env, cbinfo);
1883  CHECK_ARG(env, result);
1884 
1885  v8impl::CallbackWrapper* info =
1886  reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1887 
1888  *result = info->IsConstructCall();
1889  return napi_clear_last_error(env);
1890 }
1891 
1893  napi_value recv,
1894  napi_value func,
1895  size_t argc,
1896  const napi_value* argv,
1897  napi_value* result) {
1898  NAPI_PREAMBLE(env);
1899  CHECK_ARG(env, recv);
1900  if (argc > 0) {
1901  CHECK_ARG(env, argv);
1902  }
1903 
1904  v8::Isolate* isolate = env->isolate;
1905  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1906 
1907  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1908 
1909  v8::Local<v8::Function> v8func;
1910  CHECK_TO_FUNCTION(env, v8func, func);
1911 
1912  auto maybe = v8func->Call(context, v8recv, argc,
1913  reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1914 
1915  if (try_catch.HasCaught()) {
1916  return napi_set_last_error(env, napi_pending_exception);
1917  } else {
1918  if (result != nullptr) {
1920  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1921  }
1922  return napi_clear_last_error(env);
1923  }
1924 }
1925 
1927  CHECK_ENV(env);
1928  CHECK_ARG(env, result);
1929 
1930  v8::Isolate* isolate = env->isolate;
1931  // TODO(ianhall): what if we need the global object from a different
1932  // context in the same isolate?
1933  // Should napi_env be the current context rather than the current isolate?
1934  v8::Local<v8::Context> context = isolate->GetCurrentContext();
1935  *result = v8impl::JsValueFromV8LocalValue(context->Global());
1936 
1937  return napi_clear_last_error(env);
1938 }
1939 
1941  NAPI_PREAMBLE(env);
1942  CHECK_ARG(env, error);
1943 
1944  v8::Isolate* isolate = env->isolate;
1945 
1946  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1947  // any VM calls after this point and before returning
1948  // to the javascript invoker will fail
1949  return napi_clear_last_error(env);
1950 }
1951 
1953  const char* code,
1954  const char* msg) {
1955  NAPI_PREAMBLE(env);
1956 
1957  v8::Isolate* isolate = env->isolate;
1958  v8::Local<v8::String> str;
1959  CHECK_NEW_FROM_UTF8(env, str, msg);
1960 
1961  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1962  napi_status status = set_error_code(env, error_obj, nullptr, code);
1963  if (status != napi_ok) return status;
1964 
1965  isolate->ThrowException(error_obj);
1966  // any VM calls after this point and before returning
1967  // to the javascript invoker will fail
1968  return napi_clear_last_error(env);
1969 }
1970 
1972  const char* code,
1973  const char* msg) {
1974  NAPI_PREAMBLE(env);
1975 
1976  v8::Isolate* isolate = env->isolate;
1977  v8::Local<v8::String> str;
1978  CHECK_NEW_FROM_UTF8(env, str, msg);
1979 
1980  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1981  napi_status status = set_error_code(env, error_obj, nullptr, code);
1982  if (status != napi_ok) return status;
1983 
1984  isolate->ThrowException(error_obj);
1985  // any VM calls after this point and before returning
1986  // to the javascript invoker will fail
1987  return napi_clear_last_error(env);
1988 }
1989 
1991  const char* code,
1992  const char* msg) {
1993  NAPI_PREAMBLE(env);
1994 
1995  v8::Isolate* isolate = env->isolate;
1996  v8::Local<v8::String> str;
1997  CHECK_NEW_FROM_UTF8(env, str, msg);
1998 
1999  v8::Local<v8::Value> error_obj = v8::Exception::RangeError(str);
2000  napi_status status = set_error_code(env, error_obj, nullptr, code);
2001  if (status != napi_ok) return status;
2002 
2003  isolate->ThrowException(error_obj);
2004  // any VM calls after this point and before returning
2005  // to the javascript invoker will fail
2006  return napi_clear_last_error(env);
2007 }
2008 
2009 napi_status napi_is_error(napi_env env, napi_value value, bool* result) {
2010  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot
2011  // throw JS exceptions.
2012  CHECK_ENV(env);
2013  CHECK_ARG(env, value);
2014  CHECK_ARG(env, result);
2015 
2016  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2017  *result = val->IsNativeError();
2018 
2019  return napi_clear_last_error(env);
2020 }
2021 
2023  napi_value value,
2024  double* result) {
2025  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2026  // JS exceptions.
2027  CHECK_ENV(env);
2028  CHECK_ARG(env, value);
2029  CHECK_ARG(env, result);
2030 
2031  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2032  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
2033 
2034  *result = val.As<v8::Number>()->Value();
2035 
2036  return napi_clear_last_error(env);
2037 }
2038 
2040  napi_value value,
2041  int32_t* result) {
2042  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2043  // JS exceptions.
2044  CHECK_ENV(env);
2045  CHECK_ARG(env, value);
2046  CHECK_ARG(env, result);
2047 
2048  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2049 
2050  if (val->IsInt32()) {
2051  *result = val.As<v8::Int32>()->Value();
2052  } else {
2053  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
2054 
2055  // Empty context: https://github.com/nodejs/node/issues/14379
2056  v8::Local<v8::Context> context;
2057  *result = val->Int32Value(context).FromJust();
2058  }
2059 
2060  return napi_clear_last_error(env);
2061 }
2062 
2064  napi_value value,
2065  uint32_t* result) {
2066  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2067  // JS exceptions.
2068  CHECK_ENV(env);
2069  CHECK_ARG(env, value);
2070  CHECK_ARG(env, result);
2071 
2072  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2073 
2074  if (val->IsUint32()) {
2075  *result = val.As<v8::Uint32>()->Value();
2076  } else {
2077  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
2078 
2079  // Empty context: https://github.com/nodejs/node/issues/14379
2080  v8::Local<v8::Context> context;
2081  *result = val->Uint32Value(context).FromJust();
2082  }
2083 
2084  return napi_clear_last_error(env);
2085 }
2086 
2088  napi_value value,
2089  int64_t* result) {
2090  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2091  // JS exceptions.
2092  CHECK_ENV(env);
2093  CHECK_ARG(env, value);
2094  CHECK_ARG(env, result);
2095 
2096  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2097 
2098  // This is still a fast path very likely to be taken.
2099  if (val->IsInt32()) {
2100  *result = val.As<v8::Int32>()->Value();
2101  return napi_clear_last_error(env);
2102  }
2103 
2104  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
2105 
2106  // v8::Value::IntegerValue() converts NaN to INT64_MIN, inconsistent with
2107  // v8::Value::Int32Value() that converts NaN to 0. So special-case NaN here.
2108  double doubleValue = val.As<v8::Number>()->Value();
2109  if (std::isnan(doubleValue)) {
2110  *result = 0;
2111  } else {
2112  // Empty context: https://github.com/nodejs/node/issues/14379
2113  v8::Local<v8::Context> context;
2114  *result = val->IntegerValue(context).FromJust();
2115  }
2116 
2117  return napi_clear_last_error(env);
2118 }
2119 
2121  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2122  // JS exceptions.
2123  CHECK_ENV(env);
2124  CHECK_ARG(env, value);
2125  CHECK_ARG(env, result);
2126 
2127  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2128  RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected);
2129 
2130  *result = val.As<v8::Boolean>()->Value();
2131 
2132  return napi_clear_last_error(env);
2133 }
2134 
2135 // Copies a JavaScript string into a LATIN-1 string buffer. The result is the
2136 // number of bytes (excluding the null terminator) copied into buf.
2137 // A sufficient buffer size should be greater than the length of string,
2138 // reserving space for null terminator.
2139 // If bufsize is insufficient, the string will be truncated and null terminated.
2140 // If buf is NULL, this method returns the length of the string (in bytes)
2141 // via the result parameter.
2142 // The result argument is optional unless buf is NULL.
2144  napi_value value,
2145  char* buf,
2146  size_t bufsize,
2147  size_t* result) {
2148  CHECK_ENV(env);
2149  CHECK_ARG(env, value);
2150 
2151  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2152  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2153 
2154  if (!buf) {
2155  CHECK_ARG(env, result);
2156  *result = val.As<v8::String>()->Length();
2157  } else {
2158  int copied = val.As<v8::String>()->WriteOneByte(
2159  reinterpret_cast<uint8_t*>(buf), 0, bufsize - 1,
2160  v8::String::NO_NULL_TERMINATION);
2161 
2162  buf[copied] = '\0';
2163  if (result != nullptr) {
2164  *result = copied;
2165  }
2166  }
2167 
2168  return napi_clear_last_error(env);
2169 }
2170 
2171 // Copies a JavaScript string into a UTF-8 string buffer. The result is the
2172 // number of bytes (excluding the null terminator) copied into buf.
2173 // A sufficient buffer size should be greater than the length of string,
2174 // reserving space for null terminator.
2175 // If bufsize is insufficient, the string will be truncated and null terminated.
2176 // If buf is NULL, this method returns the length of the string (in bytes)
2177 // via the result parameter.
2178 // The result argument is optional unless buf is NULL.
2180  napi_value value,
2181  char* buf,
2182  size_t bufsize,
2183  size_t* result) {
2184  CHECK_ENV(env);
2185  CHECK_ARG(env, value);
2186 
2187  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2188  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2189 
2190  if (!buf) {
2191  CHECK_ARG(env, result);
2192  *result = val.As<v8::String>()->Utf8Length();
2193  } else {
2194  int copied = val.As<v8::String>()->WriteUtf8(
2195  buf, bufsize - 1, nullptr, v8::String::REPLACE_INVALID_UTF8 |
2196  v8::String::NO_NULL_TERMINATION);
2197 
2198  buf[copied] = '\0';
2199  if (result != nullptr) {
2200  *result = copied;
2201  }
2202  }
2203 
2204  return napi_clear_last_error(env);
2205 }
2206 
2207 // Copies a JavaScript string into a UTF-16 string buffer. The result is the
2208 // number of 2-byte code units (excluding the null terminator) copied into buf.
2209 // A sufficient buffer size should be greater than the length of string,
2210 // reserving space for null terminator.
2211 // If bufsize is insufficient, the string will be truncated and null terminated.
2212 // If buf is NULL, this method returns the length of the string (in 2-byte
2213 // code units) via the result parameter.
2214 // The result argument is optional unless buf is NULL.
2216  napi_value value,
2217  char16_t* buf,
2218  size_t bufsize,
2219  size_t* result) {
2220  CHECK_ENV(env);
2221  CHECK_ARG(env, value);
2222 
2223  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2224  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2225 
2226  if (!buf) {
2227  CHECK_ARG(env, result);
2228  // V8 assumes UTF-16 length is the same as the number of characters.
2229  *result = val.As<v8::String>()->Length();
2230  } else {
2231  int copied = val.As<v8::String>()->Write(
2232  reinterpret_cast<uint16_t*>(buf), 0, bufsize - 1,
2233  v8::String::NO_NULL_TERMINATION);
2234 
2235  buf[copied] = '\0';
2236  if (result != nullptr) {
2237  *result = copied;
2238  }
2239  }
2240 
2241  return napi_clear_last_error(env);
2242 }
2243 
2245  napi_value value,
2246  napi_value* result) {
2247  NAPI_PREAMBLE(env);
2248  CHECK_ARG(env, value);
2249  CHECK_ARG(env, result);
2250 
2251  v8::Isolate* isolate = env->isolate;
2252  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2253  v8::Local<v8::Object> obj;
2254  CHECK_TO_OBJECT(env, context, obj, value);
2255 
2256  *result = v8impl::JsValueFromV8LocalValue(obj);
2257  return GET_RETURN_STATUS(env);
2258 }
2259 
2261  napi_value value,
2262  napi_value* result) {
2263  NAPI_PREAMBLE(env);
2264  CHECK_ARG(env, value);
2265  CHECK_ARG(env, result);
2266 
2267  v8::Isolate* isolate = env->isolate;
2268  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2269  v8::Local<v8::Boolean> b;
2270 
2271  CHECK_TO_BOOL(env, context, b, value);
2272 
2273  *result = v8impl::JsValueFromV8LocalValue(b);
2274  return GET_RETURN_STATUS(env);
2275 }
2276 
2278  napi_value value,
2279  napi_value* result) {
2280  NAPI_PREAMBLE(env);
2281  CHECK_ARG(env, value);
2282  CHECK_ARG(env, result);
2283 
2284  v8::Isolate* isolate = env->isolate;
2285  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2286  v8::Local<v8::Number> num;
2287 
2288  CHECK_TO_NUMBER(env, context, num, value);
2289 
2290  *result = v8impl::JsValueFromV8LocalValue(num);
2291  return GET_RETURN_STATUS(env);
2292 }
2293 
2295  napi_value value,
2296  napi_value* result) {
2297  NAPI_PREAMBLE(env);
2298  CHECK_ARG(env, value);
2299  CHECK_ARG(env, result);
2300 
2301  v8::Isolate* isolate = env->isolate;
2302  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2303  v8::Local<v8::String> str;
2304 
2305  CHECK_TO_STRING(env, context, str, value);
2306 
2307  *result = v8impl::JsValueFromV8LocalValue(str);
2308  return GET_RETURN_STATUS(env);
2309 }
2310 
2312  napi_value js_object,
2313  void* native_object,
2314  napi_finalize finalize_cb,
2315  void* finalize_hint,
2316  napi_ref* result) {
2317  NAPI_PREAMBLE(env);
2318  CHECK_ARG(env, js_object);
2319 
2320  v8::Isolate* isolate = env->isolate;
2321  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2322 
2323  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
2324  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
2325  v8::Local<v8::Object> obj = value.As<v8::Object>();
2326 
2327  // If we've already wrapped this object, we error out.
2328  RETURN_STATUS_IF_FALSE(env, !v8impl::FindWrapper(obj), napi_invalid_arg);
2329 
2330  // Create a wrapper object with an internal field to hold the wrapped pointer
2331  // and a second internal field to identify the owner as N-API.
2332  v8::Local<v8::ObjectTemplate> wrapper_template;
2333  ENV_OBJECT_TEMPLATE(env, wrap, wrapper_template, v8impl::kWrapperFields);
2334 
2335  auto maybe_object = wrapper_template->NewInstance(context);
2336  CHECK_MAYBE_EMPTY(env, maybe_object, napi_generic_failure);
2337  v8::Local<v8::Object> wrapper = maybe_object.ToLocalChecked();
2338 
2339  // Store the pointer as an external in the wrapper.
2340  wrapper->SetInternalField(0, v8::External::New(isolate, native_object));
2341  wrapper->SetInternalField(1, v8::External::New(isolate,
2342  reinterpret_cast<void*>(const_cast<char*>(v8impl::napi_wrap_name))));
2343 
2344  // Insert the wrapper into the object's prototype chain.
2345  v8::Local<v8::Value> proto = obj->GetPrototype();
2346  CHECK(wrapper->SetPrototype(context, proto).FromJust());
2347  CHECK(obj->SetPrototype(context, wrapper).FromJust());
2348 
2349  v8impl::Reference* reference = nullptr;
2350  if (result != nullptr) {
2351  // The returned reference should be deleted via napi_delete_reference()
2352  // ONLY in response to the finalize callback invocation. (If it is deleted
2353  // before then, then the finalize callback will never be invoked.)
2354  // Therefore a finalize callback is required when returning a reference.
2355  CHECK_ARG(env, finalize_cb);
2356  reference = v8impl::Reference::New(
2357  env, obj, 0, false, finalize_cb, native_object, finalize_hint);
2358  *result = reinterpret_cast<napi_ref>(reference);
2359  } else if (finalize_cb != nullptr) {
2360  // Create a self-deleting reference just for the finalize callback.
2361  reference = v8impl::Reference::New(
2362  env, obj, 0, true, finalize_cb, native_object, finalize_hint);
2363  }
2364 
2365  if (reference != nullptr) {
2366  wrapper->SetInternalField(2, v8::External::New(isolate, reference));
2367  }
2368 
2369  return GET_RETURN_STATUS(env);
2370 }
2371 
2372 napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2373  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2374  // JS exceptions.
2375  CHECK_ENV(env);
2376  v8::Local<v8::Object> wrapper;
2377  return napi_set_last_error(env, v8impl::Unwrap(env, obj, result, &wrapper));
2378 }
2379 
2381  NAPI_PREAMBLE(env);
2382  v8::Local<v8::Object> wrapper;
2383  v8::Local<v8::Object> parent;
2384  napi_status status = v8impl::Unwrap(env, obj, result, &wrapper, &parent);
2385  if (status != napi_ok) {
2386  return napi_set_last_error(env, status);
2387  }
2388 
2389  v8::Local<v8::Value> external = wrapper->GetInternalField(2);
2390  if (external->IsExternal()) {
2391  v8impl::Reference::Delete(
2392  static_cast<v8impl::Reference*>(external.As<v8::External>()->Value()));
2393  }
2394 
2395  if (!parent.IsEmpty()) {
2396  v8::Maybe<bool> maybe = parent->SetPrototype(
2397  env->isolate->GetCurrentContext(), wrapper->GetPrototype());
2399  if (!maybe.FromMaybe(false)) {
2400  return napi_set_last_error(env, napi_generic_failure);
2401  }
2402  }
2403 
2404  return GET_RETURN_STATUS(env);
2405 }
2406 
2408  void* data,
2409  napi_finalize finalize_cb,
2410  void* finalize_hint,
2411  napi_value* result) {
2412  NAPI_PREAMBLE(env);
2413  CHECK_ARG(env, result);
2414 
2415  v8::Isolate* isolate = env->isolate;
2416 
2417  v8::Local<v8::Value> external_value = v8::External::New(isolate, data);
2418 
2419  // The Reference object will delete itself after invoking the finalizer
2420  // callback.
2422  external_value,
2423  0,
2424  true,
2425  finalize_cb,
2426  data,
2427  finalize_hint);
2428 
2429  *result = v8impl::JsValueFromV8LocalValue(external_value);
2430 
2431  return napi_clear_last_error(env);
2432 }
2433 
2435  napi_value value,
2436  void** result) {
2437  CHECK_ENV(env);
2438  CHECK_ARG(env, value);
2439  CHECK_ARG(env, result);
2440 
2441  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2442  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
2443 
2444  v8::Local<v8::External> external_value = val.As<v8::External>();
2445  *result = external_value->Value();
2446 
2447  return napi_clear_last_error(env);
2448 }
2449 
2450 // Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
2452  napi_value value,
2453  uint32_t initial_refcount,
2454  napi_ref* result) {
2455  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2456  // JS exceptions.
2457  CHECK_ENV(env);
2458  CHECK_ARG(env, value);
2459  CHECK_ARG(env, result);
2460 
2461  v8impl::Reference* reference = v8impl::Reference::New(
2462  env, v8impl::V8LocalValueFromJsValue(value), initial_refcount, false);
2463 
2464  *result = reinterpret_cast<napi_ref>(reference);
2465  return napi_clear_last_error(env);
2466 }
2467 
2468 // Deletes a reference. The referenced value is released, and may be GC'd unless
2469 // there are other references to it.
2471  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2472  // JS exceptions.
2473  CHECK_ENV(env);
2474  CHECK_ARG(env, ref);
2475 
2476  v8impl::Reference::Delete(reinterpret_cast<v8impl::Reference*>(ref));
2477 
2478  return napi_clear_last_error(env);
2479 }
2480 
2481 // Increments the reference count, optionally returning the resulting count.
2482 // After this call the reference will be a strong reference because its
2483 // refcount is >0, and the referenced object is effectively "pinned".
2484 // Calling this when the refcount is 0 and the object is unavailable
2485 // results in an error.
2486 napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) {
2487  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2488  // JS exceptions.
2489  CHECK_ENV(env);
2490  CHECK_ARG(env, ref);
2491 
2492  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2493  uint32_t count = reference->Ref();
2494 
2495  if (result != nullptr) {
2496  *result = count;
2497  }
2498 
2499  return napi_clear_last_error(env);
2500 }
2501 
2502 // Decrements the reference count, optionally returning the resulting count. If
2503 // the result is 0 the reference is now weak and the object may be GC'd at any
2504 // time if there are no other references. Calling this when the refcount is
2505 // already 0 results in an error.
2506 napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) {
2507  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2508  // JS exceptions.
2509  CHECK_ENV(env);
2510  CHECK_ARG(env, ref);
2511 
2512  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2513 
2514  if (reference->RefCount() == 0) {
2515  return napi_set_last_error(env, napi_generic_failure);
2516  }
2517 
2518  uint32_t count = reference->Unref();
2519 
2520  if (result != nullptr) {
2521  *result = count;
2522  }
2523 
2524  return napi_clear_last_error(env);
2525 }
2526 
2527 // Attempts to get a referenced value. If the reference is weak, the value might
2528 // no longer be available, in that case the call is still successful but the
2529 // result is NULL.
2531  napi_ref ref,
2532  napi_value* result) {
2533  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2534  // JS exceptions.
2535  CHECK_ENV(env);
2536  CHECK_ARG(env, ref);
2537  CHECK_ARG(env, result);
2538 
2539  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2540  *result = v8impl::JsValueFromV8LocalValue(reference->Get());
2541 
2542  return napi_clear_last_error(env);
2543 }
2544 
2546  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2547  // JS exceptions.
2548  CHECK_ENV(env);
2549  CHECK_ARG(env, result);
2550 
2551  *result = v8impl::JsHandleScopeFromV8HandleScope(
2552  new v8impl::HandleScopeWrapper(env->isolate));
2553  return napi_clear_last_error(env);
2554 }
2555 
2557  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2558  // JS exceptions.
2559  CHECK_ENV(env);
2560  CHECK_ARG(env, scope);
2561 
2562  delete v8impl::V8HandleScopeFromJsHandleScope(scope);
2563  return napi_clear_last_error(env);
2564 }
2565 
2567  napi_env env,
2568  napi_escapable_handle_scope* result) {
2569  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2570  // JS exceptions.
2571  CHECK_ENV(env);
2572  CHECK_ARG(env, result);
2573 
2574  *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope(
2575  new v8impl::EscapableHandleScopeWrapper(env->isolate));
2576  return napi_clear_last_error(env);
2577 }
2578 
2580  napi_env env,
2582  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2583  // JS exceptions.
2584  CHECK_ENV(env);
2585  CHECK_ARG(env, scope);
2586 
2587  delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2588  return napi_clear_last_error(env);
2589 }
2590 
2593  napi_value escapee,
2594  napi_value* result) {
2595  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2596  // JS exceptions.
2597  CHECK_ENV(env);
2598  CHECK_ARG(env, scope);
2599  CHECK_ARG(env, escapee);
2600  CHECK_ARG(env, result);
2601 
2602  v8impl::EscapableHandleScopeWrapper* s =
2603  v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2604  if (!s->escape_called()) {
2605  *result = v8impl::JsValueFromV8LocalValue(
2606  s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
2607  return napi_clear_last_error(env);
2608  }
2609  return napi_set_last_error(env, napi_escape_called_twice);
2610 }
2611 
2613  napi_value constructor,
2614  size_t argc,
2615  const napi_value* argv,
2616  napi_value* result) {
2617  NAPI_PREAMBLE(env);
2618  CHECK_ARG(env, constructor);
2619  if (argc > 0) {
2620  CHECK_ARG(env, argv);
2621  }
2622  CHECK_ARG(env, result);
2623 
2624  v8::Isolate* isolate = env->isolate;
2625  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2626 
2627  v8::Local<v8::Function> ctor;
2628  CHECK_TO_FUNCTION(env, ctor, constructor);
2629 
2630  auto maybe = ctor->NewInstance(context, argc,
2631  reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2632 
2634 
2635  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2636  return GET_RETURN_STATUS(env);
2637 }
2638 
2640  napi_value object,
2641  napi_value constructor,
2642  bool* result) {
2643  NAPI_PREAMBLE(env);
2644  CHECK_ARG(env, object);
2645  CHECK_ARG(env, result);
2646 
2647  *result = false;
2648 
2649  v8::Local<v8::Object> ctor;
2650  v8::Isolate* isolate = env->isolate;
2651  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2652 
2653  CHECK_TO_OBJECT(env, context, ctor, constructor);
2654 
2655  if (!ctor->IsFunction()) {
2657  "ERR_NAPI_CONS_FUNCTION",
2658  "Constructor must be a function");
2659 
2660  return napi_set_last_error(env, napi_function_expected);
2661  }
2662 
2663  if (env->has_instance_available) {
2664  napi_value value, js_result = nullptr, has_instance = nullptr;
2666  napi_valuetype value_type;
2667 
2668  // Get "Symbol" from the global object
2669  if (env->has_instance.IsEmpty()) {
2670  status = napi_get_global(env, &value);
2671  if (status != napi_ok) return status;
2672  status = napi_get_named_property(env, value, "Symbol", &value);
2673  if (status != napi_ok) return status;
2674  status = napi_typeof(env, value, &value_type);
2675  if (status != napi_ok) return status;
2676 
2677  // Get "hasInstance" from Symbol
2678  if (value_type == napi_function) {
2679  status = napi_get_named_property(env, value, "hasInstance", &value);
2680  if (status != napi_ok) return status;
2681  status = napi_typeof(env, value, &value_type);
2682  if (status != napi_ok) return status;
2683 
2684  // Store Symbol.hasInstance in a global persistent reference
2685  if (value_type == napi_symbol) {
2686  env->has_instance.Reset(env->isolate,
2687  v8impl::V8LocalValueFromJsValue(value));
2688  has_instance = value;
2689  }
2690  }
2691  } else {
2692  has_instance = v8impl::JsValueFromV8LocalValue(
2694  }
2695 
2696  if (has_instance) {
2697  status = napi_get_property(env, constructor, has_instance, &value);
2698  if (status != napi_ok) return status;
2699  status = napi_typeof(env, value, &value_type);
2700  if (status != napi_ok) return status;
2701 
2702  // Call the function to determine whether the object is an instance of the
2703  // constructor
2704  if (value_type == napi_function) {
2705  status = napi_call_function(env, constructor, value, 1, &object,
2706  &js_result);
2707  if (status != napi_ok) return status;
2708  return napi_get_value_bool(env, js_result, result);
2709  }
2710  }
2711 
2712  env->has_instance_available = false;
2713  }
2714 
2715  // If running constructor[Symbol.hasInstance](object) did not work, we perform
2716  // a traditional instanceof (early Node.js 6.x).
2717 
2718  v8::Local<v8::String> prototype_string;
2719  CHECK_NEW_FROM_UTF8(env, prototype_string, "prototype");
2720 
2721  auto maybe_prototype = ctor->Get(context, prototype_string);
2722  CHECK_MAYBE_EMPTY(env, maybe_prototype, napi_generic_failure);
2723 
2724  v8::Local<v8::Value> prototype_property = maybe_prototype.ToLocalChecked();
2725  if (!prototype_property->IsObject()) {
2727  env,
2728  "ERR_NAPI_CONS_PROTOTYPE_OBJECT",
2729  "Constructor.prototype must be an object");
2730 
2731  return napi_set_last_error(env, napi_object_expected);
2732  }
2733 
2734  auto maybe_ctor = prototype_property->ToObject(context);
2735  CHECK_MAYBE_EMPTY(env, maybe_ctor, napi_generic_failure);
2736  ctor = maybe_ctor.ToLocalChecked();
2737 
2738  v8::Local<v8::Value> current_obj = v8impl::V8LocalValueFromJsValue(object);
2739  if (!current_obj->StrictEquals(ctor)) {
2740  for (v8::Local<v8::Value> original_obj = current_obj;
2741  !(current_obj->IsNull() || current_obj->IsUndefined());) {
2742  if (current_obj->StrictEquals(ctor)) {
2743  *result = !(original_obj->IsNumber() ||
2744  original_obj->IsBoolean() ||
2745  original_obj->IsString());
2746  break;
2747  }
2748  v8::Local<v8::Object> obj;
2749  CHECK_TO_OBJECT(env, context, obj, v8impl::JsValueFromV8LocalValue(
2750  current_obj));
2751  current_obj = obj->GetPrototype();
2752  }
2753  }
2754 
2755  return GET_RETURN_STATUS(env);
2756 }
2757 
2759  napi_value recv,
2760  napi_value func,
2761  size_t argc,
2762  const napi_value* argv,
2763  napi_value* result) {
2764  NAPI_PREAMBLE(env);
2765  CHECK_ARG(env, recv);
2766  if (argc > 0) {
2767  CHECK_ARG(env, argv);
2768  }
2769 
2770  v8::Isolate* isolate = env->isolate;
2771  v8::Local<v8::Context> context = isolate->GetCurrentContext();
2772 
2773  v8::Local<v8::Object> v8recv;
2774  CHECK_TO_OBJECT(env, context, v8recv, recv);
2775 
2776  v8::Local<v8::Function> v8func;
2777  CHECK_TO_FUNCTION(env, v8func, func);
2778 
2779  v8::Local<v8::Value> callback_result = node::MakeCallback(
2780  isolate, v8recv, v8func, argc,
2781  reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2782 
2783  if (result != nullptr) {
2784  *result = v8impl::JsValueFromV8LocalValue(callback_result);
2785  }
2786 
2787  return GET_RETURN_STATUS(env);
2788 }
2789 
2790 // Methods to support catching exceptions
2792  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2793  // pending exception.
2794  CHECK_ENV(env);
2795  CHECK_ARG(env, result);
2796 
2797  *result = !env->last_exception.IsEmpty();
2798  return napi_clear_last_error(env);
2799 }
2800 
2802  napi_value* result) {
2803  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2804  // pending exception.
2805  CHECK_ENV(env);
2806  CHECK_ARG(env, result);
2807 
2808  if (env->last_exception.IsEmpty()) {
2809  return napi_get_undefined(env, result);
2810  } else {
2811  *result = v8impl::JsValueFromV8LocalValue(
2813  env->last_exception.Reset();
2814  }
2815 
2816  return napi_clear_last_error(env);
2817 }
2818 
2820  size_t length,
2821  void** data,
2822  napi_value* result) {
2823  NAPI_PREAMBLE(env);
2824  CHECK_ARG(env, result);
2825 
2826  auto maybe = node::Buffer::New(env->isolate, length);
2827 
2829 
2830  v8::Local<v8::Object> buffer = maybe.ToLocalChecked();
2831 
2832  *result = v8impl::JsValueFromV8LocalValue(buffer);
2833 
2834  if (data != nullptr) {
2835  *data = node::Buffer::Data(buffer);
2836  }
2837 
2838  return GET_RETURN_STATUS(env);
2839 }
2840 
2842  size_t length,
2843  void* data,
2844  napi_finalize finalize_cb,
2845  void* finalize_hint,
2846  napi_value* result) {
2847  NAPI_PREAMBLE(env);
2848  CHECK_ARG(env, result);
2849 
2850  v8::Isolate* isolate = env->isolate;
2851 
2852  // The finalizer object will delete itself after invoking the callback.
2853  v8impl::Finalizer* finalizer = v8impl::Finalizer::New(
2854  env, finalize_cb, nullptr, finalize_hint);
2855 
2856  auto maybe = node::Buffer::New(isolate,
2857  static_cast<char*>(data),
2858  length,
2859  v8impl::Finalizer::FinalizeBufferCallback,
2860  finalizer);
2861 
2863 
2864  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2865  return GET_RETURN_STATUS(env);
2866  // Tell coverity that 'finalizer' should not be freed when we return
2867  // as it will be deleted when the buffer to which it is associated
2868  // is finalized.
2869  // coverity[leaked_storage]
2870 }
2871 
2873  size_t length,
2874  const void* data,
2875  void** result_data,
2876  napi_value* result) {
2877  NAPI_PREAMBLE(env);
2878  CHECK_ARG(env, result);
2879 
2880  auto maybe = node::Buffer::Copy(env->isolate,
2881  static_cast<const char*>(data), length);
2882 
2884 
2885  v8::Local<v8::Object> buffer = maybe.ToLocalChecked();
2886  *result = v8impl::JsValueFromV8LocalValue(buffer);
2887 
2888  if (result_data != nullptr) {
2889  *result_data = node::Buffer::Data(buffer);
2890  }
2891 
2892  return GET_RETURN_STATUS(env);
2893 }
2894 
2895 napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) {
2896  CHECK_ENV(env);
2897  CHECK_ARG(env, value);
2898  CHECK_ARG(env, result);
2899 
2900  *result = node::Buffer::HasInstance(v8impl::V8LocalValueFromJsValue(value));
2901  return napi_clear_last_error(env);
2902 }
2903 
2905  napi_value value,
2906  void** data,
2907  size_t* length) {
2908  CHECK_ENV(env);
2909  CHECK_ARG(env, value);
2910 
2911  v8::Local<v8::Value> buffer = v8impl::V8LocalValueFromJsValue(value);
2912 
2913  if (data != nullptr) {
2914  *data = node::Buffer::Data(buffer);
2915  }
2916  if (length != nullptr) {
2917  *length = node::Buffer::Length(buffer);
2918  }
2919 
2920  return napi_clear_last_error(env);
2921 }
2922 
2924  CHECK_ENV(env);
2925  CHECK_ARG(env, value);
2926  CHECK_ARG(env, result);
2927 
2928  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2929  *result = val->IsArrayBuffer();
2930 
2931  return napi_clear_last_error(env);
2932 }
2933 
2935  size_t byte_length,
2936  void** data,
2937  napi_value* result) {
2938  NAPI_PREAMBLE(env);
2939  CHECK_ARG(env, result);
2940 
2941  v8::Isolate* isolate = env->isolate;
2942  v8::Local<v8::ArrayBuffer> buffer =
2943  v8::ArrayBuffer::New(isolate, byte_length);
2944 
2945  // Optionally return a pointer to the buffer's data, to avoid another call to
2946  // retrieve it.
2947  if (data != nullptr) {
2948  *data = buffer->GetContents().Data();
2949  }
2950 
2951  *result = v8impl::JsValueFromV8LocalValue(buffer);
2952  return GET_RETURN_STATUS(env);
2953 }
2954 
2956  void* external_data,
2957  size_t byte_length,
2958  napi_finalize finalize_cb,
2959  void* finalize_hint,
2960  napi_value* result) {
2961  NAPI_PREAMBLE(env);
2962  CHECK_ARG(env, result);
2963 
2964  v8::Isolate* isolate = env->isolate;
2965  v8::Local<v8::ArrayBuffer> buffer =
2966  v8::ArrayBuffer::New(isolate, external_data, byte_length);
2967 
2968  if (finalize_cb != nullptr) {
2969  // Create a self-deleting weak reference that invokes the finalizer
2970  // callback.
2972  buffer,
2973  0,
2974  true,
2975  finalize_cb,
2976  external_data,
2977  finalize_hint);
2978  }
2979 
2980  *result = v8impl::JsValueFromV8LocalValue(buffer);
2981  return GET_RETURN_STATUS(env);
2982 }
2983 
2985  napi_value arraybuffer,
2986  void** data,
2987  size_t* byte_length) {
2988  CHECK_ENV(env);
2989  CHECK_ARG(env, arraybuffer);
2990 
2991  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2992  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2993 
2994  v8::ArrayBuffer::Contents contents =
2995  value.As<v8::ArrayBuffer>()->GetContents();
2996 
2997  if (data != nullptr) {
2998  *data = contents.Data();
2999  }
3000 
3001  if (byte_length != nullptr) {
3002  *byte_length = contents.ByteLength();
3003  }
3004 
3005  return napi_clear_last_error(env);
3006 }
3007 
3009  CHECK_ENV(env);
3010  CHECK_ARG(env, value);
3011  CHECK_ARG(env, result);
3012 
3013  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
3014  *result = val->IsTypedArray();
3015 
3016  return napi_clear_last_error(env);
3017 }
3018 
3020  napi_typedarray_type type,
3021  size_t length,
3022  napi_value arraybuffer,
3023  size_t byte_offset,
3024  napi_value* result) {
3025  NAPI_PREAMBLE(env);
3026  CHECK_ARG(env, arraybuffer);
3027  CHECK_ARG(env, result);
3028 
3029  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3030  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
3031 
3032  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
3033  v8::Local<v8::TypedArray> typedArray;
3034 
3035  switch (type) {
3036  case napi_int8_array:
3037  typedArray = v8::Int8Array::New(buffer, byte_offset, length);
3038  break;
3039  case napi_uint8_array:
3040  typedArray = v8::Uint8Array::New(buffer, byte_offset, length);
3041  break;
3043  typedArray = v8::Uint8ClampedArray::New(buffer, byte_offset, length);
3044  break;
3045  case napi_int16_array:
3046  typedArray = v8::Int16Array::New(buffer, byte_offset, length);
3047  break;
3048  case napi_uint16_array:
3049  typedArray = v8::Uint16Array::New(buffer, byte_offset, length);
3050  break;
3051  case napi_int32_array:
3052  typedArray = v8::Int32Array::New(buffer, byte_offset, length);
3053  break;
3054  case napi_uint32_array:
3055  typedArray = v8::Uint32Array::New(buffer, byte_offset, length);
3056  break;
3057  case napi_float32_array:
3058  typedArray = v8::Float32Array::New(buffer, byte_offset, length);
3059  break;
3060  case napi_float64_array:
3061  typedArray = v8::Float64Array::New(buffer, byte_offset, length);
3062  break;
3063  default:
3064  return napi_set_last_error(env, napi_invalid_arg);
3065  }
3066 
3067  *result = v8impl::JsValueFromV8LocalValue(typedArray);
3068  return GET_RETURN_STATUS(env);
3069 }
3070 
3072  napi_value typedarray,
3073  napi_typedarray_type* type,
3074  size_t* length,
3075  void** data,
3076  napi_value* arraybuffer,
3077  size_t* byte_offset) {
3078  CHECK_ENV(env);
3079  CHECK_ARG(env, typedarray);
3080 
3081  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(typedarray);
3082  RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), napi_invalid_arg);
3083 
3084  v8::Local<v8::TypedArray> array = value.As<v8::TypedArray>();
3085 
3086  if (type != nullptr) {
3087  if (value->IsInt8Array()) {
3088  *type = napi_int8_array;
3089  } else if (value->IsUint8Array()) {
3090  *type = napi_uint8_array;
3091  } else if (value->IsUint8ClampedArray()) {
3092  *type = napi_uint8_clamped_array;
3093  } else if (value->IsInt16Array()) {
3094  *type = napi_int16_array;
3095  } else if (value->IsUint16Array()) {
3096  *type = napi_uint16_array;
3097  } else if (value->IsInt32Array()) {
3098  *type = napi_int32_array;
3099  } else if (value->IsUint32Array()) {
3100  *type = napi_uint32_array;
3101  } else if (value->IsFloat32Array()) {
3102  *type = napi_float32_array;
3103  } else if (value->IsFloat64Array()) {
3104  *type = napi_float64_array;
3105  }
3106  }
3107 
3108  if (length != nullptr) {
3109  *length = array->Length();
3110  }
3111 
3112  v8::Local<v8::ArrayBuffer> buffer = array->Buffer();
3113  if (data != nullptr) {
3114  *data = static_cast<uint8_t*>(buffer->GetContents().Data()) +
3115  array->ByteOffset();
3116  }
3117 
3118  if (arraybuffer != nullptr) {
3119  *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
3120  }
3121 
3122  if (byte_offset != nullptr) {
3123  *byte_offset = array->ByteOffset();
3124  }
3125 
3126  return napi_clear_last_error(env);
3127 }
3128 
3130  size_t byte_length,
3131  napi_value arraybuffer,
3132  size_t byte_offset,
3133  napi_value* result) {
3134  NAPI_PREAMBLE(env);
3135  CHECK_ARG(env, arraybuffer);
3136  CHECK_ARG(env, result);
3137 
3138  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3139  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
3140 
3141  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
3142  v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset,
3143  byte_length);
3144 
3145  *result = v8impl::JsValueFromV8LocalValue(DataView);
3146  return GET_RETURN_STATUS(env);
3147 }
3148 
3150  CHECK_ENV(env);
3151  CHECK_ARG(env, value);
3152  CHECK_ARG(env, result);
3153 
3154  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
3155  *result = val->IsDataView();
3156 
3157  return napi_clear_last_error(env);
3158 }
3159 
3161  napi_value dataview,
3162  size_t* byte_length,
3163  void** data,
3164  napi_value* arraybuffer,
3165  size_t* byte_offset) {
3166  CHECK_ENV(env);
3167  CHECK_ARG(env, dataview);
3168 
3169  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(dataview);
3170  RETURN_STATUS_IF_FALSE(env, value->IsDataView(), napi_invalid_arg);
3171 
3172  v8::Local<v8::DataView> array = value.As<v8::DataView>();
3173 
3174  if (byte_length != nullptr) {
3175  *byte_length = array->ByteLength();
3176  }
3177 
3178  v8::Local<v8::ArrayBuffer> buffer = array->Buffer();
3179  if (data != nullptr) {
3180  *data = static_cast<uint8_t*>(buffer->GetContents().Data()) +
3181  array->ByteOffset();
3182  }
3183 
3184  if (arraybuffer != nullptr) {
3185  *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
3186  }
3187 
3188  if (byte_offset != nullptr) {
3189  *byte_offset = array->ByteOffset();
3190  }
3191 
3192  return napi_clear_last_error(env);
3193 }
3194 
3195 napi_status napi_get_version(napi_env env, uint32_t* result) {
3196  CHECK_ENV(env);
3197  CHECK_ARG(env, result);
3198  *result = NAPI_VERSION;
3199  return napi_clear_last_error(env);
3200 }
3201 
3203  const napi_node_version** result) {
3204  CHECK_ENV(env);
3205  CHECK_ARG(env, result);
3206  static const napi_node_version version = {
3210  NODE_RELEASE
3211  };
3212  *result = &version;
3213  return napi_clear_last_error(env);
3214 }
3215 
3217  int64_t change_in_bytes,
3218  int64_t* adjusted_value) {
3219  CHECK_ENV(env);
3220  CHECK_ARG(env, &change_in_bytes);
3221  CHECK_ARG(env, adjusted_value);
3222 
3223  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
3224  change_in_bytes);
3225 
3226  return napi_clear_last_error(env);
3227 }
3228 
3229 namespace uvimpl {
3230 
3231 static napi_status ConvertUVErrorCode(int code) {
3232  switch (code) {
3233  case 0:
3234  return napi_ok;
3235  case UV_EINVAL:
3236  return napi_invalid_arg;
3237  case UV_ECANCELED:
3238  return napi_cancelled;
3239  }
3240 
3241  return napi_generic_failure;
3242 }
3243 
3244 // Wrapper around uv_work_t which calls user-provided callbacks.
3245 class Work {
3246  private:
3247  explicit Work(napi_env env,
3248  napi_async_execute_callback execute = nullptr,
3249  napi_async_complete_callback complete = nullptr,
3250  void* data = nullptr)
3251  : _env(env),
3252  _data(data),
3253  _execute(execute),
3254  _complete(complete) {
3255  memset(&_request, 0, sizeof(_request));
3256  _request.data = this;
3257  }
3258 
3259  ~Work() { }
3260 
3261  public:
3262  static Work* New(napi_env env,
3265  void* data) {
3266  return new Work(env, execute, complete, data);
3267  }
3268 
3269  static void Delete(Work* work) {
3270  delete work;
3271  }
3272 
3273  static void ExecuteCallback(uv_work_t* req) {
3274  Work* work = static_cast<Work*>(req->data);
3275  work->_execute(work->_env, work->_data);
3276  }
3277 
3278  static void CompleteCallback(uv_work_t* req, int status) {
3279  Work* work = static_cast<Work*>(req->data);
3280 
3281  if (work->_complete != nullptr) {
3282  napi_env env = work->_env;
3283 
3284  // Establish a handle scope here so that every callback doesn't have to.
3285  // Also it is needed for the exception-handling below.
3286  v8::HandleScope scope(env->isolate);
3287 
3288  work->_complete(env, ConvertUVErrorCode(status), work->_data);
3289 
3290  // Note: Don't access `work` after this point because it was
3291  // likely deleted by the complete callback.
3292 
3293  // If there was an unhandled exception in the complete callback,
3294  // report it as a fatal exception. (There is no JavaScript on the
3295  // callstack that can possibly handle it.)
3296  if (!env->last_exception.IsEmpty()) {
3297  v8::TryCatch try_catch(env->isolate);
3298  env->isolate->ThrowException(
3300  node::FatalException(env->isolate, try_catch);
3301  }
3302  }
3303  }
3304 
3305  uv_work_t* Request() {
3306  return &_request;
3307  }
3308 
3309  private:
3310  napi_env _env;
3311  void* _data;
3312  uv_work_t _request;
3313  napi_async_execute_callback _execute;
3314  napi_async_complete_callback _complete;
3315 };
3316 
3317 } // end of namespace uvimpl
3318 
3319 #define CALL_UV(env, condition) \
3320  do { \
3321  int result = (condition); \
3322  napi_status status = uvimpl::ConvertUVErrorCode(result); \
3323  if (status != napi_ok) { \
3324  return napi_set_last_error(env, status, result); \
3325  } \
3326  } while (0)
3327 
3331  void* data,
3332  napi_async_work* result) {
3333  CHECK_ENV(env);
3334  CHECK_ARG(env, execute);
3335  CHECK_ARG(env, result);
3336 
3337  uvimpl::Work* work = uvimpl::Work::New(env, execute, complete, data);
3338 
3339  *result = reinterpret_cast<napi_async_work>(work);
3340 
3341  return napi_clear_last_error(env);
3342 }
3343 
3345  CHECK_ENV(env);
3346  CHECK_ARG(env, work);
3347 
3348  uvimpl::Work::Delete(reinterpret_cast<uvimpl::Work*>(work));
3349 
3350  return napi_clear_last_error(env);
3351 }
3352 
3354  CHECK_ENV(env);
3355  CHECK_ARG(env, work);
3356 
3357  // Consider: Encapsulate the uv_loop_t into an opaque pointer parameter.
3358  // Currently the environment event loop is the same as the UV default loop.
3359  // Someday (if node ever supports multiple isolates), it may be better to get
3360  // the loop from node::Environment::GetCurrent(env->isolate)->event_loop();
3361  uv_loop_t* event_loop = uv_default_loop();
3362 
3363  uvimpl::Work* w = reinterpret_cast<uvimpl::Work*>(work);
3364 
3365  CALL_UV(env, uv_queue_work(event_loop,
3366  w->Request(),
3369 
3370  return napi_clear_last_error(env);
3371 }
3372 
3374  CHECK_ENV(env);
3375  CHECK_ARG(env, work);
3376 
3377  uvimpl::Work* w = reinterpret_cast<uvimpl::Work*>(work);
3378 
3379  CALL_UV(env, uv_cancel(reinterpret_cast<uv_req_t*>(w->Request())));
3380 
3381  return napi_clear_last_error(env);
3382 }
3383 
3385  napi_deferred* deferred,
3386  napi_value* promise) {
3387  NAPI_PREAMBLE(env);
3388  CHECK_ARG(env, deferred);
3389  CHECK_ARG(env, promise);
3390 
3391  auto maybe = v8::Promise::Resolver::New(env->isolate->GetCurrentContext());
3393 
3394  auto v8_resolver = maybe.ToLocalChecked();
3395  auto v8_deferred = new v8::Persistent<v8::Value>();
3396  v8_deferred->Reset(env->isolate, v8_resolver);
3397 
3398  *deferred = v8impl::JsDeferredFromV8Persistent(v8_deferred);
3399  *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise());
3400  return GET_RETURN_STATUS(env);
3401 }
3402 
3404  napi_deferred deferred,
3405  napi_value resolution) {
3406  return v8impl::ConcludeDeferred(env, deferred, resolution, true);
3407 }
3408 
3410  napi_deferred deferred,
3411  napi_value resolution) {
3412  return v8impl::ConcludeDeferred(env, deferred, resolution, false);
3413 }
3414 
3416  napi_value promise,
3417  bool* is_promise) {
3418  CHECK_ENV(env);
3419  CHECK_ARG(env, promise);
3420  CHECK_ARG(env, is_promise);
3421 
3422  *is_promise = v8impl::V8LocalValueFromJsValue(promise)->IsPromise();
3423 
3424  return napi_clear_last_error(env);
3425 }
3426 
3429  napi_value* result) {
3430  NAPI_PREAMBLE(env);
3431  CHECK_ARG(env, script);
3432  CHECK_ARG(env, result);
3433 
3434  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
3435 
3436  if (!v8_script->IsString()) {
3437  return napi_set_last_error(env, napi_string_expected);
3438  }
3439 
3440  v8::Local<v8::Context> context = env->isolate->GetCurrentContext();
3441 
3442  auto maybe_script = v8::Script::Compile(context,
3443  v8::Local<v8::String>::Cast(v8_script));
3444  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
3445 
3446  auto script_result =
3447  maybe_script.ToLocalChecked()->Run(context);
3448  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
3449 
3450  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
3451  return GET_RETURN_STATUS(env);
3452 }
static Work * New(napi_env env, napi_async_execute_callback execute, napi_async_complete_callback complete, void *data)
Definition: node_api.cc:3262
this func
Definition: v8ustack.d:371
struct napi_ref__ * napi_ref
napi_status napi_delete_reference(napi_env env, napi_ref ref)
Definition: node_api.cc:2470
napi_status napi_get_array_length(napi_env env, napi_value value, uint32_t *result)
Definition: node_api.cc:1451
napi_status napi_get_value_double(napi_env env, napi_value value, double *result)
Definition: node_api.cc:2022
napi_status napi_create_object(napi_env env, napi_value *result)
Definition: node_api.cc:1500
napi_status napi_set_named_property(napi_env env, napi_value object, const char *utf8name, napi_value value)
Definition: node_api.cc:1205
napi_status napi_has_element(napi_env env, napi_value object, uint32_t index, bool *result)
Definition: node_api.cc:1300
#define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len)
Definition: node_api.cc:122
napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope)
Definition: node_api.cc:2556
napi_status napi_throw(napi_env env, napi_value error)
Definition: node_api.cc:1940
#define NODE_RELEASE
Definition: node_version.h:37
napi_status napi_create_buffer(napi_env env, size_t length, void **data, napi_value *result)
Definition: node_api.cc:2819
napi_property_attributes attributes
napi_status napi_open_escapable_handle_scope(napi_env env, napi_escapable_handle_scope *result)
Definition: node_api.cc:2566
napi_status napi_create_int64(napi_env env, int64_t value, napi_value *result)
Definition: node_api.cc:1620
napi_status napi_define_class(napi_env env, const char *utf8name, napi_callback constructor, void *callback_data, size_t property_count, const napi_property_descriptor *properties, napi_value *result)
Definition: node_api.cc:969
#define CHECK_MAYBE_EMPTY(env, maybe, status)
Definition: node_api.cc:79
bool load_napi_modules
Definition: node.cc:197
bool HasInstance(Local< Value > val)
Definition: node_buffer.cc:201
unsigned char * buf
Definition: cares_wrap.cc:483
const char * nm_modname
Definition: node_api.h:57
napi_status napi_delete_property(napi_env env, napi_value object, napi_value key, bool *result)
Definition: node_api.cc:1162
struct napi_deferred__ * napi_deferred
napi_status napi_throw_error(napi_env env, const char *code, const char *msg)
Definition: node_api.cc:1952
napi_status napi_create_buffer_copy(napi_env env, size_t length, const void *data, void **result_data, napi_value *result)
Definition: node_api.cc:2872
v8::Persistent< v8::ObjectTemplate > accessor_data_template
Definition: node_api.cc:46
NAPI_EXTERN napi_status napi_run_script(napi_env env, napi_value script, napi_value *result)
Definition: node_api.cc:3427
uv_work_t * Request()
Definition: node_api.cc:3305
napi_status napi_get_value_bool(napi_env env, napi_value value, bool *result)
Definition: node_api.cc:2120
napi_status napi_create_int32(napi_env env, int32_t value, napi_value *result)
Definition: node_api.cc:1596
napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value *result)
Definition: node_api.cc:2294
void * nm_priv
Definition: node_api.h:58
napi_status napi_coerce_to_bool(napi_env env, napi_value value, napi_value *result)
Definition: node_api.cc:2260
napi_status napi_get_typedarray_info(napi_env env, napi_value typedarray, napi_typedarray_type *type, size_t *length, void **data, napi_value *arraybuffer, size_t *byte_offset)
Definition: node_api.cc:3071
#define NODE_MINOR_VERSION
Definition: node_version.h:26
#define CHECK_TO_STRING(env, context, result, src)
Definition: node_api.cc:112
napi_status napi_strict_equals(napi_env env, napi_value lhs, napi_value rhs, bool *result)
Definition: node_api.cc:1467
napi_status napi_is_error(napi_env env, napi_value value, bool *result)
Definition: node_api.cc:2009
napi_status napi_is_typedarray(napi_env env, napi_value value, bool *result)
Definition: node_api.cc:3008
#define NODE_MODULE_VERSION
Definition: node_version.h:80
NAPI_EXTERN napi_status napi_is_promise(napi_env env, napi_value promise, bool *is_promise)
Definition: node_api.cc:3415
#define CHECK_TO_OBJECT(env, context, result, src)
Definition: node_api.cc:109
#define CHECK_ENV(env)
Definition: node_api.cc:71
napi_status napi_is_dataview(napi_env env, napi_value value, bool *result)
Definition: node_api.cc:3149
QueryWrap * wrap
Definition: cares_wrap.cc:478
void FatalException(Isolate *isolate, Local< Value > error, Local< Message > message)
Definition: node.cc:2623
napi_status napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref *result)
Definition: node_api.cc:2451
napi_status napi_is_exception_pending(napi_env env, bool *result)
Definition: node_api.cc:2791
napi_status napi_get_null(napi_env env, napi_value *result)
Definition: node_api.cc:1835
struct napi_async_work__ * napi_async_work
const char * nm_filename
Definition: node_api.h:55
napi_status napi_adjust_external_memory(napi_env env, int64_t change_in_bytes, int64_t *adjusted_value)
Definition: node_api.cc:3216
napi_status napi_new_instance(napi_env env, napi_value constructor, size_t argc, const napi_value *argv, napi_value *result)
Definition: node_api.cc:2612
void node_module_register(void *m)
Definition: node.cc:2465
napi_status napi_delete_element(napi_env env, napi_value object, uint32_t index, bool *result)
Definition: node_api.cc:1342
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool *result)
Definition: node_api.cc:2923
napi_status napi_wrap(napi_env env, napi_value js_object, void *native_object, napi_finalize finalize_cb, void *finalize_hint, napi_ref *result)
Definition: node_api.cc:2311
static void Delete(Work *work)
Definition: node_api.cc:3269
napi_status napi_create_string_utf16(napi_env env, const char16_t *str, size_t length, napi_value *result)
Definition: node_api.cc:1565
NO_RETURN void FatalError(const char *location, const char *message)
Definition: node.cc:2616
napi_status napi_unwrap(napi_env env, napi_value obj, void **result)
Definition: node_api.cc:2372
int status
Definition: cares_wrap.cc:479
this script
Definition: v8ustack.d:378
union node::cares_wrap::@8::CaresAsyncData::@0 data
napi_status napi_has_property(napi_env env, napi_value object, napi_value key, bool *result)
Definition: node_api.cc:1115
struct napi_handle_scope__ * napi_handle_scope
struct napi_value__ * napi_value
unsigned int nm_flags
Definition: node_api.h:54
napi_status napi_get_value_int64(napi_env env, napi_value value, int64_t *result)
Definition: node_api.cc:2087
napi_status napi_create_external_buffer(napi_env env, size_t length, void *data, napi_finalize finalize_cb, void *finalize_hint, napi_value *result)
Definition: node_api.cc:2841
napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value *result)
Definition: node_api.cc:2530
void(* napi_finalize)(napi_env env, void *finalize_data, void *finalize_hint)
~napi_env__()
Definition: node_api.cc:34
napi_status napi_escape_handle(napi_env env, napi_escapable_handle_scope scope, napi_value escapee, napi_value *result)
Definition: node_api.cc:2591
napi_status napi_create_external(napi_env env, void *data, napi_finalize finalize_cb, void *finalize_hint, napi_value *result)
Definition: node_api.cc:2407
napi_status napi_is_construct_call(napi_env env, napi_callback_info cbinfo, bool *result)
Definition: node_api.cc:1877
napi_status napi_get_cb_info(napi_env env, napi_callback_info cbinfo, size_t *argc, napi_value *argv, napi_value *this_arg, void **data)
Definition: node_api.cc:1846
void(* napi_async_execute_callback)(napi_env env, void *data)
napi_status napi_create_array_with_length(napi_env env, size_t length, napi_value *result)
Definition: node_api.cc:1520
napi_status napi_create_dataview(napi_env env, size_t byte_length, napi_value arraybuffer, size_t byte_offset, napi_value *result)
Definition: node_api.cc:3129
v8::Persistent< v8::ObjectTemplate > function_data_template
Definition: node_api.cc:45
napi_status napi_delete_async_work(napi_env env, napi_async_work work)
Definition: node_api.cc:3344
napi_status napi_create_typedarray(napi_env env, napi_typedarray_type type, size_t length, napi_value arraybuffer, size_t byte_offset, napi_value *result)
Definition: node_api.cc:3019
const char * error_messages[]
Definition: node_api.cc:871
napi_status napi_cancel_async_work(napi_env env, napi_async_work work)
Definition: node_api.cc:3373
napi_status napi_define_properties(napi_env env, napi_value object, size_t property_count, const napi_property_descriptor *properties)
Definition: node_api.cc:1362
napi_status napi_get_global(napi_env env, napi_value *result)
Definition: node_api.cc:1926
#define ENV_OBJECT_TEMPLATE(env, prefix, destination, field_count)
Definition: node_api.cc:51
napi_status napi_create_array(napi_env env, napi_value *result)
Definition: node_api.cc:1510
#define NODE_PATCH_VERSION
Definition: node_version.h:27
NAPI_EXTERN napi_status napi_has_own_property(napi_env env, napi_value object, napi_value key, bool *result)
Definition: node_api.cc:1184
napi_status napi_get_value_string_utf8(napi_env env, napi_value value, char *buf, size_t bufsize, size_t *result)
Definition: node_api.cc:2179
napi_status napi_remove_wrap(napi_env env, napi_value obj, void **result)
Definition: node_api.cc:2380
napi_status napi_get_dataview_info(napi_env env, napi_value dataview, size_t *byte_length, void **data, napi_value *arraybuffer, size_t *byte_offset)
Definition: node_api.cc:3160
napi_status napi_get_value_string_utf16(napi_env env, napi_value value, char16_t *buf, size_t bufsize, size_t *result)
Definition: node_api.cc:2215
size_t Length(Local< Value > val)
Definition: node_buffer.cc:227
napi_status napi_get_property(napi_env env, napi_value object, napi_value key, napi_value *result)
Definition: node_api.cc:1138
#define CHECK_TO_BOOL(env, context, result, src)
Definition: node_api.cc:118
napi_addon_register_func nm_register_func
Definition: node_api.h:56
napi_status napi_coerce_to_object(napi_env env, napi_value value, napi_value *result)
Definition: node_api.cc:2244
napi_status napi_get_named_property(napi_env env, napi_value object, const char *utf8name, napi_value *result)
Definition: node_api.cc:1253
napi_status napi_create_string_latin1(napi_env env, const char *str, size_t length, napi_value *result)
Definition: node_api.cc:1532
napi_status napi_get_value_string_latin1(napi_env env, napi_value value, char *buf, size_t bufsize, size_t *result)
Definition: node_api.cc:2143
struct napi_callback_info__ * napi_callback_info
napi_status napi_make_callback(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv, napi_value *result)
Definition: node_api.cc:2758
napi_status napi_call_function(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv, napi_value *result)
Definition: node_api.cc:1892
dtrace a
Definition: v8ustack.d:531
napi_status napi_get_arraybuffer_info(napi_env env, napi_value arraybuffer, void **data, size_t *byte_length)
Definition: node_api.cc:2984
static void CompleteCallback(uv_work_t *req, int status)
Definition: node_api.cc:3278
napi_status napi_get_property_names(napi_env env, napi_value object, napi_value *result)
Definition: node_api.cc:1072
v8::Persistent< v8::Value > has_instance
Definition: node_api.cc:43
napi_status napi_get_and_clear_last_exception(napi_env env, napi_value *result)
Definition: node_api.cc:2801
napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value *result)
Definition: node_api.cc:1608
napi_status napi_is_buffer(napi_env env, napi_value value, bool *result)
Definition: node_api.cc:2895
napi_typedarray_type
#define NAPI_EXTERN
Definition: node_api.h:31
#define CALL_UV(env, condition)
Definition: node_api.cc:3319
char * Data(Local< Value > val)
Definition: node_buffer.cc:211
napi_status napi_has_named_property(napi_env env, napi_value object, const char *utf8name, bool *result)
Definition: node_api.cc:1229
dtrace p
Definition: v8ustack.d:615
napi_status napi_create_symbol(napi_env env, napi_value description, napi_value *result)
Definition: node_api.cc:1647
napi_status napi_create_error(napi_env env, napi_value code, napi_value msg, napi_value *result)
Definition: node_api.cc:1721
#define GET_RETURN_STATUS(env)
Definition: node_api.cc:133
napi_status napi_get_undefined(napi_env env, napi_value *result)
Definition: node_api.cc:1825
dtrace s
Definition: v8ustack.d:615
napi_status napi_get_value_uint32(napi_env env, napi_value value, uint32_t *result)
Definition: node_api.cc:2063
dtrace t
Definition: v8ustack.d:582
#define NODE_MAJOR_VERSION
Definition: node_version.h:25
NAPI_EXTERN napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value resolution)
Definition: node_api.cc:3409
struct napi_escapable_handle_scope__ * napi_escapable_handle_scope
napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype *result)
Definition: node_api.cc:1784
napi_status napi_create_function(napi_env env, const char *utf8name, napi_callback cb, void *callback_data, napi_value *result)
Definition: node_api.cc:932
napi_status napi_queue_async_work(napi_env env, napi_async_work work)
Definition: node_api.cc:3353
napi_status napi_coerce_to_number(napi_env env, napi_value value, napi_value *result)
Definition: node_api.cc:2277
napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, napi_value value)
Definition: node_api.cc:1279
napi_status napi_get_boolean(napi_env env, bool value, napi_value *result)
Definition: node_api.cc:1632
napi_status napi_throw_range_error(napi_env env, const char *code, const char *msg)
Definition: node_api.cc:1990
#define CHECK_TO_FUNCTION(env, result, src)
Definition: node_api.cc:101
uv_fs_t req
Definition: node_file.cc:374
napi_status napi_create_range_error(napi_env env, napi_value code, napi_value msg, napi_value *result)
Definition: node_api.cc:1763
napi_status
static void ExecuteCallback(uv_work_t *req)
Definition: node_api.cc:3273
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
Definition: node_buffer.cc:241
napi_status napi_set_property(napi_env env, napi_value object, napi_value key, napi_value value)
Definition: node_api.cc:1092
NAPI_NO_RETURN void napi_fatal_error(const char *location, const char *message)
Definition: node_api.cc:927
napi_status napi_close_escapable_handle_scope(napi_env env, napi_escapable_handle_scope scope)
Definition: node_api.cc:2579
void(* napi_async_complete_callback)(napi_env env, napi_status status, void *data)
#define CHECK_MAYBE_NOTHING(env, maybe, status)
Definition: node_api.cc:82
#define NAPI_PREAMBLE(env)
Definition: node_api.cc:86
napi_status napi_get_prototype(napi_env env, napi_value object, napi_value *result)
Definition: node_api.cc:1483
napi_status napi_get_node_version(napi_env env, const napi_node_version **result)
Definition: node_api.cc:3202
MaybeLocal< Value > MakeCallback(Isolate *isolate, Local< Object > recv, Local< Function > callback, int argc, Local< Value > *argv, async_id asyncId, async_id triggerAsyncId)
Definition: async-wrap.cc:802
v8::Persistent< v8::Value > last_exception
Definition: node_api.cc:42
napi_status napi_get_buffer_info(napi_env env, napi_value value, void **data, size_t *length)
Definition: node_api.cc:2904
napi_status napi_create_double(napi_env env, double value, napi_value *result)
Definition: node_api.cc:1584
napi_env__(v8::Isolate *_isolate)
Definition: node_api.cc:32
napi_status napi_open_handle_scope(napi_env env, napi_handle_scope *result)
Definition: node_api.cc:2545
napi_status napi_is_array(napi_env env, napi_value value, bool *result)
Definition: node_api.cc:1440
napi_value(* napi_callback)(napi_env env, napi_callback_info info)
napi_status napi_create_external_arraybuffer(napi_env env, void *external_data, size_t byte_length, napi_finalize finalize_cb, void *finalize_hint, napi_value *result)
Definition: node_api.cc:2955
napi_status napi_create_type_error(napi_env env, napi_value code, napi_value msg, napi_value *result)
Definition: node_api.cc:1742
#define RETURN_STATUS_IF_FALSE(env, condition, status)
Definition: node_api.cc:64
#define CHECK_NEW_FROM_UTF8(env, result, str)
Definition: node_api.cc:130
void napi_module_register(napi_module *mod)
Definition: node_api.cc:844
#define CHECK_ARG(env, arg)
Definition: node_api.cc:76
napi_status napi_create_arraybuffer(napi_env env, size_t byte_length, void **data, napi_value *result)
Definition: node_api.cc:2934
napi_status napi_create_async_work(napi_env env, napi_async_execute_callback execute, napi_async_complete_callback complete, void *data, napi_async_work *result)
Definition: node_api.cc:3328
napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t *result)
Definition: node_api.cc:2506
napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, napi_value *result)
Definition: node_api.cc:1321
napi_status napi_get_value_int32(napi_env env, napi_value value, int32_t *result)
Definition: node_api.cc:2039
uint16_t char16_t
Definition: node_api_types.h:8
NAPI_EXTERN napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution)
Definition: node_api.cc:3403
napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t *result)
Definition: node_api.cc:2486
NAPI_EXTERN napi_status napi_create_promise(napi_env env, napi_deferred *deferred, napi_value *promise)
Definition: node_api.cc:3384
v8::Persistent< v8::ObjectTemplate > wrap_template
Definition: node_api.cc:44
napi_valuetype
napi_status napi_get_value_external(napi_env env, napi_value value, void **result)
Definition: node_api.cc:2434
v8::Isolate * isolate
Definition: node_api.cc:41
napi_status napi_get_last_error_info(napi_env env, const napi_extended_error_info **result)
Definition: node_api.cc:904
napi_status napi_instanceof(napi_env env, napi_value object, napi_value constructor, bool *result)
Definition: node_api.cc:2639
napi_extended_error_info last_error
Definition: node_api.cc:48
#define NAPI_NO_RETURN
Definition: node_api.h:43
MaybeLocal< Object > Copy(Isolate *isolate, const char *data, size_t length)
Definition: node_buffer.cc:320
napi_status napi_get_version(napi_env env, uint32_t *result)
Definition: node_api.cc:3195
#define CHECK_TO_NUMBER(env, context, result, src)
Definition: node_api.cc:115
napi_status napi_create_string_utf8(napi_env env, const char *str, size_t length, napi_value *result)
Definition: node_api.cc:1551
bool has_instance_available
Definition: node_api.cc:47
#define NAPI_VERSION
Definition: node_api.cc:22
napi_status napi_throw_type_error(napi_env env, const char *code, const char *msg)
Definition: node_api.cc:1971