GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/js_native_api_v8.cc Lines: 1231 1273 96.7 %
Date: 2019-01-07 12:15:22 Branches: 757 1294 58.5 %

Line Branch Exec Source
1
#include <limits.h>  // INT_MAX
2
#include <cmath>
3
#include <algorithm>
4
#define NAPI_EXPERIMENTAL
5
#include "js_native_api_v8.h"
6
#include "js_native_api.h"
7
8
#define CHECK_MAYBE_NOTHING(env, maybe, status) \
9
  RETURN_STATUS_IF_FALSE((env), !((maybe).IsNothing()), (status))
10
11
#define CHECK_TO_NUMBER(env, context, result, src) \
12
  CHECK_TO_TYPE((env), Number, (context), (result), (src), napi_number_expected)
13
14
// n-api defines NAPI_AUTO_LENGHTH as the indicator that a string
15
// is null terminated. For V8 the equivalent is -1. The assert
16
// validates that our cast of NAPI_AUTO_LENGTH results in -1 as
17
// needed by V8.
18
#define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len)                   \
19
  do {                                                                   \
20
    static_assert(static_cast<int>(NAPI_AUTO_LENGTH) == -1,              \
21
                  "Casting NAPI_AUTO_LENGTH to int must result in -1");  \
22
    RETURN_STATUS_IF_FALSE((env),                                        \
23
        (len == NAPI_AUTO_LENGTH) || len <= INT_MAX,                     \
24
        napi_invalid_arg);                                               \
25
    auto str_maybe = v8::String::NewFromUtf8(                            \
26
        (env)->isolate, (str), v8::NewStringType::kInternalized,         \
27
        static_cast<int>(len));                                          \
28
    CHECK_MAYBE_EMPTY((env), str_maybe, napi_generic_failure);           \
29
    (result) = str_maybe.ToLocalChecked();                               \
30
  } while (0)
31
32
#define CHECK_NEW_FROM_UTF8(env, result, str) \
33
  CHECK_NEW_FROM_UTF8_LEN((env), (result), (str), NAPI_AUTO_LENGTH)
34
35
#define CREATE_TYPED_ARRAY(                                                    \
36
    env, type, size_of_element, buffer, byte_offset, length, out)              \
37
  do {                                                                         \
38
    if ((size_of_element) > 1) {                                               \
39
      THROW_RANGE_ERROR_IF_FALSE(                                              \
40
          (env), (byte_offset) % (size_of_element) == 0,                       \
41
          "ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT",                             \
42
          "start offset of "#type" should be a multiple of "#size_of_element); \
43
    }                                                                          \
44
    THROW_RANGE_ERROR_IF_FALSE((env), (length) * (size_of_element) +           \
45
        (byte_offset) <= buffer->ByteLength(),                                 \
46
        "ERR_NAPI_INVALID_TYPEDARRAY_LENGTH",                                  \
47
        "Invalid typed array length");                                         \
48
    (out) = v8::type::New((buffer), (byte_offset), (length));                  \
49
  } while (0)
50
51
namespace v8impl {
52
53
namespace {
54
55
inline static napi_status
56
302
V8NameFromPropertyDescriptor(napi_env env,
57
                             const napi_property_descriptor* p,
58
                             v8::Local<v8::Name>* result) {
59
302
  if (p->utf8name != nullptr) {
60
900
    CHECK_NEW_FROM_UTF8(env, *result, p->utf8name);
61
  } else {
62
    v8::Local<v8::Value> property_value =
63
2
      v8impl::V8LocalValueFromJsValue(p->name);
64
65
2
    RETURN_STATUS_IF_FALSE(env, property_value->IsName(), napi_name_expected);
66
2
    *result = property_value.As<v8::Name>();
67
  }
68
69
302
  return napi_ok;
70
}
71
72
// convert from n-api property attributes to v8::PropertyAttribute
73
302
inline static v8::PropertyAttribute V8PropertyAttributesFromDescriptor(
74
    const napi_property_descriptor* descriptor) {
75
302
  unsigned int attribute_flags = v8::PropertyAttribute::None;
76
77

302
  if (descriptor->getter != nullptr || descriptor->setter != nullptr) {
78
    // The napi_writable attribute is ignored for accessor descriptors, but
79
    // V8 requires the ReadOnly attribute to match nonexistence of a setter.
80
18
    attribute_flags |= (descriptor->setter == nullptr ?
81
18
      v8::PropertyAttribute::ReadOnly : v8::PropertyAttribute::None);
82
284
  } else if ((descriptor->attributes & napi_writable) == 0) {
83
281
    attribute_flags |= v8::PropertyAttribute::ReadOnly;
84
  }
85
86
302
  if ((descriptor->attributes & napi_enumerable) == 0) {
87
283
    attribute_flags |= v8::PropertyAttribute::DontEnum;
88
  }
89
302
  if ((descriptor->attributes & napi_configurable) == 0) {
90
302
    attribute_flags |= v8::PropertyAttribute::DontDelete;
91
  }
92
93
302
  return static_cast<v8::PropertyAttribute>(attribute_flags);
94
}
95
96
inline static napi_deferred
97
5
JsDeferredFromNodePersistent(v8impl::Persistent<v8::Value>* local) {
98
5
  return reinterpret_cast<napi_deferred>(local);
99
}
100
101
inline static v8impl::Persistent<v8::Value>*
102
5
NodePersistentFromJsDeferred(napi_deferred local) {
103
5
  return reinterpret_cast<v8impl::Persistent<v8::Value>*>(local);
104
}
105
106
4
class HandleScopeWrapper {
107
 public:
108
4
  explicit HandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {}
109
110
 private:
111
  v8::HandleScope scope;
112
};
113
114
// In node v0.10 version of v8, there is no EscapableHandleScope and the
115
// node v0.10 port use HandleScope::Close(Local<T> v) to mimic the behavior
116
// of a EscapableHandleScope::Escape(Local<T> v), but it is not the same
117
// semantics. This is an example of where the api abstraction fail to work
118
// across different versions.
119
4
class EscapableHandleScopeWrapper {
120
 public:
121
2
  explicit EscapableHandleScopeWrapper(v8::Isolate* isolate)
122
2
      : scope(isolate), escape_called_(false) {}
123
3
  bool escape_called() const {
124
3
    return escape_called_;
125
  }
126
  template <typename T>
127
2
  v8::Local<T> Escape(v8::Local<T> handle) {
128
2
    escape_called_ = true;
129
4
    return scope.Escape(handle);
130
  }
131
132
 private:
133
  v8::EscapableHandleScope scope;
134
  bool escape_called_;
135
};
136
137
inline static napi_handle_scope
138
4
JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s) {
139
4
  return reinterpret_cast<napi_handle_scope>(s);
140
}
141
142
inline static HandleScopeWrapper*
143
4
V8HandleScopeFromJsHandleScope(napi_handle_scope s) {
144
4
  return reinterpret_cast<HandleScopeWrapper*>(s);
145
}
146
147
inline static napi_escapable_handle_scope
148
2
JsEscapableHandleScopeFromV8EscapableHandleScope(
149
    EscapableHandleScopeWrapper* s) {
150
2
  return reinterpret_cast<napi_escapable_handle_scope>(s);
151
}
152
153
inline static EscapableHandleScopeWrapper*
154
5
V8EscapableHandleScopeFromJsEscapableHandleScope(
155
    napi_escapable_handle_scope s) {
156
5
  return reinterpret_cast<EscapableHandleScopeWrapper*>(s);
157
}
158
159
5
inline static napi_status ConcludeDeferred(napi_env env,
160
                                           napi_deferred deferred,
161
                                           napi_value result,
162
                                           bool is_resolved) {
163

10
  NAPI_PREAMBLE(env);
164
5
  CHECK_ARG(env, result);
165
166
5
  v8::Local<v8::Context> context = env->isolate->GetCurrentContext();
167
  v8impl::Persistent<v8::Value>* deferred_ref =
168
5
      NodePersistentFromJsDeferred(deferred);
169
  v8::Local<v8::Value> v8_deferred =
170
10
      v8::Local<v8::Value>::New(env->isolate, *deferred_ref);
171
172
5
  auto v8_resolver = v8::Local<v8::Promise::Resolver>::Cast(v8_deferred);
173
174
  v8::Maybe<bool> success = is_resolved ?
175
8
      v8_resolver->Resolve(context, v8impl::V8LocalValueFromJsValue(result)) :
176
10
      v8_resolver->Reject(context, v8impl::V8LocalValueFromJsValue(result));
177
178
10
  delete deferred_ref;
179
180
10
  RETURN_STATUS_IF_FALSE(env, success.FromMaybe(false), napi_generic_failure);
181
182
5
  return GET_RETURN_STATUS(env);
183
}
184
185
// Wrapper around v8impl::Persistent that implements reference counting.
186
4046
class Reference : private Finalizer {
187
 private:
188
2556
  Reference(napi_env env,
189
            v8::Local<v8::Value> value,
190
            uint32_t initial_refcount,
191
            bool delete_self,
192
            napi_finalize finalize_callback,
193
            void* finalize_data,
194
            void* finalize_hint)
195
       : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
196
        _persistent(env->isolate, value),
197
        _refcount(initial_refcount),
198
5112
        _delete_self(delete_self) {
199
2556
    if (initial_refcount == 0) {
200
      _persistent.SetWeak(
201
2029
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
202
    }
203
2556
  }
204
205
 public:
206
25
  void* Data() {
207
25
    return _finalize_data;
208
  }
209
210
2556
  static Reference* New(napi_env env,
211
                        v8::Local<v8::Value> value,
212
                        uint32_t initial_refcount,
213
                        bool delete_self,
214
                        napi_finalize finalize_callback = nullptr,
215
                        void* finalize_data = nullptr,
216
                        void* finalize_hint = nullptr) {
217
    return new Reference(env,
218
      value,
219
      initial_refcount,
220
      delete_self,
221
      finalize_callback,
222
      finalize_data,
223
2556
      finalize_hint);
224
  }
225
226
  // Delete is called in 2 ways. Either from the finalizer or
227
  // from one of Unwrap or napi_delete_reference.
228
  //
229
  // When it is called from Unwrap or napi_delete_reference we only
230
  // want to do the delete if the finalizer has already run,
231
  // otherwise we may crash when the finalizer does run.
232
  // If the finalizer has not already run delay the delete until
233
  // the finalizer runs by not doing the delete
234
  // and setting _delete_self to true so that the finalizer will
235
  // delete it when it runs.
236
  //
237
  // The second way this is called is from
238
  // the finalizer and _delete_self is set. In this case we
239
  // know we need to do the deletion so just do it.
240
2549
  static void Delete(Reference* reference) {
241

2549
    if ((reference->_delete_self) || (reference->_finalize_ran)) {
242
2023
      delete reference;
243
    } else {
244
      // reduce the reference count to 0 and defer until
245
      // finalizer runs
246
526
      reference->_delete_self = true;
247
526
      while (reference->Unref() != 0) {}
248
    }
249
2549
  }
250
251
1
  uint32_t Ref() {
252
1
    if (++_refcount == 1) {
253
      _persistent.ClearWeak();
254
    }
255
256
1
    return _refcount;
257
  }
258
259
528
  uint32_t Unref() {
260
528
    if (_refcount == 0) {
261
5
        return 0;
262
    }
263
523
    if (--_refcount == 0) {
264
      _persistent.SetWeak(
265
522
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
266
    }
267
268
523
    return _refcount;
269
  }
270
271
2
  uint32_t RefCount() {
272
2
    return _refcount;
273
  }
274
275
532
  v8::Local<v8::Value> Get() {
276
1064
    if (_persistent.IsEmpty()) {
277
1
      return v8::Local<v8::Value>();
278
    } else {
279
1062
      return v8::Local<v8::Value>::New(_env->isolate, _persistent);
280
    }
281
  }
282
283
 private:
284
2021
  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
285
2021
    Reference* reference = data.GetParameter();
286
2021
    reference->_persistent.Reset();
287
288
2021
    napi_env env = reference->_env;
289
290
2021
    if (reference->_finalize_callback != nullptr) {
291

2031
      NAPI_CALL_INTO_MODULE_THROW(env,
292
        reference->_finalize_callback(
293
            reference->_env,
294
            reference->_finalize_data,
295
            reference->_finalize_hint));
296
    }
297
298
    // this is safe because if a request to delete the reference
299
    // is made in the finalize_callback it will defer deletion
300
    // to this block and set _delete_self to true
301
2021
    if (reference->_delete_self) {
302
1020
      Delete(reference);
303
    } else {
304
1001
      reference->_finalize_ran = true;
305
    }
306
2021
  }
307
308
  v8impl::Persistent<v8::Value> _persistent;
309
  uint32_t _refcount;
310
  bool _delete_self;
311
};
312
313
enum UnwrapAction {
314
  KeepWrap,
315
  RemoveWrap
316
};
317
318
27
inline static napi_status Unwrap(napi_env env,
319
                                 napi_value js_object,
320
                                 void** result,
321
                                 UnwrapAction action) {
322

54
  NAPI_PREAMBLE(env);
323
27
  CHECK_ARG(env, js_object);
324
27
  if (action == KeepWrap) {
325
24
    CHECK_ARG(env, result);
326
  }
327
328
27
  v8::Isolate* isolate = env->isolate;
329
27
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
330
331
27
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
332
27
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
333
27
  v8::Local<v8::Object> obj = value.As<v8::Object>();
334
335
54
  auto val = obj->GetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
336
54
      .ToLocalChecked();
337
27
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
338
  Reference* reference =
339
50
      static_cast<v8impl::Reference*>(val.As<v8::External>()->Value());
340
341
25
  if (result) {
342
25
    *result = reference->Data();
343
  }
344
345
25
  if (action == RemoveWrap) {
346
6
    CHECK(obj->DeletePrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
347
        .FromJust());
348
2
    Reference::Delete(reference);
349
  }
350
351
25
  return GET_RETURN_STATUS(env);
352
}
353
354
//=== Function napi_callback wrapper =================================
355
356
// Use this data structure to associate callback data with each N-API function
357
// exposed to JavaScript. The structure is stored in a v8::External which gets
358
// passed into our callback wrapper. This reduces the performance impact of
359
// calling through N-API.
360
// Ref: benchmark/misc/function_call
361
// Discussion (incl. perf. data): https://github.com/nodejs/node/pull/21072
362
606
struct CallbackBundle {
363
  // Bind the lifecycle of `this` C++ object to a JavaScript object.
364
  // We never delete a CallbackBundle C++ object directly.
365
302
  void BindLifecycleTo(v8::Isolate* isolate, v8::Local<v8::Value> target) {
366
302
    handle.Reset(isolate, target);
367
302
    handle.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
368
302
  }
369
370
  napi_env       env;      // Necessary to invoke C++ NAPI callback
371
  void*          cb_data;  // The user provided callback data
372
  napi_callback  function_or_getter;
373
  napi_callback  setter;
374
  v8impl::Persistent<v8::Value> handle;  // Die with this JavaScript object
375
376
 private:
377
1
  static void WeakCallback(v8::WeakCallbackInfo<CallbackBundle> const& info) {
378
    // Use the "WeakCallback mechanism" to delete the C++ `bundle` object.
379
    // This will be called when the v8::External containing `this` pointer
380
    // is being GC-ed.
381
1
    CallbackBundle* bundle = info.GetParameter();
382
1
    if (bundle != nullptr) {
383
1
      delete bundle;
384
    }
385
1
  }
386
};
387
388
// Base class extended by classes that wrap V8 function and property callback
389
// info.
390
class CallbackWrapper {
391
 public:
392
4494
  CallbackWrapper(napi_value this_arg, size_t args_length, void* data)
393
4494
      : _this(this_arg), _args_length(args_length), _data(data) {}
394
395
  virtual napi_value GetNewTarget() = 0;
396
  virtual void Args(napi_value* buffer, size_t bufferlength) = 0;
397
  virtual void SetReturnValue(napi_value value) = 0;
398
399
36
  napi_value This() { return _this; }
400
401
4391
  size_t ArgsLength() { return _args_length; }
402
403
6
  void* Data() { return _data; }
404
405
 protected:
406
  const napi_value _this;
407
  const size_t _args_length;
408
  void* _data;
409
};
410
411
template <typename Info, napi_callback CallbackBundle::*FunctionField>
412
class CallbackWrapperBase : public CallbackWrapper {
413
 public:
414
4494
  CallbackWrapperBase(const Info& cbinfo, const size_t args_length)
415
      : CallbackWrapper(JsValueFromV8LocalValue(cbinfo.This()),
416
                        args_length,
417
                        nullptr),
418
4494
        _cbinfo(cbinfo) {
419
8988
    _bundle = reinterpret_cast<CallbackBundle*>(
420
        v8::Local<v8::External>::Cast(cbinfo.Data())->Value());
421
4494
    _data = _bundle->cb_data;
422
4494
  }
423
424
  napi_value GetNewTarget() override { return nullptr; }
425
426
 protected:
427
4494
  void InvokeCallback() {
428
    napi_callback_info cbinfo_wrapper = reinterpret_cast<napi_callback_info>(
429
4494
        static_cast<CallbackWrapper*>(this));
430
431
    // All other pointers we need are stored in `_bundle`
432
4494
    napi_env env = _bundle->env;
433
4494
    napi_callback cb = _bundle->*FunctionField;
434
435
    napi_value result;
436




10215
    NAPI_CALL_INTO_MODULE_THROW(env, result = cb(env, cbinfo_wrapper));
437
438

4494
    if (result != nullptr) {
439
2689
      this->SetReturnValue(result);
440
    }
441
4494
  }
442
443
  const Info& _cbinfo;
444
  CallbackBundle* _bundle;
445
};
446
447
class FunctionCallbackWrapper
448
    : public CallbackWrapperBase<v8::FunctionCallbackInfo<v8::Value>,
449
                                 &CallbackBundle::function_or_getter> {
450
 public:
451
4453
  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
452
4453
    FunctionCallbackWrapper cbwrapper(info);
453
4453
    cbwrapper.InvokeCallback();
454
4453
  }
455
456
4453
  explicit FunctionCallbackWrapper(
457
      const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
458
4453
      : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
459
460
8
  napi_value GetNewTarget() override {
461
16
    if (_cbinfo.IsConstructCall()) {
462
14
      return v8impl::JsValueFromV8LocalValue(_cbinfo.NewTarget());
463
    } else {
464
1
      return nullptr;
465
    }
466
  }
467
468
  /*virtual*/
469
4374
  void Args(napi_value* buffer, size_t buffer_length) override {
470
4374
    size_t i = 0;
471
4374
    size_t min = std::min(buffer_length, _args_length);
472
473
11299
    for (; i < min; i += 1) {
474
13850
      buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
475
    }
476
477
4374
    if (i < buffer_length) {
478
      napi_value undefined =
479
75
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
480
127
      for (; i < buffer_length; i += 1) {
481
102
        buffer[i] = undefined;
482
      }
483
    }
484
4374
  }
485
486
  /*virtual*/
487
2654
  void SetReturnValue(napi_value value) override {
488
2654
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
489
7962
    _cbinfo.GetReturnValue().Set(val);
490
2654
  }
491
};
492
493
class GetterCallbackWrapper
494
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<v8::Value>,
495
                                 &CallbackBundle::function_or_getter> {
496
 public:
497
36
  static void Invoke(v8::Local<v8::Name> property,
498
                     const v8::PropertyCallbackInfo<v8::Value>& info) {
499
36
    GetterCallbackWrapper cbwrapper(info);
500
36
    cbwrapper.InvokeCallback();
501
36
  }
502
503
36
  explicit GetterCallbackWrapper(
504
      const v8::PropertyCallbackInfo<v8::Value>& cbinfo)
505
36
      : CallbackWrapperBase(cbinfo, 0) {}
506
507
  /*virtual*/
508
  void Args(napi_value* buffer, size_t buffer_length) override {
509
    if (buffer_length > 0) {
510
      napi_value undefined =
511
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
512
      for (size_t i = 0; i < buffer_length; i += 1) {
513
        buffer[i] = undefined;
514
      }
515
    }
516
  }
517
518
  /*virtual*/
519
35
  void SetReturnValue(napi_value value) override {
520
35
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
521
105
    _cbinfo.GetReturnValue().Set(val);
522
35
  }
523
};
524
525
class SetterCallbackWrapper
526
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<void>,
527
                                 &CallbackBundle::setter> {
528
 public:
529
5
  static void Invoke(v8::Local<v8::Name> property,
530
                     v8::Local<v8::Value> value,
531
                     const v8::PropertyCallbackInfo<void>& info) {
532
5
    SetterCallbackWrapper cbwrapper(info, value);
533
5
    cbwrapper.InvokeCallback();
534
5
  }
535
536
5
  SetterCallbackWrapper(const v8::PropertyCallbackInfo<void>& cbinfo,
537
                        const v8::Local<v8::Value>& value)
538
5
      : CallbackWrapperBase(cbinfo, 1), _value(value) {}
539
540
  /*virtual*/
541
5
  void Args(napi_value* buffer, size_t buffer_length) override {
542
5
    if (buffer_length > 0) {
543
5
      buffer[0] = v8impl::JsValueFromV8LocalValue(_value);
544
545
5
      if (buffer_length > 1) {
546
        napi_value undefined = v8impl::JsValueFromV8LocalValue(
547
            v8::Undefined(_cbinfo.GetIsolate()));
548
        for (size_t i = 1; i < buffer_length; i += 1) {
549
          buffer[i] = undefined;
550
        }
551
      }
552
    }
553
5
  }
554
555
  /*virtual*/
556
  void SetReturnValue(napi_value value) override {
557
    // Ignore any value returned from a setter callback.
558
  }
559
560
 private:
561
  const v8::Local<v8::Value>& _value;
562
};
563
564
// Creates an object to be made available to the static function callback
565
// wrapper, used to retrieve the native callback function and data pointer.
566
static
567
284
v8::Local<v8::Value> CreateFunctionCallbackData(napi_env env,
568
                                                napi_callback cb,
569
                                                void* data) {
570
284
  CallbackBundle* bundle = new CallbackBundle();
571
284
  bundle->function_or_getter = cb;
572
284
  bundle->cb_data = data;
573
284
  bundle->env = env;
574
284
  v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
575
284
  bundle->BindLifecycleTo(env->isolate, cbdata);
576
577
284
  return cbdata;
578
}
579
580
// Creates an object to be made available to the static getter/setter
581
// callback wrapper, used to retrieve the native getter/setter callback
582
// function and data pointer.
583
18
inline v8::Local<v8::Value> CreateAccessorCallbackData(napi_env env,
584
                                                       napi_callback getter,
585
                                                       napi_callback setter,
586
                                                       void* data) {
587
18
  CallbackBundle* bundle = new CallbackBundle();
588
18
  bundle->function_or_getter = getter;
589
18
  bundle->setter = setter;
590
18
  bundle->cb_data = data;
591
18
  bundle->env = env;
592
18
  v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
593
18
  bundle->BindLifecycleTo(env->isolate, cbdata);
594
595
18
  return cbdata;
596
}
597
598
enum WrapType {
599
  retrievable,
600
  anonymous
601
};
602
603
template <WrapType wrap_type>
604
1022
inline napi_status Wrap(napi_env env,
605
                        napi_value js_object,
606
                        void* native_object,
607
                        napi_finalize finalize_cb,
608
                        void* finalize_hint,
609
                        napi_ref* result) {
610


2044
  NAPI_PREAMBLE(env);
611

1022
  CHECK_ARG(env, js_object);
612
613
1022
  v8::Local<v8::Context> context = env->context();
614
615
1022
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
616

1022
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
617
1022
  v8::Local<v8::Object> obj = value.As<v8::Object>();
618
619
  if (wrap_type == retrievable) {
620
    // If we've already wrapped this object, we error out.
621
3057
    RETURN_STATUS_IF_FALSE(env,
622
        !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
623
            .FromJust(),
624
        napi_invalid_arg);
625
  } else if (wrap_type == anonymous) {
626
    // If no finalize callback is provided, we error out.
627
3
    CHECK_ARG(env, finalize_cb);
628
  }
629
630
1021
  v8impl::Reference* reference = nullptr;
631

1021
  if (result != nullptr) {
632
    // The returned reference should be deleted via napi_delete_reference()
633
    // ONLY in response to the finalize callback invocation. (If it is deleted
634
    // before then, then the finalize callback will never be invoked.)
635
    // Therefore a finalize callback is required when returning a reference.
636

8
    CHECK_ARG(env, finalize_cb);
637
8
    reference = v8impl::Reference::New(
638
24
        env, obj, 0, false, finalize_cb, native_object, finalize_hint);
639
8
    *result = reinterpret_cast<napi_ref>(reference);
640
  } else {
641
    // Create a self-deleting reference.
642
1013
    reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb,
643

3039
        native_object, finalize_cb == nullptr ? nullptr : finalize_hint);
644
  }
645
646
  if (wrap_type == retrievable) {
647
4072
    CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper),
648
          v8::External::New(env->isolate, reference)).FromJust());
649
  }
650
651

1021
  return GET_RETURN_STATUS(env);
652
}
653
654
}  // end of anonymous namespace
655
656
}  // end of namespace v8impl
657
658
// Warning: Keep in-sync with napi_status enum
659
static
660
const char* error_messages[] = {nullptr,
661
                                "Invalid argument",
662
                                "An object was expected",
663
                                "A string was expected",
664
                                "A string or symbol was expected",
665
                                "A function was expected",
666
                                "A number was expected",
667
                                "A boolean was expected",
668
                                "An array was expected",
669
                                "Unknown failure",
670
                                "An exception is pending",
671
                                "The async work item was cancelled",
672
                                "napi_escape_handle already called on scope",
673
                                "Invalid handle scope usage",
674
                                "Invalid callback scope usage",
675
                                "Thread-safe function queue is full",
676
                                "Thread-safe function handle is closing",
677
                                "A bigint was expected",
678
};
679
680
1209
napi_status napi_get_last_error_info(napi_env env,
681
                                     const napi_extended_error_info** result) {
682
1209
  CHECK_ENV(env);
683
1209
  CHECK_ARG(env, result);
684
685
  // you must update this assert to reference the last message
686
  // in the napi_status enum each time a new error message is added.
687
  // We don't have a napi_status_last as this would result in an ABI
688
  // change each time a message was added.
689
  static_assert(
690
      NAPI_ARRAYSIZE(error_messages) == napi_bigint_expected + 1,
691
      "Count of error messages must match count of error values");
692
1209
  CHECK_LE(env->last_error.error_code, napi_callback_scope_mismatch);
693
694
  // Wait until someone requests the last error information to fetch the error
695
  // message string
696
  env->last_error.error_message =
697
1209
      error_messages[env->last_error.error_code];
698
699
1209
  *result = &(env->last_error);
700
1209
  return napi_ok;
701
}
702
703
12
napi_status napi_create_function(napi_env env,
704
                                 const char* utf8name,
705
                                 size_t length,
706
                                 napi_callback cb,
707
                                 void* callback_data,
708
                                 napi_value* result) {
709

24
  NAPI_PREAMBLE(env);
710
12
  CHECK_ARG(env, result);
711
12
  CHECK_ARG(env, cb);
712
713
12
  v8::Isolate* isolate = env->isolate;
714
  v8::Local<v8::Function> return_value;
715
12
  v8::EscapableHandleScope scope(isolate);
716
  v8::Local<v8::Value> cbdata =
717
12
      v8impl::CreateFunctionCallbackData(env, cb, callback_data);
718
719
12
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
720
721
12
  v8::Local<v8::Context> context = env->context();
722
  v8::MaybeLocal<v8::Function> maybe_function =
723
      v8::Function::New(context,
724
                        v8impl::FunctionCallbackWrapper::Invoke,
725
12
                        cbdata);
726
12
  CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
727
728
12
  return_value = scope.Escape(maybe_function.ToLocalChecked());
729
730
12
  if (utf8name != nullptr) {
731
    v8::Local<v8::String> name_string;
732

24
    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
733
8
    return_value->SetName(name_string);
734
  }
735
736
24
  *result = v8impl::JsValueFromV8LocalValue(return_value);
737
738
24
  return GET_RETURN_STATUS(env);
739
}
740
741
7
napi_status napi_define_class(napi_env env,
742
                              const char* utf8name,
743
                              size_t length,
744
                              napi_callback constructor,
745
                              void* callback_data,
746
                              size_t property_count,
747
                              const napi_property_descriptor* properties,
748
                              napi_value* result) {
749

14
  NAPI_PREAMBLE(env);
750
7
  CHECK_ARG(env, result);
751
7
  CHECK_ARG(env, constructor);
752
753
7
  v8::Isolate* isolate = env->isolate;
754
755
7
  v8::EscapableHandleScope scope(isolate);
756
  v8::Local<v8::Value> cbdata =
757
7
      v8impl::CreateFunctionCallbackData(env, constructor, callback_data);
758
759
7
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
760
761
  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(
762
7
      isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
763
764
  v8::Local<v8::String> name_string;
765

21
  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
766
7
  tpl->SetClassName(name_string);
767
768
7
  size_t static_property_count = 0;
769
31
  for (size_t i = 0; i < property_count; i++) {
770
24
    const napi_property_descriptor* p = properties + i;
771
772
24
    if ((p->attributes & napi_static) != 0) {
773
      // Static properties are handled separately below.
774
4
      static_property_count++;
775
4
      continue;
776
    }
777
778
    v8::Local<v8::Name> property_name;
779
    napi_status status =
780
20
        v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
781
782
20
    if (status != napi_ok) {
783
      return napi_set_last_error(env, status);
784
    }
785
786
    v8::PropertyAttribute attributes =
787
20
        v8impl::V8PropertyAttributesFromDescriptor(p);
788
789
    // This code is similar to that in napi_define_properties(); the
790
    // difference is it applies to a template instead of an object.
791

20
    if (p->getter != nullptr || p->setter != nullptr) {
792
      v8::Local<v8::Value> cbdata = v8impl::CreateAccessorCallbackData(
793
9
        env, p->getter, p->setter, p->data);
794
795
9
      tpl->PrototypeTemplate()->SetAccessor(
796
        property_name,
797
        p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
798
        p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
799
        cbdata,
800
        v8::AccessControl::DEFAULT,
801

27
        attributes);
802
11
    } else if (p->method != nullptr) {
803
      v8::Local<v8::Value> cbdata =
804
5
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
805
806
5
      RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
807
808
      v8::Local<v8::FunctionTemplate> t =
809
        v8::FunctionTemplate::New(isolate,
810
          v8impl::FunctionCallbackWrapper::Invoke,
811
          cbdata,
812
5
          v8::Signature::New(isolate, tpl));
813
814
10
      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
815
    } else {
816
6
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
817
12
      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
818
    }
819
  }
820
821
7
  v8::Local<v8::Context> context = env->context();
822
  *result = v8impl::JsValueFromV8LocalValue(
823
21
      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
824
825
7
  if (static_property_count > 0) {
826
2
    std::vector<napi_property_descriptor> static_descriptors;
827
2
    static_descriptors.reserve(static_property_count);
828
829
22
    for (size_t i = 0; i < property_count; i++) {
830
20
      const napi_property_descriptor* p = properties + i;
831
20
      if ((p->attributes & napi_static) != 0) {
832
4
        static_descriptors.push_back(*p);
833
      }
834
    }
835
836
    napi_status status =
837
        napi_define_properties(env,
838
                               *result,
839
                               static_descriptors.size(),
840
2
                               static_descriptors.data());
841

2
    if (status != napi_ok) return status;
842
  }
843
844
14
  return GET_RETURN_STATUS(env);
845
}
846
847
4
napi_status napi_get_property_names(napi_env env,
848
                                    napi_value object,
849
                                    napi_value* result) {
850

8
  NAPI_PREAMBLE(env);
851
4
  CHECK_ARG(env, result);
852
853
4
  v8::Local<v8::Context> context = env->context();
854
  v8::Local<v8::Object> obj;
855

16
  CHECK_TO_OBJECT(env, context, obj, object);
856
857
4
  auto maybe_propertynames = obj->GetPropertyNames(context);
858
859
4
  CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure);
860
861
  *result = v8impl::JsValueFromV8LocalValue(
862
8
      maybe_propertynames.ToLocalChecked());
863
4
  return GET_RETURN_STATUS(env);
864
}
865
866
15
napi_status napi_set_property(napi_env env,
867
                              napi_value object,
868
                              napi_value key,
869
                              napi_value value) {
870

30
  NAPI_PREAMBLE(env);
871
15
  CHECK_ARG(env, key);
872
15
  CHECK_ARG(env, value);
873
874
15
  v8::Local<v8::Context> context = env->context();
875
  v8::Local<v8::Object> obj;
876
877

60
  CHECK_TO_OBJECT(env, context, obj, object);
878
879
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
880
15
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
881
882
15
  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
883
884
30
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
885
15
  return GET_RETURN_STATUS(env);
886
}
887
888
8
napi_status napi_has_property(napi_env env,
889
                              napi_value object,
890
                              napi_value key,
891
                              bool* result) {
892

16
  NAPI_PREAMBLE(env);
893
8
  CHECK_ARG(env, result);
894
8
  CHECK_ARG(env, key);
895
896
8
  v8::Local<v8::Context> context = env->context();
897
  v8::Local<v8::Object> obj;
898
899

32
  CHECK_TO_OBJECT(env, context, obj, object);
900
901
8
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
902
8
  v8::Maybe<bool> has_maybe = obj->Has(context, k);
903
904
8
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
905
906
16
  *result = has_maybe.FromMaybe(false);
907
8
  return GET_RETURN_STATUS(env);
908
}
909
910
24
napi_status napi_get_property(napi_env env,
911
                              napi_value object,
912
                              napi_value key,
913
                              napi_value* result) {
914

48
  NAPI_PREAMBLE(env);
915
24
  CHECK_ARG(env, key);
916
24
  CHECK_ARG(env, result);
917
918
24
  v8::Local<v8::Context> context = env->context();
919
24
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
920
  v8::Local<v8::Object> obj;
921
922

96
  CHECK_TO_OBJECT(env, context, obj, object);
923
924
24
  auto get_maybe = obj->Get(context, k);
925
926
24
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
927
928
24
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
929
24
  *result = v8impl::JsValueFromV8LocalValue(val);
930
24
  return GET_RETURN_STATUS(env);
931
}
932
933
5
napi_status napi_delete_property(napi_env env,
934
                                 napi_value object,
935
                                 napi_value key,
936
                                 bool* result) {
937

10
  NAPI_PREAMBLE(env);
938
5
  CHECK_ARG(env, key);
939
940
5
  v8::Local<v8::Context> context = env->context();
941
5
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
942
  v8::Local<v8::Object> obj;
943
944

20
  CHECK_TO_OBJECT(env, context, obj, object);
945
5
  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
946
5
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
947
948
5
  if (result != nullptr)
949
10
    *result = delete_maybe.FromMaybe(false);
950
951
5
  return GET_RETURN_STATUS(env);
952
}
953
954
15
napi_status napi_has_own_property(napi_env env,
955
                                  napi_value object,
956
                                  napi_value key,
957
                                  bool* result) {
958

30
  NAPI_PREAMBLE(env);
959
15
  CHECK_ARG(env, key);
960
961
15
  v8::Local<v8::Context> context = env->context();
962
  v8::Local<v8::Object> obj;
963
964

60
  CHECK_TO_OBJECT(env, context, obj, object);
965
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
966
24
  RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected);
967
6
  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
968
6
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
969
12
  *result = has_maybe.FromMaybe(false);
970
971
6
  return GET_RETURN_STATUS(env);
972
}
973
974
20
napi_status napi_set_named_property(napi_env env,
975
                                    napi_value object,
976
                                    const char* utf8name,
977
                                    napi_value value) {
978

40
  NAPI_PREAMBLE(env);
979
20
  CHECK_ARG(env, value);
980
981
20
  v8::Local<v8::Context> context = env->context();
982
  v8::Local<v8::Object> obj;
983
984

80
  CHECK_TO_OBJECT(env, context, obj, object);
985
986
  v8::Local<v8::Name> key;
987
60
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
988
989
20
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
990
991
20
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
992
993
40
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
994
20
  return GET_RETURN_STATUS(env);
995
}
996
997
3
napi_status napi_has_named_property(napi_env env,
998
                                    napi_value object,
999
                                    const char* utf8name,
1000
                                    bool* result) {
1001

6
  NAPI_PREAMBLE(env);
1002
3
  CHECK_ARG(env, result);
1003
1004
3
  v8::Local<v8::Context> context = env->context();
1005
  v8::Local<v8::Object> obj;
1006
1007

12
  CHECK_TO_OBJECT(env, context, obj, object);
1008
1009
  v8::Local<v8::Name> key;
1010
9
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1011
1012
3
  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1013
1014
3
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1015
1016
6
  *result = has_maybe.FromMaybe(false);
1017
3
  return GET_RETURN_STATUS(env);
1018
}
1019
1020
napi_status napi_get_named_property(napi_env env,
1021
                                    napi_value object,
1022
                                    const char* utf8name,
1023
                                    napi_value* result) {
1024
  NAPI_PREAMBLE(env);
1025
  CHECK_ARG(env, result);
1026
1027
  v8::Local<v8::Context> context = env->context();
1028
1029
  v8::Local<v8::Name> key;
1030
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1031
1032
  v8::Local<v8::Object> obj;
1033
1034
  CHECK_TO_OBJECT(env, context, obj, object);
1035
1036
  auto get_maybe = obj->Get(context, key);
1037
1038
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1039
1040
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1041
  *result = v8impl::JsValueFromV8LocalValue(val);
1042
  return GET_RETURN_STATUS(env);
1043
}
1044
1045
11
napi_status napi_set_element(napi_env env,
1046
                             napi_value object,
1047
                             uint32_t index,
1048
                             napi_value value) {
1049

22
  NAPI_PREAMBLE(env);
1050
11
  CHECK_ARG(env, value);
1051
1052
11
  v8::Local<v8::Context> context = env->context();
1053
  v8::Local<v8::Object> obj;
1054
1055

44
  CHECK_TO_OBJECT(env, context, obj, object);
1056
1057
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1058
11
  auto set_maybe = obj->Set(context, index, val);
1059
1060
22
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1061
1062
11
  return GET_RETURN_STATUS(env);
1063
}
1064
1065
2
napi_status napi_has_element(napi_env env,
1066
                             napi_value object,
1067
                             uint32_t index,
1068
                             bool* result) {
1069

4
  NAPI_PREAMBLE(env);
1070
2
  CHECK_ARG(env, result);
1071
1072
2
  v8::Local<v8::Context> context = env->context();
1073
  v8::Local<v8::Object> obj;
1074
1075

8
  CHECK_TO_OBJECT(env, context, obj, object);
1076
1077
2
  v8::Maybe<bool> has_maybe = obj->Has(context, index);
1078
1079
2
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1080
1081
4
  *result = has_maybe.FromMaybe(false);
1082
2
  return GET_RETURN_STATUS(env);
1083
}
1084
1085
27
napi_status napi_get_element(napi_env env,
1086
                             napi_value object,
1087
                             uint32_t index,
1088
                             napi_value* result) {
1089

54
  NAPI_PREAMBLE(env);
1090
27
  CHECK_ARG(env, result);
1091
1092
27
  v8::Local<v8::Context> context = env->context();
1093
  v8::Local<v8::Object> obj;
1094
1095

108
  CHECK_TO_OBJECT(env, context, obj, object);
1096
1097
27
  auto get_maybe = obj->Get(context, index);
1098
1099
27
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1100
1101
54
  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
1102
27
  return GET_RETURN_STATUS(env);
1103
}
1104
1105
1
napi_status napi_delete_element(napi_env env,
1106
                                napi_value object,
1107
                                uint32_t index,
1108
                                bool* result) {
1109

2
  NAPI_PREAMBLE(env);
1110
1111
1
  v8::Local<v8::Context> context = env->context();
1112
  v8::Local<v8::Object> obj;
1113
1114

4
  CHECK_TO_OBJECT(env, context, obj, object);
1115
1
  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
1116
1
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1117
1118
1
  if (result != nullptr)
1119
2
    *result = delete_maybe.FromMaybe(false);
1120
1121
1
  return GET_RETURN_STATUS(env);
1122
}
1123
1124
50
napi_status napi_define_properties(napi_env env,
1125
                                   napi_value object,
1126
                                   size_t property_count,
1127
                                   const napi_property_descriptor* properties) {
1128

100
  NAPI_PREAMBLE(env);
1129
50
  if (property_count > 0) {
1130
50
    CHECK_ARG(env, properties);
1131
  }
1132
1133
50
  v8::Local<v8::Context> context = env->context();
1134
1135
  v8::Local<v8::Object> obj;
1136

200
  CHECK_TO_OBJECT(env, context, obj, object);
1137
1138
664
  for (size_t i = 0; i < property_count; i++) {
1139
282
    const napi_property_descriptor* p = &properties[i];
1140
1141
    v8::Local<v8::Name> property_name;
1142
    napi_status status =
1143
282
        v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
1144
1145
282
    if (status != napi_ok) {
1146
      return napi_set_last_error(env, status);
1147
    }
1148
1149
    v8::PropertyAttribute attributes =
1150
282
        v8impl::V8PropertyAttributesFromDescriptor(p);
1151
1152

282
    if (p->getter != nullptr || p->setter != nullptr) {
1153
      v8::Local<v8::Value> cbdata = v8impl::CreateAccessorCallbackData(
1154
        env,
1155
        p->getter,
1156
        p->setter,
1157
9
        p->data);
1158
1159
      auto set_maybe = obj->SetAccessor(
1160
        context,
1161
        property_name,
1162
        p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
1163
        p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
1164
        cbdata,
1165
        v8::AccessControl::DEFAULT,
1166

18
        attributes);
1167
1168
18
      if (!set_maybe.FromMaybe(false)) {
1169
        return napi_set_last_error(env, napi_invalid_arg);
1170
9
      }
1171
273
    } else if (p->method != nullptr) {
1172
      v8::Local<v8::Value> cbdata =
1173
260
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
1174
1175
260
      CHECK_MAYBE_EMPTY(env, cbdata, napi_generic_failure);
1176
1177
      v8::MaybeLocal<v8::Function> maybe_fn =
1178
          v8::Function::New(context,
1179
                            v8impl::FunctionCallbackWrapper::Invoke,
1180
260
                            cbdata);
1181
1182
260
      CHECK_MAYBE_EMPTY(env, maybe_fn, napi_generic_failure);
1183
1184
      auto define_maybe = obj->DefineOwnProperty(
1185
260
        context, property_name, maybe_fn.ToLocalChecked(), attributes);
1186
1187
520
      if (!define_maybe.FromMaybe(false)) {
1188
        return napi_set_last_error(env, napi_generic_failure);
1189
      }
1190
    } else {
1191
13
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1192
1193
      auto define_maybe =
1194
13
          obj->DefineOwnProperty(context, property_name, value, attributes);
1195
1196
26
      if (!define_maybe.FromMaybe(false)) {
1197
        return napi_set_last_error(env, napi_invalid_arg);
1198
      }
1199
    }
1200
  }
1201
1202
50
  return GET_RETURN_STATUS(env);
1203
}
1204
1205
11
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1206
11
  CHECK_ENV(env);
1207
11
  CHECK_ARG(env, value);
1208
11
  CHECK_ARG(env, result);
1209
1210
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1211
1212
22
  *result = val->IsArray();
1213
11
  return napi_clear_last_error(env);
1214
}
1215
1216
13
napi_status napi_get_array_length(napi_env env,
1217
                                  napi_value value,
1218
                                  uint32_t* result) {
1219

26
  NAPI_PREAMBLE(env);
1220
13
  CHECK_ARG(env, value);
1221
13
  CHECK_ARG(env, result);
1222
1223
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1224
13
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1225
1226
13
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1227
26
  *result = arr->Length();
1228
1229
13
  return GET_RETURN_STATUS(env);
1230
}
1231
1232
9
napi_status napi_strict_equals(napi_env env,
1233
                               napi_value lhs,
1234
                               napi_value rhs,
1235
                               bool* result) {
1236

18
  NAPI_PREAMBLE(env);
1237
9
  CHECK_ARG(env, lhs);
1238
9
  CHECK_ARG(env, rhs);
1239
9
  CHECK_ARG(env, result);
1240
1241
9
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1242
9
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1243
1244
18
  *result = a->StrictEquals(b);
1245
9
  return GET_RETURN_STATUS(env);
1246
}
1247
1248
4
napi_status napi_get_prototype(napi_env env,
1249
                               napi_value object,
1250
                               napi_value* result) {
1251

8
  NAPI_PREAMBLE(env);
1252
4
  CHECK_ARG(env, result);
1253
1254
4
  v8::Local<v8::Context> context = env->context();
1255
1256
  v8::Local<v8::Object> obj;
1257

16
  CHECK_TO_OBJECT(env, context, obj, object);
1258
1259
4
  v8::Local<v8::Value> val = obj->GetPrototype();
1260
4
  *result = v8impl::JsValueFromV8LocalValue(val);
1261
4
  return GET_RETURN_STATUS(env);
1262
}
1263
1264
8
napi_status napi_create_object(napi_env env, napi_value* result) {
1265
8
  CHECK_ENV(env);
1266
8
  CHECK_ARG(env, result);
1267
1268
  *result = v8impl::JsValueFromV8LocalValue(
1269
16
      v8::Object::New(env->isolate));
1270
1271
8
  return napi_clear_last_error(env);
1272
}
1273
1274
1
napi_status napi_create_array(napi_env env, napi_value* result) {
1275
1
  CHECK_ENV(env);
1276
1
  CHECK_ARG(env, result);
1277
1278
  *result = v8impl::JsValueFromV8LocalValue(
1279
2
      v8::Array::New(env->isolate));
1280
1281
1
  return napi_clear_last_error(env);
1282
}
1283
1284
4
napi_status napi_create_array_with_length(napi_env env,
1285
                                          size_t length,
1286
                                          napi_value* result) {
1287
4
  CHECK_ENV(env);
1288
4
  CHECK_ARG(env, result);
1289
1290
  *result = v8impl::JsValueFromV8LocalValue(
1291
8
      v8::Array::New(env->isolate, length));
1292
1293
4
  return napi_clear_last_error(env);
1294
}
1295
1296
11
napi_status napi_create_string_latin1(napi_env env,
1297
                                      const char* str,
1298
                                      size_t length,
1299
                                      napi_value* result) {
1300
11
  CHECK_ENV(env);
1301
11
  CHECK_ARG(env, result);
1302
1303
11
  auto isolate = env->isolate;
1304
  auto str_maybe =
1305
      v8::String::NewFromOneByte(isolate,
1306
                                 reinterpret_cast<const uint8_t*>(str),
1307
                                 v8::NewStringType::kInternalized,
1308
11
                                 length);
1309
11
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1310
1311
22
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1312
11
  return napi_clear_last_error(env);
1313
}
1314
1315
573
napi_status napi_create_string_utf8(napi_env env,
1316
                                    const char* str,
1317
                                    size_t length,
1318
                                    napi_value* result) {
1319
573
  CHECK_ENV(env);
1320
573
  CHECK_ARG(env, result);
1321
1322
  v8::Local<v8::String> s;
1323

1718
  CHECK_NEW_FROM_UTF8_LEN(env, s, str, length);
1324
1325
1144
  *result = v8impl::JsValueFromV8LocalValue(s);
1326
572
  return napi_clear_last_error(env);
1327
}
1328
1329
13
napi_status napi_create_string_utf16(napi_env env,
1330
                                     const char16_t* str,
1331
                                     size_t length,
1332
                                     napi_value* result) {
1333
13
  CHECK_ENV(env);
1334
13
  CHECK_ARG(env, result);
1335
1336
13
  auto isolate = env->isolate;
1337
  auto str_maybe =
1338
      v8::String::NewFromTwoByte(isolate,
1339
                                 reinterpret_cast<const uint16_t*>(str),
1340
                                 v8::NewStringType::kInternalized,
1341
13
                                 length);
1342
13
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1343
1344
26
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1345
13
  return napi_clear_last_error(env);
1346
}
1347
1348
68
napi_status napi_create_double(napi_env env,
1349
                               double value,
1350
                               napi_value* result) {
1351
68
  CHECK_ENV(env);
1352
68
  CHECK_ARG(env, result);
1353
1354
  *result = v8impl::JsValueFromV8LocalValue(
1355
136
      v8::Number::New(env->isolate, value));
1356
1357
68
  return napi_clear_last_error(env);
1358
}
1359
1360
144
napi_status napi_create_int32(napi_env env,
1361
                              int32_t value,
1362
                              napi_value* result) {
1363
144
  CHECK_ENV(env);
1364
144
  CHECK_ARG(env, result);
1365
1366
  *result = v8impl::JsValueFromV8LocalValue(
1367
288
      v8::Integer::New(env->isolate, value));
1368
1369
144
  return napi_clear_last_error(env);
1370
}
1371
1372
549
napi_status napi_create_uint32(napi_env env,
1373
                               uint32_t value,
1374
                               napi_value* result) {
1375
549
  CHECK_ENV(env);
1376
549
  CHECK_ARG(env, result);
1377
1378
  *result = v8impl::JsValueFromV8LocalValue(
1379
1098
      v8::Integer::NewFromUnsigned(env->isolate, value));
1380
1381
549
  return napi_clear_last_error(env);
1382
}
1383
1384
24
napi_status napi_create_int64(napi_env env,
1385
                              int64_t value,
1386
                              napi_value* result) {
1387
24
  CHECK_ENV(env);
1388
24
  CHECK_ARG(env, result);
1389
1390
  *result = v8impl::JsValueFromV8LocalValue(
1391
48
      v8::Number::New(env->isolate, static_cast<double>(value)));
1392
1393
24
  return napi_clear_last_error(env);
1394
}
1395
1396
9
napi_status napi_create_bigint_int64(napi_env env,
1397
                                     int64_t value,
1398
                                     napi_value* result) {
1399
9
  CHECK_ENV(env);
1400
9
  CHECK_ARG(env, result);
1401
1402
  *result = v8impl::JsValueFromV8LocalValue(
1403
18
      v8::BigInt::New(env->isolate, value));
1404
1405
9
  return napi_clear_last_error(env);
1406
}
1407
1408
6
napi_status napi_create_bigint_uint64(napi_env env,
1409
                                      uint64_t value,
1410
                                      napi_value* result) {
1411
6
  CHECK_ENV(env);
1412
6
  CHECK_ARG(env, result);
1413
1414
  *result = v8impl::JsValueFromV8LocalValue(
1415
12
      v8::BigInt::NewFromUnsigned(env->isolate, value));
1416
1417
6
  return napi_clear_last_error(env);
1418
}
1419
1420
12
napi_status napi_create_bigint_words(napi_env env,
1421
                                     int sign_bit,
1422
                                     size_t word_count,
1423
                                     const uint64_t* words,
1424
                                     napi_value* result) {
1425

24
  NAPI_PREAMBLE(env);
1426
12
  CHECK_ARG(env, words);
1427
12
  CHECK_ARG(env, result);
1428
1429
12
  v8::Local<v8::Context> context = env->context();
1430
1431
12
  if (word_count > INT_MAX) {
1432
1
    napi_throw_range_error(env, nullptr, "Maximum BigInt size exceeded");
1433
1
    return napi_set_last_error(env, napi_pending_exception);
1434
  }
1435
1436
  v8::MaybeLocal<v8::BigInt> b = v8::BigInt::NewFromWords(
1437
11
      context, sign_bit, word_count, words);
1438
1439
11
  if (try_catch.HasCaught()) {
1440
    return napi_set_last_error(env, napi_pending_exception);
1441
  } else {
1442
11
    CHECK_MAYBE_EMPTY(env, b, napi_generic_failure);
1443
22
    *result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
1444
11
    return napi_clear_last_error(env);
1445
12
  }
1446
}
1447
1448
1250
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
1449
1250
  CHECK_ENV(env);
1450
1250
  CHECK_ARG(env, result);
1451
1452
1250
  v8::Isolate* isolate = env->isolate;
1453
1454
1250
  if (value) {
1455
1424
    *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
1456
  } else {
1457
1076
    *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
1458
  }
1459
1460
1250
  return napi_clear_last_error(env);
1461
}
1462
1463
13
napi_status napi_create_symbol(napi_env env,
1464
                               napi_value description,
1465
                               napi_value* result) {
1466
13
  CHECK_ENV(env);
1467
13
  CHECK_ARG(env, result);
1468
1469
13
  v8::Isolate* isolate = env->isolate;
1470
1471
13
  if (description == nullptr) {
1472
6
    *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
1473
  } else {
1474
11
    v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
1475
22
    RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
1476
1477
    *result = v8impl::JsValueFromV8LocalValue(
1478
33
      v8::Symbol::New(isolate, desc.As<v8::String>()));
1479
  }
1480
1481
13
  return napi_clear_last_error(env);
1482
}
1483
1484
196
static inline napi_status set_error_code(napi_env env,
1485
                                         v8::Local<v8::Value> error,
1486
                                         napi_value code,
1487
                                         const char* code_cstring) {
1488

196
  if ((code != nullptr) || (code_cstring != nullptr)) {
1489
115
    v8::Isolate* isolate = env->isolate;
1490
115
    v8::Local<v8::Context> context = env->context();
1491
115
    v8::Local<v8::Object> err_object = error.As<v8::Object>();
1492
1493
115
    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1494
115
    if (code != nullptr) {
1495
4
      code_value = v8impl::V8LocalValueFromJsValue(code);
1496
8
      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1497
    } else {
1498
333
      CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
1499
    }
1500
1501
    v8::Local<v8::Name> code_key;
1502
345
    CHECK_NEW_FROM_UTF8(env, code_key, "code");
1503
1504
115
    v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
1505
230
    RETURN_STATUS_IF_FALSE(env,
1506
                           set_maybe.FromMaybe(false),
1507
                           napi_generic_failure);
1508
1509
    // now update the name to be "name [code]" where name is the
1510
    // original name and code is the code associated with the Error
1511
    v8::Local<v8::String> name_string;
1512
345
    CHECK_NEW_FROM_UTF8(env, name_string, "");
1513
    v8::Local<v8::Name> name_key;
1514
345
    CHECK_NEW_FROM_UTF8(env, name_key, "name");
1515
1516
115
    auto maybe_name = err_object->Get(context, name_key);
1517
115
    if (!maybe_name.IsEmpty()) {
1518
115
      v8::Local<v8::Value> name = maybe_name.ToLocalChecked();
1519
230
      if (name->IsString()) {
1520
        name_string =
1521
115
            v8::String::Concat(isolate, name_string, name.As<v8::String>());
1522
      }
1523
    }
1524
    name_string = v8::String::Concat(
1525
115
        isolate, name_string, NAPI_FIXED_ONE_BYTE_STRING(isolate, " ["));
1526
    name_string =
1527
115
        v8::String::Concat(isolate, name_string, code_value.As<v8::String>());
1528
    name_string = v8::String::Concat(
1529
115
        isolate, name_string, NAPI_FIXED_ONE_BYTE_STRING(isolate, "]"));
1530
1531
115
    set_maybe = err_object->Set(context, name_key, name_string);
1532
230
    RETURN_STATUS_IF_FALSE(env,
1533
                           set_maybe.FromMaybe(false),
1534
                           napi_generic_failure);
1535
  }
1536
196
  return napi_ok;
1537
}
1538
1539
4
napi_status napi_create_error(napi_env env,
1540
                              napi_value code,
1541
                              napi_value msg,
1542
                              napi_value* result) {
1543
4
  CHECK_ENV(env);
1544
4
  CHECK_ARG(env, msg);
1545
4
  CHECK_ARG(env, result);
1546
1547
4
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1548
8
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1549
1550
  v8::Local<v8::Value> error_obj =
1551
4
      v8::Exception::Error(message_value.As<v8::String>());
1552
4
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1553
4
  if (status != napi_ok) return status;
1554
1555
4
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1556
1557
4
  return napi_clear_last_error(env);
1558
}
1559
1560
2
napi_status napi_create_type_error(napi_env env,
1561
                                   napi_value code,
1562
                                   napi_value msg,
1563
                                   napi_value* result) {
1564
2
  CHECK_ENV(env);
1565
2
  CHECK_ARG(env, msg);
1566
2
  CHECK_ARG(env, result);
1567
1568
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1569
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1570
1571
  v8::Local<v8::Value> error_obj =
1572
2
      v8::Exception::TypeError(message_value.As<v8::String>());
1573
2
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1574
2
  if (status != napi_ok) return status;
1575
1576
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1577
1578
2
  return napi_clear_last_error(env);
1579
}
1580
1581
2
napi_status napi_create_range_error(napi_env env,
1582
                                    napi_value code,
1583
                                    napi_value msg,
1584
                                    napi_value* result) {
1585
2
  CHECK_ENV(env);
1586
2
  CHECK_ARG(env, msg);
1587
2
  CHECK_ARG(env, result);
1588
1589
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1590
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1591
1592
  v8::Local<v8::Value> error_obj =
1593
2
      v8::Exception::RangeError(message_value.As<v8::String>());
1594
2
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1595
2
  if (status != napi_ok) return status;
1596
1597
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1598
1599
2
  return napi_clear_last_error(env);
1600
}
1601
1602
425
napi_status napi_typeof(napi_env env,
1603
                        napi_value value,
1604
                        napi_valuetype* result) {
1605
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1606
  // JS exceptions.
1607
425
  CHECK_ENV(env);
1608
425
  CHECK_ARG(env, value);
1609
425
  CHECK_ARG(env, result);
1610
1611
425
  v8::Local<v8::Value> v = v8impl::V8LocalValueFromJsValue(value);
1612
1613
425
  if (v->IsNumber()) {
1614
140
    *result = napi_number;
1615
285
  } else if (v->IsBigInt()) {
1616
26
    *result = napi_bigint;
1617
518
  } else if (v->IsString()) {
1618
80
    *result = napi_string;
1619
179
  } else if (v->IsFunction()) {
1620
    // This test has to come before IsObject because IsFunction
1621
    // implies IsObject
1622
33
    *result = napi_function;
1623
146
  } else if (v->IsExternal()) {
1624
    // This test has to come before IsObject because IsExternal
1625
    // implies IsObject
1626
2
    *result = napi_external;
1627
144
  } else if (v->IsObject()) {
1628
131
    *result = napi_object;
1629
13
  } else if (v->IsBoolean()) {
1630
1
    *result = napi_boolean;
1631
24
  } else if (v->IsUndefined()) {
1632
2
    *result = napi_undefined;
1633
10
  } else if (v->IsSymbol()) {
1634
9
    *result = napi_symbol;
1635
2
  } else if (v->IsNull()) {
1636
1
    *result = napi_null;
1637
  } else {
1638
    // Should not get here unless V8 has added some new kind of value.
1639
    return napi_set_last_error(env, napi_invalid_arg);
1640
  }
1641
1642
425
  return napi_clear_last_error(env);
1643
}
1644
1645
120
napi_status napi_get_undefined(napi_env env, napi_value* result) {
1646
120
  CHECK_ENV(env);
1647
120
  CHECK_ARG(env, result);
1648
1649
  *result = v8impl::JsValueFromV8LocalValue(
1650
240
      v8::Undefined(env->isolate));
1651
1652
120
  return napi_clear_last_error(env);
1653
}
1654
1655
5
napi_status napi_get_null(napi_env env, napi_value* result) {
1656
5
  CHECK_ENV(env);
1657
5
  CHECK_ARG(env, result);
1658
1659
  *result = v8impl::JsValueFromV8LocalValue(
1660
10
        v8::Null(env->isolate));
1661
1662
5
  return napi_clear_last_error(env);
1663
}
1664
1665
// Gets all callback info in a single call. (Ugly, but faster.)
1666
4408
napi_status napi_get_cb_info(
1667
    napi_env env,               // [in] NAPI environment handle
1668
    napi_callback_info cbinfo,  // [in] Opaque callback-info handle
1669
    size_t* argc,      // [in-out] Specifies the size of the provided argv array
1670
                       // and receives the actual count of args.
1671
    napi_value* argv,  // [out] Array of values
1672
    napi_value* this_arg,  // [out] Receives the JS 'this' arg for the call
1673
    void** data) {         // [out] Receives the data pointer for the callback.
1674
4408
  CHECK_ENV(env);
1675
4408
  CHECK_ARG(env, cbinfo);
1676
1677
  v8impl::CallbackWrapper* info =
1678
4408
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1679
1680
4408
  if (argv != nullptr) {
1681
4379
    CHECK_ARG(env, argc);
1682
4379
    info->Args(argv, *argc);
1683
  }
1684
4408
  if (argc != nullptr) {
1685
4391
    *argc = info->ArgsLength();
1686
  }
1687
4408
  if (this_arg != nullptr) {
1688
36
    *this_arg = info->This();
1689
  }
1690
4408
  if (data != nullptr) {
1691
6
    *data = info->Data();
1692
  }
1693
1694
4408
  return napi_clear_last_error(env);
1695
}
1696
1697
8
napi_status napi_get_new_target(napi_env env,
1698
                                napi_callback_info cbinfo,
1699
                                napi_value* result) {
1700
8
  CHECK_ENV(env);
1701
8
  CHECK_ARG(env, cbinfo);
1702
8
  CHECK_ARG(env, result);
1703
1704
  v8impl::CallbackWrapper* info =
1705
8
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1706
1707
8
  *result = info->GetNewTarget();
1708
8
  return napi_clear_last_error(env);
1709
}
1710
1711
640
napi_status napi_call_function(napi_env env,
1712
                               napi_value recv,
1713
                               napi_value func,
1714
                               size_t argc,
1715
                               const napi_value* argv,
1716
                               napi_value* result) {
1717

1280
  NAPI_PREAMBLE(env);
1718
640
  CHECK_ARG(env, recv);
1719
640
  if (argc > 0) {
1720
595
    CHECK_ARG(env, argv);
1721
  }
1722
1723
640
  v8::Local<v8::Context> context = env->context();
1724
1725
640
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1726
1727
  v8::Local<v8::Function> v8func;
1728

1920
  CHECK_TO_FUNCTION(env, v8func, func);
1729
1730
  auto maybe = v8func->Call(context, v8recv, argc,
1731
1280
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1732
1733
640
  if (try_catch.HasCaught()) {
1734
6
    return napi_set_last_error(env, napi_pending_exception);
1735
  } else {
1736
634
    if (result != nullptr) {
1737
11
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1738
11
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1739
    }
1740
634
    return napi_clear_last_error(env);
1741
640
  }
1742
}
1743
1744
14
napi_status napi_get_global(napi_env env, napi_value* result) {
1745
14
  CHECK_ENV(env);
1746
14
  CHECK_ARG(env, result);
1747
1748
42
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1749
1750
14
  return napi_clear_last_error(env);
1751
}
1752
1753
11
napi_status napi_throw(napi_env env, napi_value error) {
1754

22
  NAPI_PREAMBLE(env);
1755
11
  CHECK_ARG(env, error);
1756
1757
11
  v8::Isolate* isolate = env->isolate;
1758
1759
11
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1760
  // any VM calls after this point and before returning
1761
  // to the javascript invoker will fail
1762
11
  return napi_clear_last_error(env);
1763
}
1764
1765
75
napi_status napi_throw_error(napi_env env,
1766
                             const char* code,
1767
                             const char* msg) {
1768

150
  NAPI_PREAMBLE(env);
1769
1770
75
  v8::Isolate* isolate = env->isolate;
1771
  v8::Local<v8::String> str;
1772
225
  CHECK_NEW_FROM_UTF8(env, str, msg);
1773
1774
75
  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1775
75
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1776
75
  if (status != napi_ok) return status;
1777
1778
75
  isolate->ThrowException(error_obj);
1779
  // any VM calls after this point and before returning
1780
  // to the javascript invoker will fail
1781
75
  return napi_clear_last_error(env);
1782
}
1783
1784
90
napi_status napi_throw_type_error(napi_env env,
1785
                                  const char* code,
1786
                                  const char* msg) {
1787

180
  NAPI_PREAMBLE(env);
1788
1789
90
  v8::Isolate* isolate = env->isolate;
1790
  v8::Local<v8::String> str;
1791
270
  CHECK_NEW_FROM_UTF8(env, str, msg);
1792
1793
90
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1794
90
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1795
90
  if (status != napi_ok) return status;
1796
1797
90
  isolate->ThrowException(error_obj);
1798
  // any VM calls after this point and before returning
1799
  // to the javascript invoker will fail
1800
90
  return napi_clear_last_error(env);
1801
}
1802
1803
23
napi_status napi_throw_range_error(napi_env env,
1804
                                   const char* code,
1805
                                   const char* msg) {
1806

46
  NAPI_PREAMBLE(env);
1807
1808
23
  v8::Isolate* isolate = env->isolate;
1809
  v8::Local<v8::String> str;
1810
69
  CHECK_NEW_FROM_UTF8(env, str, msg);
1811
1812
23
  v8::Local<v8::Value> error_obj = v8::Exception::RangeError(str);
1813
23
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1814
23
  if (status != napi_ok) return status;
1815
1816
23
  isolate->ThrowException(error_obj);
1817
  // any VM calls after this point and before returning
1818
  // to the javascript invoker will fail
1819
23
  return napi_clear_last_error(env);
1820
}
1821
1822
10
napi_status napi_is_error(napi_env env, napi_value value, bool* result) {
1823
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot
1824
  // throw JS exceptions.
1825
10
  CHECK_ENV(env);
1826
10
  CHECK_ARG(env, value);
1827
10
  CHECK_ARG(env, result);
1828
1829
10
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1830
20
  *result = val->IsNativeError();
1831
1832
10
  return napi_clear_last_error(env);
1833
}
1834
1835
74
napi_status napi_get_value_double(napi_env env,
1836
                                  napi_value value,
1837
                                  double* result) {
1838
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1839
  // JS exceptions.
1840
74
  CHECK_ENV(env);
1841
74
  CHECK_ARG(env, value);
1842
74
  CHECK_ARG(env, result);
1843
1844
74
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1845
74
  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1846
1847
195
  *result = val.As<v8::Number>()->Value();
1848
1849
65
  return napi_clear_last_error(env);
1850
}
1851
1852
57
napi_status napi_get_value_int32(napi_env env,
1853
                                 napi_value value,
1854
                                 int32_t* result) {
1855
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1856
  // JS exceptions.
1857
57
  CHECK_ENV(env);
1858
57
  CHECK_ARG(env, value);
1859
57
  CHECK_ARG(env, result);
1860
1861
57
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1862
1863
57
  if (val->IsInt32()) {
1864
75
    *result = val.As<v8::Int32>()->Value();
1865
  } else {
1866
32
    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1867
1868
    // Empty context: https://github.com/nodejs/node/issues/14379
1869
    v8::Local<v8::Context> context;
1870
72
    *result = val->Int32Value(context).FromJust();
1871
  }
1872
1873
49
  return napi_clear_last_error(env);
1874
}
1875
1876
82
napi_status napi_get_value_uint32(napi_env env,
1877
                                  napi_value value,
1878
                                  uint32_t* result) {
1879
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1880
  // JS exceptions.
1881
82
  CHECK_ENV(env);
1882
82
  CHECK_ARG(env, value);
1883
82
  CHECK_ARG(env, result);
1884
1885
82
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1886
1887
82
  if (val->IsUint32()) {
1888
192
    *result = val.As<v8::Uint32>()->Value();
1889
  } else {
1890
18
    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1891
1892
    // Empty context: https://github.com/nodejs/node/issues/14379
1893
    v8::Local<v8::Context> context;
1894
30
    *result = val->Uint32Value(context).FromJust();
1895
  }
1896
1897
74
  return napi_clear_last_error(env);
1898
}
1899
1900
32
napi_status napi_get_value_int64(napi_env env,
1901
                                 napi_value value,
1902
                                 int64_t* result) {
1903
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1904
  // JS exceptions.
1905
32
  CHECK_ENV(env);
1906
32
  CHECK_ARG(env, value);
1907
32
  CHECK_ARG(env, result);
1908
1909
32
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1910
1911
  // This is still a fast path very likely to be taken.
1912
32
  if (val->IsInt32()) {
1913
15
    *result = val.As<v8::Int32>()->Value();
1914
5
    return napi_clear_last_error(env);
1915
  }
1916
1917
27
  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1918
1919
  // v8::Value::IntegerValue() converts NaN, +Inf, and -Inf to INT64_MIN,
1920
  // inconsistent with v8::Value::Int32Value() which converts those values to 0.
1921
  // Special-case all non-finite values to match that behavior.
1922
38
  double doubleValue = val.As<v8::Number>()->Value();
1923
19
  if (std::isfinite(doubleValue)) {
1924
    // Empty context: https://github.com/nodejs/node/issues/14379
1925
    v8::Local<v8::Context> context;
1926
45
    *result = val->IntegerValue(context).FromJust();
1927
  } else {
1928
4
    *result = 0;
1929
  }
1930
1931
19
  return napi_clear_last_error(env);
1932
}
1933
1934
20
napi_status napi_get_value_bigint_int64(napi_env env,
1935
                                        napi_value value,
1936
                                        int64_t* result,
1937
                                        bool* lossless) {
1938
20
  CHECK_ENV(env);
1939
20
  CHECK_ARG(env, value);
1940
20
  CHECK_ARG(env, result);
1941
20
  CHECK_ARG(env, lossless);
1942
1943
20
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1944
1945
20
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
1946
1947
60
  *result = val.As<v8::BigInt>()->Int64Value(lossless);
1948
1949
20
  return napi_clear_last_error(env);
1950
}
1951
1952
17
napi_status napi_get_value_bigint_uint64(napi_env env,
1953
                                         napi_value value,
1954
                                         uint64_t* result,
1955
                                         bool* lossless) {
1956
17
  CHECK_ENV(env);
1957
17
  CHECK_ARG(env, value);
1958
17
  CHECK_ARG(env, result);
1959
17
  CHECK_ARG(env, lossless);
1960
1961
17
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1962
1963
17
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
1964
1965
51
  *result = val.As<v8::BigInt>()->Uint64Value(lossless);
1966
1967
17
  return napi_clear_last_error(env);
1968
}
1969
1970
22
napi_status napi_get_value_bigint_words(napi_env env,
1971
                                        napi_value value,
1972
                                        int* sign_bit,
1973
                                        size_t* word_count,
1974
                                        uint64_t* words) {
1975
22
  CHECK_ENV(env);
1976
22
  CHECK_ARG(env, value);
1977
22
  CHECK_ARG(env, word_count);
1978
1979
22
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1980
1981
22
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
1982
1983
22
  v8::Local<v8::BigInt> big = val.As<v8::BigInt>();
1984
1985
22
  int word_count_int = *word_count;
1986
1987

22
  if (sign_bit == nullptr && words == nullptr) {
1988
11
    word_count_int = big->WordCount();
1989
  } else {
1990
11
    CHECK_ARG(env, sign_bit);
1991
11
    CHECK_ARG(env, words);
1992
22
    big->ToWordsArray(sign_bit, &word_count_int, words);
1993
  }
1994
1995
22
  *word_count = word_count_int;
1996
1997
22
  return napi_clear_last_error(env);
1998
}
1999
2000
80
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) {
2001
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2002
  // JS exceptions.
2003
80
  CHECK_ENV(env);
2004
80
  CHECK_ARG(env, value);
2005
80
  CHECK_ARG(env, result);
2006
2007
80
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2008
80
  RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected);
2009
2010
204
  *result = val.As<v8::Boolean>()->Value();
2011
2012
68
  return napi_clear_last_error(env);
2013
}
2014
2015
// Copies a JavaScript string into a LATIN-1 string buffer. The result is the
2016
// number of bytes (excluding the null terminator) copied into buf.
2017
// A sufficient buffer size should be greater than the length of string,
2018
// reserving space for null terminator.
2019
// If bufsize is insufficient, the string will be truncated and null terminated.
2020
// If buf is NULL, this method returns the length of the string (in bytes)
2021
// via the result parameter.
2022
// The result argument is optional unless buf is NULL.
2023
11
napi_status napi_get_value_string_latin1(napi_env env,
2024
                                         napi_value value,
2025
                                         char* buf,
2026
                                         size_t bufsize,
2027
                                         size_t* result) {
2028
11
  CHECK_ENV(env);
2029
11
  CHECK_ARG(env, value);
2030
2031
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2032
22
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2033
2034
11
  if (!buf) {
2035
    CHECK_ARG(env, result);
2036
    *result = val.As<v8::String>()->Length();
2037
  } else {
2038
    int copied =
2039
        val.As<v8::String>()->WriteOneByte(env->isolate,
2040
                                           reinterpret_cast<uint8_t*>(buf),
2041
                                           0,
2042
                                           bufsize - 1,
2043
33
                                           v8::String::NO_NULL_TERMINATION);
2044
2045
11
    buf[copied] = '\0';
2046
11
    if (result != nullptr) {
2047
11
      *result = copied;
2048
    }
2049
  }
2050
2051
11
  return napi_clear_last_error(env);
2052
}
2053
2054
// Copies a JavaScript string into a UTF-8 string buffer. The result is the
2055
// number of bytes (excluding the null terminator) copied into buf.
2056
// A sufficient buffer size should be greater than the length of string,
2057
// reserving space for null terminator.
2058
// If bufsize is insufficient, the string will be truncated and null terminated.
2059
// If buf is NULL, this method returns the length of the string (in bytes)
2060
// via the result parameter.
2061
// The result argument is optional unless buf is NULL.
2062
34
napi_status napi_get_value_string_utf8(napi_env env,
2063
                                       napi_value value,
2064
                                       char* buf,
2065
                                       size_t bufsize,
2066
                                       size_t* result) {
2067
34
  CHECK_ENV(env);
2068
34
  CHECK_ARG(env, value);
2069
2070
34
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2071
68
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2072
2073
25
  if (!buf) {
2074
7
    CHECK_ARG(env, result);
2075
21
    *result = val.As<v8::String>()->Utf8Length(env->isolate);
2076
  } else {
2077
    int copied = val.As<v8::String>()->WriteUtf8(
2078
        env->isolate,
2079
        buf,
2080
        bufsize - 1,
2081
        nullptr,
2082
54
        v8::String::REPLACE_INVALID_UTF8 | v8::String::NO_NULL_TERMINATION);
2083
2084
18
    buf[copied] = '\0';
2085
18
    if (result != nullptr) {
2086
16
      *result = copied;
2087
    }
2088
  }
2089
2090
25
  return napi_clear_last_error(env);
2091
}
2092
2093
// Copies a JavaScript string into a UTF-16 string buffer. The result is the
2094
// number of 2-byte code units (excluding the null terminator) copied into buf.
2095
// A sufficient buffer size should be greater than the length of string,
2096
// reserving space for null terminator.
2097
// If bufsize is insufficient, the string will be truncated and null terminated.
2098
// If buf is NULL, this method returns the length of the string (in 2-byte
2099
// code units) via the result parameter.
2100
// The result argument is optional unless buf is NULL.
2101
20
napi_status napi_get_value_string_utf16(napi_env env,
2102
                                        napi_value value,
2103
                                        char16_t* buf,
2104
                                        size_t bufsize,
2105
                                        size_t* result) {
2106
20
  CHECK_ENV(env);
2107
20
  CHECK_ARG(env, value);
2108
2109
20
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2110
40
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2111
2112
20
  if (!buf) {
2113
7
    CHECK_ARG(env, result);
2114
    // V8 assumes UTF-16 length is the same as the number of characters.
2115
21
    *result = val.As<v8::String>()->Length();
2116
  } else {
2117
    int copied = val.As<v8::String>()->Write(env->isolate,
2118
                                             reinterpret_cast<uint16_t*>(buf),
2119
                                             0,
2120
                                             bufsize - 1,
2121
39
                                             v8::String::NO_NULL_TERMINATION);
2122
2123
13
    buf[copied] = '\0';
2124
13
    if (result != nullptr) {
2125
13
      *result = copied;
2126
    }
2127
  }
2128
2129
20
  return napi_clear_last_error(env);
2130
}
2131
2132
15
napi_status napi_coerce_to_object(napi_env env,
2133
                                  napi_value value,
2134
                                  napi_value* result) {
2135

30
  NAPI_PREAMBLE(env);
2136
15
  CHECK_ARG(env, value);
2137
15
  CHECK_ARG(env, result);
2138
2139
15
  v8::Local<v8::Context> context = env->context();
2140
  v8::Local<v8::Object> obj;
2141

60
  CHECK_TO_OBJECT(env, context, obj, value);
2142
2143
30
  *result = v8impl::JsValueFromV8LocalValue(obj);
2144
15
  return GET_RETURN_STATUS(env);
2145
}
2146
2147
14
napi_status napi_coerce_to_bool(napi_env env,
2148
                                napi_value value,
2149
                                napi_value* result) {
2150

28
  NAPI_PREAMBLE(env);
2151
14
  CHECK_ARG(env, value);
2152
14
  CHECK_ARG(env, result);
2153
2154
14
  v8::Isolate* isolate = env->isolate;
2155
  v8::Local<v8::Boolean> b =
2156
28
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2157
28
  *result = v8impl::JsValueFromV8LocalValue(b);
2158
14
  return GET_RETURN_STATUS(env);
2159
}
2160
2161
15
napi_status napi_coerce_to_number(napi_env env,
2162
                                  napi_value value,
2163
                                  napi_value* result) {
2164

30
  NAPI_PREAMBLE(env);
2165
15
  CHECK_ARG(env, value);
2166
15
  CHECK_ARG(env, result);
2167
2168
15
  v8::Local<v8::Context> context = env->context();
2169
  v8::Local<v8::Number> num;
2170
2171

60
  CHECK_TO_NUMBER(env, context, num, value);
2172
2173
28
  *result = v8impl::JsValueFromV8LocalValue(num);
2174
14
  return GET_RETURN_STATUS(env);
2175
}
2176
2177
14
napi_status napi_coerce_to_string(napi_env env,
2178
                                  napi_value value,
2179
                                  napi_value* result) {
2180

28
  NAPI_PREAMBLE(env);
2181
14
  CHECK_ARG(env, value);
2182
14
  CHECK_ARG(env, result);
2183
2184
14
  v8::Local<v8::Context> context = env->context();
2185
  v8::Local<v8::String> str;
2186
2187

56
  CHECK_TO_STRING(env, context, str, value);
2188
2189
26
  *result = v8impl::JsValueFromV8LocalValue(str);
2190
13
  return GET_RETURN_STATUS(env);
2191
}
2192
2193
1019
napi_status napi_wrap(napi_env env,
2194
                      napi_value js_object,
2195
                      void* native_object,
2196
                      napi_finalize finalize_cb,
2197
                      void* finalize_hint,
2198
                      napi_ref* result) {
2199
  return v8impl::Wrap<v8impl::retrievable>(env,
2200
                                           js_object,
2201
                                           native_object,
2202
                                           finalize_cb,
2203
                                           finalize_hint,
2204
1019
                                           result);
2205
}
2206
2207
24
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2208
24
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2209
}
2210
2211
3
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2212
3
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2213
}
2214
2215
7
napi_status napi_create_external(napi_env env,
2216
                                 void* data,
2217
                                 napi_finalize finalize_cb,
2218
                                 void* finalize_hint,
2219
                                 napi_value* result) {
2220

14
  NAPI_PREAMBLE(env);
2221
7
  CHECK_ARG(env, result);
2222
2223
7
  v8::Isolate* isolate = env->isolate;
2224
2225
7
  v8::Local<v8::Value> external_value = v8::External::New(isolate, data);
2226
2227
  // The Reference object will delete itself after invoking the finalizer
2228
  // callback.
2229
  v8impl::Reference::New(env,
2230
      external_value,
2231
      0,
2232
      true,
2233
      finalize_cb,
2234
      data,
2235
7
      finalize_hint);
2236
2237
7
  *result = v8impl::JsValueFromV8LocalValue(external_value);
2238
2239
7
  return napi_clear_last_error(env);
2240
}
2241
2242
3
napi_status napi_get_value_external(napi_env env,
2243
                                    napi_value value,
2244
                                    void** result) {
2245
3
  CHECK_ENV(env);
2246
3
  CHECK_ARG(env, value);
2247
3
  CHECK_ARG(env, result);
2248
2249
3
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2250
3
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
2251
2252
3
  v8::Local<v8::External> external_value = val.As<v8::External>();
2253
6
  *result = external_value->Value();
2254
2255
3
  return napi_clear_last_error(env);
2256
}
2257
2258
// Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
2259
1528
napi_status napi_create_reference(napi_env env,
2260
                                  napi_value value,
2261
                                  uint32_t initial_refcount,
2262
                                  napi_ref* result) {
2263
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2264
  // JS exceptions.
2265
1528
  CHECK_ENV(env);
2266
1528
  CHECK_ARG(env, value);
2267
1528
  CHECK_ARG(env, result);
2268
2269
1528
  v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(value);
2270
2271

1528
  if (!(v8_value->IsObject() || v8_value->IsFunction())) {
2272
    return napi_set_last_error(env, napi_object_expected);
2273
  }
2274
2275
  v8impl::Reference* reference =
2276
1528
      v8impl::Reference::New(env, v8_value, initial_refcount, false);
2277
2278
1528
  *result = reinterpret_cast<napi_ref>(reference);
2279
1528
  return napi_clear_last_error(env);
2280
}
2281
2282
// Deletes a reference. The referenced value is released, and may be GC'd unless
2283
// there are other references to it.
2284
1527
napi_status napi_delete_reference(napi_env env, napi_ref ref) {
2285
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2286
  // JS exceptions.
2287
1527
  CHECK_ENV(env);
2288
1527
  CHECK_ARG(env, ref);
2289
2290
1527
  v8impl::Reference::Delete(reinterpret_cast<v8impl::Reference*>(ref));
2291
2292
1527
  return napi_clear_last_error(env);
2293
}
2294
2295
// Increments the reference count, optionally returning the resulting count.
2296
// After this call the reference will be a strong reference because its
2297
// refcount is >0, and the referenced object is effectively "pinned".
2298
// Calling this when the refcount is 0 and the object is unavailable
2299
// results in an error.
2300
1
napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) {
2301
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2302
  // JS exceptions.
2303
1
  CHECK_ENV(env);
2304
1
  CHECK_ARG(env, ref);
2305
2306
1
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2307
1
  uint32_t count = reference->Ref();
2308
2309
1
  if (result != nullptr) {
2310
1
    *result = count;
2311
  }
2312
2313
1
  return napi_clear_last_error(env);
2314
}
2315
2316
// Decrements the reference count, optionally returning the resulting count. If
2317
// the result is 0 the reference is now weak and the object may be GC'd at any
2318
// time if there are no other references. Calling this when the refcount is
2319
// already 0 results in an error.
2320
2
napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) {
2321
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2322
  // JS exceptions.
2323
2
  CHECK_ENV(env);
2324
2
  CHECK_ARG(env, ref);
2325
2326
2
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2327
2328
2
  if (reference->RefCount() == 0) {
2329
    return napi_set_last_error(env, napi_generic_failure);
2330
  }
2331
2332
2
  uint32_t count = reference->Unref();
2333
2334
2
  if (result != nullptr) {
2335
2
    *result = count;
2336
  }
2337
2338
2
  return napi_clear_last_error(env);
2339
}
2340
2341
// Attempts to get a referenced value. If the reference is weak, the value might
2342
// no longer be available, in that case the call is still successful but the
2343
// result is NULL.
2344
534
napi_status napi_get_reference_value(napi_env env,
2345
                                     napi_ref ref,
2346
                                     napi_value* result) {
2347
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2348
  // JS exceptions.
2349
534
  CHECK_ENV(env);
2350
534
  CHECK_ARG(env, ref);
2351
532
  CHECK_ARG(env, result);
2352
2353
532
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2354
532
  *result = v8impl::JsValueFromV8LocalValue(reference->Get());
2355
2356
532
  return napi_clear_last_error(env);
2357
}
2358
2359
4
napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result) {
2360
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2361
  // JS exceptions.
2362
4
  CHECK_ENV(env);
2363
4
  CHECK_ARG(env, result);
2364
2365
  *result = v8impl::JsHandleScopeFromV8HandleScope(
2366
4
      new v8impl::HandleScopeWrapper(env->isolate));
2367
4
  env->open_handle_scopes++;
2368
4
  return napi_clear_last_error(env);
2369
}
2370
2371
4
napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) {
2372
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2373
  // JS exceptions.
2374
4
  CHECK_ENV(env);
2375
4
  CHECK_ARG(env, scope);
2376
4
  if (env->open_handle_scopes == 0) {
2377
    return napi_handle_scope_mismatch;
2378
  }
2379
2380
4
  env->open_handle_scopes--;
2381
4
  delete v8impl::V8HandleScopeFromJsHandleScope(scope);
2382
4
  return napi_clear_last_error(env);
2383
}
2384
2385
2
napi_status napi_open_escapable_handle_scope(
2386
    napi_env env,
2387
    napi_escapable_handle_scope* result) {
2388
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2389
  // JS exceptions.
2390
2
  CHECK_ENV(env);
2391
2
  CHECK_ARG(env, result);
2392
2393
  *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope(
2394
2
      new v8impl::EscapableHandleScopeWrapper(env->isolate));
2395
2
  env->open_handle_scopes++;
2396
2
  return napi_clear_last_error(env);
2397
}
2398
2399
2
napi_status napi_close_escapable_handle_scope(
2400
    napi_env env,
2401
    napi_escapable_handle_scope scope) {
2402
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2403
  // JS exceptions.
2404
2
  CHECK_ENV(env);
2405
2
  CHECK_ARG(env, scope);
2406
2
  if (env->open_handle_scopes == 0) {
2407
    return napi_handle_scope_mismatch;
2408
  }
2409
2410
2
  delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2411
2
  env->open_handle_scopes--;
2412
2
  return napi_clear_last_error(env);
2413
}
2414
2415
3
napi_status napi_escape_handle(napi_env env,
2416
                               napi_escapable_handle_scope scope,
2417
                               napi_value escapee,
2418
                               napi_value* result) {
2419
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2420
  // JS exceptions.
2421
3
  CHECK_ENV(env);
2422
3
  CHECK_ARG(env, scope);
2423
3
  CHECK_ARG(env, escapee);
2424
3
  CHECK_ARG(env, result);
2425
2426
  v8impl::EscapableHandleScopeWrapper* s =
2427
3
      v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2428
3
  if (!s->escape_called()) {
2429
    *result = v8impl::JsValueFromV8LocalValue(
2430
2
        s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
2431
2
    return napi_clear_last_error(env);
2432
  }
2433
1
  return napi_set_last_error(env, napi_escape_called_twice);
2434
}
2435
2436
7
napi_status napi_new_instance(napi_env env,
2437
                              napi_value constructor,
2438
                              size_t argc,
2439
                              const napi_value* argv,
2440
                              napi_value* result) {
2441

14
  NAPI_PREAMBLE(env);
2442
7
  CHECK_ARG(env, constructor);
2443
7
  if (argc > 0) {
2444
7
    CHECK_ARG(env, argv);
2445
  }
2446
7
  CHECK_ARG(env, result);
2447
2448
7
  v8::Local<v8::Context> context = env->context();
2449
2450
  v8::Local<v8::Function> ctor;
2451

21
  CHECK_TO_FUNCTION(env, ctor, constructor);
2452
2453
  auto maybe = ctor->NewInstance(context, argc,
2454
14
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2455
2456
7
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2457
2458
14
  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2459
7
  return GET_RETURN_STATUS(env);
2460
}
2461
2462
2278
napi_status napi_instanceof(napi_env env,
2463
                            napi_value object,
2464
                            napi_value constructor,
2465
                            bool* result) {
2466

4556
  NAPI_PREAMBLE(env);
2467
2278
  CHECK_ARG(env, object);
2468
2278
  CHECK_ARG(env, result);
2469
2470
2278
  *result = false;
2471
2472
  v8::Local<v8::Object> ctor;
2473
2278
  v8::Local<v8::Context> context = env->context();
2474
2475

9112
  CHECK_TO_OBJECT(env, context, ctor, constructor);
2476
2477
2278
  if (!ctor->IsFunction()) {
2478
    napi_throw_type_error(env,
2479
                          "ERR_NAPI_CONS_FUNCTION",
2480
88
                          "Constructor must be a function");
2481
2482
88
    return napi_set_last_error(env, napi_function_expected);
2483
  }
2484
2485
2190
  napi_status status = napi_generic_failure;
2486
2487
2190
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(object);
2488
2190
  auto maybe_result = val->InstanceOf(context, ctor);
2489
2190
  CHECK_MAYBE_NOTHING(env, maybe_result, status);
2490
2332
  *result = maybe_result.FromJust();
2491
1166
  return GET_RETURN_STATUS(env);
2492
}
2493
2494
// Methods to support catching exceptions
2495
1226
napi_status napi_is_exception_pending(napi_env env, bool* result) {
2496
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2497
  // pending exception.
2498
1226
  CHECK_ENV(env);
2499
1226
  CHECK_ARG(env, result);
2500
2501
2452
  *result = !env->last_exception.IsEmpty();
2502
1226
  return napi_clear_last_error(env);
2503
}
2504
2505
1
napi_status napi_get_and_clear_last_exception(napi_env env,
2506
                                              napi_value* result) {
2507
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2508
  // pending exception.
2509
1
  CHECK_ENV(env);
2510
1
  CHECK_ARG(env, result);
2511
2512
2
  if (env->last_exception.IsEmpty()) {
2513
    return napi_get_undefined(env, result);
2514
  } else {
2515
    *result = v8impl::JsValueFromV8LocalValue(
2516
2
      v8::Local<v8::Value>::New(env->isolate, env->last_exception));
2517
1
    env->last_exception.Reset();
2518
  }
2519
2520
1
  return napi_clear_last_error(env);
2521
}
2522
2523
31
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) {
2524
31
  CHECK_ENV(env);
2525
31
  CHECK_ARG(env, value);
2526
31
  CHECK_ARG(env, result);
2527
2528
31
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2529
62
  *result = val->IsArrayBuffer();
2530
2531
31
  return napi_clear_last_error(env);
2532
}
2533
2534
2
napi_status napi_create_arraybuffer(napi_env env,
2535
                                    size_t byte_length,
2536
                                    void** data,
2537
                                    napi_value* result) {
2538

4
  NAPI_PREAMBLE(env);
2539
2
  CHECK_ARG(env, result);
2540
2541
2
  v8::Isolate* isolate = env->isolate;
2542
  v8::Local<v8::ArrayBuffer> buffer =
2543
2
      v8::ArrayBuffer::New(isolate, byte_length);
2544
2545
  // Optionally return a pointer to the buffer's data, to avoid another call to
2546
  // retrieve it.
2547
2
  if (data != nullptr) {
2548
2
    *data = buffer->GetContents().Data();
2549
  }
2550
2551
4
  *result = v8impl::JsValueFromV8LocalValue(buffer);
2552
2
  return GET_RETURN_STATUS(env);
2553
}
2554
2555
1
napi_status napi_create_external_arraybuffer(napi_env env,
2556
                                             void* external_data,
2557
                                             size_t byte_length,
2558
                                             napi_finalize finalize_cb,
2559
                                             void* finalize_hint,
2560
                                             napi_value* result) {
2561

2
  NAPI_PREAMBLE(env);
2562
1
  CHECK_ARG(env, result);
2563
2564
1
  v8::Isolate* isolate = env->isolate;
2565
  v8::Local<v8::ArrayBuffer> buffer =
2566
1
      v8::ArrayBuffer::New(isolate, external_data, byte_length);
2567
2568
1
  if (finalize_cb != nullptr) {
2569
    // Create a self-deleting weak reference that invokes the finalizer
2570
    // callback.
2571
    v8impl::Reference::New(env,
2572
        buffer,
2573
        0,
2574
        true,
2575
        finalize_cb,
2576
        external_data,
2577
        finalize_hint);
2578
  }
2579
2580
2
  *result = v8impl::JsValueFromV8LocalValue(buffer);
2581
1
  return GET_RETURN_STATUS(env);
2582
}
2583
2584
2
napi_status napi_get_arraybuffer_info(napi_env env,
2585
                                      napi_value arraybuffer,
2586
                                      void** data,
2587
                                      size_t* byte_length) {
2588
2
  CHECK_ENV(env);
2589
2
  CHECK_ARG(env, arraybuffer);
2590
2591
2
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2592
2
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2593
2594
  v8::ArrayBuffer::Contents contents =
2595
4
      value.As<v8::ArrayBuffer>()->GetContents();
2596
2597
2
  if (data != nullptr) {
2598
2
    *data = contents.Data();
2599
  }
2600
2601
2
  if (byte_length != nullptr) {
2602
2
    *byte_length = contents.ByteLength();
2603
  }
2604
2605
2
  return napi_clear_last_error(env);
2606
}
2607
2608
32
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) {
2609
32
  CHECK_ENV(env);
2610
32
  CHECK_ARG(env, value);
2611
32
  CHECK_ARG(env, result);
2612
2613
32
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2614
64
  *result = val->IsTypedArray();
2615
2616
32
  return napi_clear_last_error(env);
2617
}
2618
2619
33
napi_status napi_create_typedarray(napi_env env,
2620
                                   napi_typedarray_type type,
2621
                                   size_t length,
2622
                                   napi_value arraybuffer,
2623
                                   size_t byte_offset,
2624
                                   napi_value* result) {
2625

66
  NAPI_PREAMBLE(env);
2626
33
  CHECK_ARG(env, arraybuffer);
2627
33
  CHECK_ARG(env, result);
2628
2629
33
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2630
33
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2631
2632
33
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2633
  v8::Local<v8::TypedArray> typedArray;
2634
2635



33
  switch (type) {
2636
    case napi_int8_array:
2637
8
      CREATE_TYPED_ARRAY(
2638
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2639
2
      break;
2640
    case napi_uint8_array:
2641
8
      CREATE_TYPED_ARRAY(
2642
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2643
2
      break;
2644
    case napi_uint8_clamped_array:
2645
5
      CREATE_TYPED_ARRAY(
2646
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2647
1
      break;
2648
    case napi_int16_array:
2649

6
      CREATE_TYPED_ARRAY(
2650
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2651
1
      break;
2652
    case napi_uint16_array:
2653

6
      CREATE_TYPED_ARRAY(
2654
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2655
1
      break;
2656
    case napi_int32_array:
2657

6
      CREATE_TYPED_ARRAY(
2658
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2659
1
      break;
2660
    case napi_uint32_array:
2661

6
      CREATE_TYPED_ARRAY(
2662
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2663
1
      break;
2664
    case napi_float32_array:
2665

6
      CREATE_TYPED_ARRAY(
2666
          env, Float32Array, 4, buffer, byte_offset, length, typedArray);
2667
1
      break;
2668
    case napi_float64_array:
2669

9
      CREATE_TYPED_ARRAY(
2670
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2671
2
      break;
2672
    case napi_bigint64_array:
2673

6
      CREATE_TYPED_ARRAY(
2674
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2675
1
      break;
2676
    case napi_biguint64_array:
2677

6
      CREATE_TYPED_ARRAY(
2678
          env, BigUint64Array, 8, buffer, byte_offset, length, typedArray);
2679
1
      break;
2680
    default:
2681
      return napi_set_last_error(env, napi_invalid_arg);
2682
  }
2683
2684
28
  *result = v8impl::JsValueFromV8LocalValue(typedArray);
2685
14
  return GET_RETURN_STATUS(env);
2686
}
2687
2688
32
napi_status napi_get_typedarray_info(napi_env env,
2689
                                     napi_value typedarray,
2690
                                     napi_typedarray_type* type,
2691
                                     size_t* length,
2692
                                     void** data,
2693
                                     napi_value* arraybuffer,
2694
                                     size_t* byte_offset) {
2695
32
  CHECK_ENV(env);
2696
32
  CHECK_ARG(env, typedarray);
2697
2698
32
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(typedarray);
2699
32
  RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), napi_invalid_arg);
2700
2701
32
  v8::Local<v8::TypedArray> array = value.As<v8::TypedArray>();
2702
2703
32
  if (type != nullptr) {
2704
32
    if (value->IsInt8Array()) {
2705
2
      *type = napi_int8_array;
2706
30
    } else if (value->IsUint8Array()) {
2707
3
      *type = napi_uint8_array;
2708
27
    } else if (value->IsUint8ClampedArray()) {
2709
2
      *type = napi_uint8_clamped_array;
2710
25
    } else if (value->IsInt16Array()) {
2711
3
      *type = napi_int16_array;
2712
22
    } else if (value->IsUint16Array()) {
2713
3
      *type = napi_uint16_array;
2714
19
    } else if (value->IsInt32Array()) {
2715
3
      *type = napi_int32_array;
2716
16
    } else if (value->IsUint32Array()) {
2717
3
      *type = napi_uint32_array;
2718
13
    } else if (value->IsFloat32Array()) {
2719
3
      *type = napi_float32_array;
2720
10
    } else if (value->IsFloat64Array()) {
2721
4
      *type = napi_float64_array;
2722
6
    } else if (value->IsBigInt64Array()) {
2723
3
      *type = napi_bigint64_array;
2724
3
    } else if (value->IsBigUint64Array()) {
2725
3
      *type = napi_biguint64_array;
2726
    }
2727
  }
2728
2729
32
  if (length != nullptr) {
2730
32
    *length = array->Length();
2731
  }
2732
2733
32
  v8::Local<v8::ArrayBuffer> buffer = array->Buffer();
2734
32
  if (data != nullptr) {
2735
    *data = static_cast<uint8_t*>(buffer->GetContents().Data()) +
2736
            array->ByteOffset();
2737
  }
2738
2739
32
  if (arraybuffer != nullptr) {
2740
32
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2741
  }
2742
2743
32
  if (byte_offset != nullptr) {
2744
32
    *byte_offset = array->ByteOffset();
2745
  }
2746
2747
32
  return napi_clear_last_error(env);
2748
}
2749
2750
2
napi_status napi_create_dataview(napi_env env,
2751
                                 size_t byte_length,
2752
                                 napi_value arraybuffer,
2753
                                 size_t byte_offset,
2754
                                 napi_value* result) {
2755

4
  NAPI_PREAMBLE(env);
2756
2
  CHECK_ARG(env, arraybuffer);
2757
2
  CHECK_ARG(env, result);
2758
2759
2
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2760
2
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2761
2762
2
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2763
4
  if (byte_length + byte_offset > buffer->ByteLength()) {
2764
    napi_throw_range_error(
2765
        env,
2766
        "ERR_NAPI_INVALID_DATAVIEW_ARGS",
2767
        "byte_offset + byte_length should be less than or "
2768
1
        "equal to the size in bytes of the array passed in");
2769
1
    return napi_set_last_error(env, napi_pending_exception);
2770
  }
2771
  v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset,
2772
1
                                                       byte_length);
2773
2774
2
  *result = v8impl::JsValueFromV8LocalValue(DataView);
2775
1
  return GET_RETURN_STATUS(env);
2776
}
2777
2778
1
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) {
2779
1
  CHECK_ENV(env);
2780
1
  CHECK_ARG(env, value);
2781
1
  CHECK_ARG(env, result);
2782
2783
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2784
2
  *result = val->IsDataView();
2785
2786
1
  return napi_clear_last_error(env);
2787
}
2788
2789
1
napi_status napi_get_dataview_info(napi_env env,
2790
                                   napi_value dataview,
2791
                                   size_t* byte_length,
2792
                                   void** data,
2793
                                   napi_value* arraybuffer,
2794
                                   size_t* byte_offset) {
2795
1
  CHECK_ENV(env);
2796
1
  CHECK_ARG(env, dataview);
2797
2798
1
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(dataview);
2799
1
  RETURN_STATUS_IF_FALSE(env, value->IsDataView(), napi_invalid_arg);
2800
2801
1
  v8::Local<v8::DataView> array = value.As<v8::DataView>();
2802
2803
1
  if (byte_length != nullptr) {
2804
1
    *byte_length = array->ByteLength();
2805
  }
2806
2807
1
  v8::Local<v8::ArrayBuffer> buffer = array->Buffer();
2808
1
  if (data != nullptr) {
2809
    *data = static_cast<uint8_t*>(buffer->GetContents().Data()) +
2810
            array->ByteOffset();
2811
  }
2812
2813
1
  if (arraybuffer != nullptr) {
2814
1
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2815
  }
2816
2817
1
  if (byte_offset != nullptr) {
2818
1
    *byte_offset = array->ByteOffset();
2819
  }
2820
2821
1
  return napi_clear_last_error(env);
2822
}
2823
2824
1
napi_status napi_get_version(napi_env env, uint32_t* result) {
2825
1
  CHECK_ENV(env);
2826
1
  CHECK_ARG(env, result);
2827
1
  *result = NAPI_VERSION;
2828
1
  return napi_clear_last_error(env);
2829
}
2830
2831
5
napi_status napi_create_promise(napi_env env,
2832
                                napi_deferred* deferred,
2833
                                napi_value* promise) {
2834

10
  NAPI_PREAMBLE(env);
2835
5
  CHECK_ARG(env, deferred);
2836
5
  CHECK_ARG(env, promise);
2837
2838
5
  auto maybe = v8::Promise::Resolver::New(env->context());
2839
5
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2840
2841
5
  auto v8_resolver = maybe.ToLocalChecked();
2842
10
  auto v8_deferred = new v8impl::Persistent<v8::Value>();
2843
5
  v8_deferred->Reset(env->isolate, v8_resolver);
2844
2845
5
  *deferred = v8impl::JsDeferredFromNodePersistent(v8_deferred);
2846
15
  *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise());
2847
5
  return GET_RETURN_STATUS(env);
2848
}
2849
2850
4
napi_status napi_resolve_deferred(napi_env env,
2851
                                  napi_deferred deferred,
2852
                                  napi_value resolution) {
2853
4
  return v8impl::ConcludeDeferred(env, deferred, resolution, true);
2854
}
2855
2856
1
napi_status napi_reject_deferred(napi_env env,
2857
                                 napi_deferred deferred,
2858
                                 napi_value resolution) {
2859
1
  return v8impl::ConcludeDeferred(env, deferred, resolution, false);
2860
}
2861
2862
7
napi_status napi_is_promise(napi_env env,
2863
                            napi_value promise,
2864
                            bool* is_promise) {
2865
7
  CHECK_ENV(env);
2866
7
  CHECK_ARG(env, promise);
2867
7
  CHECK_ARG(env, is_promise);
2868
2869
14
  *is_promise = v8impl::V8LocalValueFromJsValue(promise)->IsPromise();
2870
2871
7
  return napi_clear_last_error(env);
2872
}
2873
2874
2
napi_status napi_run_script(napi_env env,
2875
                            napi_value script,
2876
                            napi_value* result) {
2877

4
  NAPI_PREAMBLE(env);
2878
2
  CHECK_ARG(env, script);
2879
2
  CHECK_ARG(env, result);
2880
2881
2
  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
2882
2883
4
  if (!v8_script->IsString()) {
2884
1
    return napi_set_last_error(env, napi_string_expected);
2885
  }
2886
2887
1
  v8::Local<v8::Context> context = env->context();
2888
2889
  auto maybe_script = v8::Script::Compile(context,
2890
1
      v8::Local<v8::String>::Cast(v8_script));
2891
1
  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
2892
2893
  auto script_result =
2894
2
      maybe_script.ToLocalChecked()->Run(context);
2895
1
  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
2896
2897
2
  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
2898
1
  return GET_RETURN_STATUS(env);
2899
}
2900
2901
3
napi_status napi_add_finalizer(napi_env env,
2902
                               napi_value js_object,
2903
                               void* native_object,
2904
                               napi_finalize finalize_cb,
2905
                               void* finalize_hint,
2906
                               napi_ref* result) {
2907
  return v8impl::Wrap<v8impl::anonymous>(env,
2908
                                         js_object,
2909
                                         native_object,
2910
                                         finalize_cb,
2911
                                         finalize_hint,
2912
3
                                         result);
2913
}
2914
2915
1
napi_status napi_adjust_external_memory(napi_env env,
2916
                                        int64_t change_in_bytes,
2917
                                        int64_t* adjusted_value) {
2918
1
  CHECK_ENV(env);
2919
1
  CHECK_ARG(env, adjusted_value);
2920
2921
  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
2922
2
      change_in_bytes);
2923
2924
1
  return napi_clear_last_error(env);
2925
}