GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/js_native_api_v8.cc Lines: 1237 1279 96.7 %
Date: 2019-02-26 22:23:30 Branches: 829 1438 57.6 %

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
305
V8NameFromPropertyDescriptor(napi_env env,
57
                             const napi_property_descriptor* p,
58
                             v8::Local<v8::Name>* result) {
59
305
  if (p->utf8name != nullptr) {
60
909
    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
305
  return napi_ok;
70
}
71
72
// convert from n-api property attributes to v8::PropertyAttribute
73
305
inline static v8::PropertyAttribute V8PropertyAttributesFromDescriptor(
74
    const napi_property_descriptor* descriptor) {
75
305
  unsigned int attribute_flags = v8::PropertyAttribute::None;
76
77

305
  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
287
  } else if ((descriptor->attributes & napi_writable) == 0) {
83
284
    attribute_flags |= v8::PropertyAttribute::ReadOnly;
84
  }
85
86
305
  if ((descriptor->attributes & napi_enumerable) == 0) {
87
286
    attribute_flags |= v8::PropertyAttribute::DontEnum;
88
  }
89
305
  if ((descriptor->attributes & napi_configurable) == 0) {
90
305
    attribute_flags |= v8::PropertyAttribute::DontDelete;
91
  }
92
93
305
  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
4042
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
3545
  static void Delete(Reference* reference) {
241

3545
    if ((reference->_delete_self) || (reference->_finalize_ran)) {
242
2021
      delete reference;
243
    } else {
244
      // reduce the reference count to 0 and defer until
245
      // finalizer runs
246
1524
      reference->_delete_self = true;
247
1524
      while (reference->Unref() != 0) {}
248
    }
249
3545
  }
250
251
1
  uint32_t Ref() {
252
1
    if (++_refcount == 1) {
253
      _persistent.ClearWeak();
254
    }
255
256
1
    return _refcount;
257
  }
258
259
1526
  uint32_t Unref() {
260
1526
    if (_refcount == 0) {
261
1003
        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
  // The N-API finalizer callback may make calls into the engine. V8's heap is
285
  // not in a consistent state during the weak callback, and therefore it does
286
  // not support calls back into it. However, it provides a mechanism for adding
287
  // a finalizer which may make calls back into the engine by allowing us to
288
  // attach such a second-pass finalizer from the first pass finalizer. Thus,
289
  // we do that here to ensure that the N-API finalizer callback is free to call
290
  // into the engine.
291
2019
  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
292
2019
    Reference* reference = data.GetParameter();
293
294
    // The reference must be reset during the first pass.
295
2019
    reference->_persistent.Reset();
296
297
2019
    data.SetSecondPassCallback(SecondPassCallback);
298
2019
  }
299
300
2019
  static void SecondPassCallback(const v8::WeakCallbackInfo<Reference>& data) {
301
2019
    Reference* reference = data.GetParameter();
302
303
2019
    napi_env env = reference->_env;
304
305
2019
    if (reference->_finalize_callback != nullptr) {
306
1015
      NapiCallIntoModuleThrow(env, [&]() {
307
        reference->_finalize_callback(
308
            reference->_env,
309
            reference->_finalize_data,
310
1015
            reference->_finalize_hint);
311
2030
      });
312
    }
313
314
    // this is safe because if a request to delete the reference
315
    // is made in the finalize_callback it will defer deletion
316
    // to this block and set _delete_self to true
317
2019
    if (reference->_delete_self) {
318
2016
      Delete(reference);
319
    } else {
320
3
      reference->_finalize_ran = true;
321
    }
322
2019
  }
323
324
  v8impl::Persistent<v8::Value> _persistent;
325
  uint32_t _refcount;
326
  bool _delete_self;
327
};
328
329
enum UnwrapAction {
330
  KeepWrap,
331
  RemoveWrap
332
};
333
334
27
inline static napi_status Unwrap(napi_env env,
335
                                 napi_value js_object,
336
                                 void** result,
337
                                 UnwrapAction action) {
338


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

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




2044
  NAPI_PREAMBLE(env);
627

1022
  CHECK_ARG(env, js_object);
628
629
1022
  v8::Local<v8::Context> context = env->context();
630
631
1022
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
632

1022
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
633
1022
  v8::Local<v8::Object> obj = value.As<v8::Object>();
634
635
  if (wrap_type == retrievable) {
636
    // If we've already wrapped this object, we error out.
637
3057
    RETURN_STATUS_IF_FALSE(env,
638
        !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
639
            .FromJust(),
640
        napi_invalid_arg);
641
  } else if (wrap_type == anonymous) {
642
    // If no finalize callback is provided, we error out.
643
3
    CHECK_ARG(env, finalize_cb);
644
  }
645
646
1021
  v8impl::Reference* reference = nullptr;
647

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

8
    CHECK_ARG(env, finalize_cb);
653
8
    reference = v8impl::Reference::New(
654
24
        env, obj, 0, false, finalize_cb, native_object, finalize_hint);
655
8
    *result = reinterpret_cast<napi_ref>(reference);
656
  } else {
657
    // Create a self-deleting reference.
658
1013
    reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb,
659

3039
        native_object, finalize_cb == nullptr ? nullptr : finalize_hint);
660
  }
661
662
  if (wrap_type == retrievable) {
663
4072
    CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper),
664
          v8::External::New(env->isolate, reference)).FromJust());
665
  }
666
667

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


72
  NAPI_PREAMBLE(env);
726
36
  CHECK_ARG(env, result);
727
36
  CHECK_ARG(env, cb);
728
729
36
  v8::Isolate* isolate = env->isolate;
730
  v8::Local<v8::Function> return_value;
731
36
  v8::EscapableHandleScope scope(isolate);
732
  v8::Local<v8::Value> cbdata =
733
36
      v8impl::CreateFunctionCallbackData(env, cb, callback_data);
734
735
36
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
736
737
36
  v8::Local<v8::Context> context = env->context();
738
  v8::MaybeLocal<v8::Function> maybe_function =
739
      v8::Function::New(context,
740
                        v8impl::FunctionCallbackWrapper::Invoke,
741
36
                        cbdata);
742
36
  CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
743
744
36
  return_value = scope.Escape(maybe_function.ToLocalChecked());
745
746
36
  if (utf8name != nullptr) {
747
    v8::Local<v8::String> name_string;
748

96
    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
749
32
    return_value->SetName(name_string);
750
  }
751
752
72
  *result = v8impl::JsValueFromV8LocalValue(return_value);
753
754
72
  return GET_RETURN_STATUS(env);
755
}
756
757
7
napi_status napi_define_class(napi_env env,
758
                              const char* utf8name,
759
                              size_t length,
760
                              napi_callback constructor,
761
                              void* callback_data,
762
                              size_t property_count,
763
                              const napi_property_descriptor* properties,
764
                              napi_value* result) {
765


14
  NAPI_PREAMBLE(env);
766
7
  CHECK_ARG(env, result);
767
7
  CHECK_ARG(env, constructor);
768
769
7
  v8::Isolate* isolate = env->isolate;
770
771
7
  v8::EscapableHandleScope scope(isolate);
772
  v8::Local<v8::Value> cbdata =
773
7
      v8impl::CreateFunctionCallbackData(env, constructor, callback_data);
774
775
7
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
776
777
  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(
778
7
      isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
779
780
  v8::Local<v8::String> name_string;
781

21
  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
782
7
  tpl->SetClassName(name_string);
783
784
7
  size_t static_property_count = 0;
785
31
  for (size_t i = 0; i < property_count; i++) {
786
24
    const napi_property_descriptor* p = properties + i;
787
788
24
    if ((p->attributes & napi_static) != 0) {
789
      // Static properties are handled separately below.
790
4
      static_property_count++;
791
4
      continue;
792
    }
793
794
    v8::Local<v8::Name> property_name;
795
    napi_status status =
796
20
        v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
797
798
20
    if (status != napi_ok) {
799
      return napi_set_last_error(env, status);
800
    }
801
802
    v8::PropertyAttribute attributes =
803
20
        v8impl::V8PropertyAttributesFromDescriptor(p);
804
805
    // This code is similar to that in napi_define_properties(); the
806
    // difference is it applies to a template instead of an object.
807

20
    if (p->getter != nullptr || p->setter != nullptr) {
808
      v8::Local<v8::Value> cbdata = v8impl::CreateAccessorCallbackData(
809
9
        env, p->getter, p->setter, p->data);
810
811
9
      tpl->PrototypeTemplate()->SetAccessor(
812
        property_name,
813
        p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
814
        p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
815
        cbdata,
816
        v8::AccessControl::DEFAULT,
817

27
        attributes);
818
11
    } else if (p->method != nullptr) {
819
      v8::Local<v8::Value> cbdata =
820
5
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
821
822
5
      RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
823
824
      v8::Local<v8::FunctionTemplate> t =
825
        v8::FunctionTemplate::New(isolate,
826
          v8impl::FunctionCallbackWrapper::Invoke,
827
          cbdata,
828
5
          v8::Signature::New(isolate, tpl));
829
830
10
      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
831
    } else {
832
6
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
833
12
      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
834
    }
835
  }
836
837
7
  v8::Local<v8::Context> context = env->context();
838
  *result = v8impl::JsValueFromV8LocalValue(
839
21
      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
840
841
7
  if (static_property_count > 0) {
842
2
    std::vector<napi_property_descriptor> static_descriptors;
843
2
    static_descriptors.reserve(static_property_count);
844
845
22
    for (size_t i = 0; i < property_count; i++) {
846
20
      const napi_property_descriptor* p = properties + i;
847
20
      if ((p->attributes & napi_static) != 0) {
848
4
        static_descriptors.push_back(*p);
849
      }
850
    }
851
852
    napi_status status =
853
        napi_define_properties(env,
854
                               *result,
855
                               static_descriptors.size(),
856
2
                               static_descriptors.data());
857

2
    if (status != napi_ok) return status;
858
  }
859
860
14
  return GET_RETURN_STATUS(env);
861
}
862
863
4
napi_status napi_get_property_names(napi_env env,
864
                                    napi_value object,
865
                                    napi_value* result) {
866


8
  NAPI_PREAMBLE(env);
867
4
  CHECK_ARG(env, result);
868
869
4
  v8::Local<v8::Context> context = env->context();
870
  v8::Local<v8::Object> obj;
871

16
  CHECK_TO_OBJECT(env, context, obj, object);
872
873
4
  auto maybe_propertynames = obj->GetPropertyNames(context);
874
875
4
  CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure);
876
877
  *result = v8impl::JsValueFromV8LocalValue(
878
8
      maybe_propertynames.ToLocalChecked());
879
4
  return GET_RETURN_STATUS(env);
880
}
881
882
15
napi_status napi_set_property(napi_env env,
883
                              napi_value object,
884
                              napi_value key,
885
                              napi_value value) {
886


30
  NAPI_PREAMBLE(env);
887
15
  CHECK_ARG(env, key);
888
15
  CHECK_ARG(env, value);
889
890
15
  v8::Local<v8::Context> context = env->context();
891
  v8::Local<v8::Object> obj;
892
893

60
  CHECK_TO_OBJECT(env, context, obj, object);
894
895
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
896
15
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
897
898
15
  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
899
900
30
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
901
15
  return GET_RETURN_STATUS(env);
902
}
903
904
8
napi_status napi_has_property(napi_env env,
905
                              napi_value object,
906
                              napi_value key,
907
                              bool* result) {
908


16
  NAPI_PREAMBLE(env);
909
8
  CHECK_ARG(env, result);
910
8
  CHECK_ARG(env, key);
911
912
8
  v8::Local<v8::Context> context = env->context();
913
  v8::Local<v8::Object> obj;
914
915

32
  CHECK_TO_OBJECT(env, context, obj, object);
916
917
8
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
918
8
  v8::Maybe<bool> has_maybe = obj->Has(context, k);
919
920
8
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
921
922
16
  *result = has_maybe.FromMaybe(false);
923
8
  return GET_RETURN_STATUS(env);
924
}
925
926
24
napi_status napi_get_property(napi_env env,
927
                              napi_value object,
928
                              napi_value key,
929
                              napi_value* result) {
930


48
  NAPI_PREAMBLE(env);
931
24
  CHECK_ARG(env, key);
932
24
  CHECK_ARG(env, result);
933
934
24
  v8::Local<v8::Context> context = env->context();
935
24
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
936
  v8::Local<v8::Object> obj;
937
938

96
  CHECK_TO_OBJECT(env, context, obj, object);
939
940
24
  auto get_maybe = obj->Get(context, k);
941
942
24
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
943
944
24
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
945
24
  *result = v8impl::JsValueFromV8LocalValue(val);
946
24
  return GET_RETURN_STATUS(env);
947
}
948
949
5
napi_status napi_delete_property(napi_env env,
950
                                 napi_value object,
951
                                 napi_value key,
952
                                 bool* result) {
953


10
  NAPI_PREAMBLE(env);
954
5
  CHECK_ARG(env, key);
955
956
5
  v8::Local<v8::Context> context = env->context();
957
5
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
958
  v8::Local<v8::Object> obj;
959
960

20
  CHECK_TO_OBJECT(env, context, obj, object);
961
5
  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
962
5
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
963
964
5
  if (result != nullptr)
965
10
    *result = delete_maybe.FromMaybe(false);
966
967
5
  return GET_RETURN_STATUS(env);
968
}
969
970
15
napi_status napi_has_own_property(napi_env env,
971
                                  napi_value object,
972
                                  napi_value key,
973
                                  bool* result) {
974


30
  NAPI_PREAMBLE(env);
975
15
  CHECK_ARG(env, key);
976
977
15
  v8::Local<v8::Context> context = env->context();
978
  v8::Local<v8::Object> obj;
979
980

60
  CHECK_TO_OBJECT(env, context, obj, object);
981
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
982
24
  RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected);
983
6
  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
984
6
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
985
12
  *result = has_maybe.FromMaybe(false);
986
987
6
  return GET_RETURN_STATUS(env);
988
}
989
990
44
napi_status napi_set_named_property(napi_env env,
991
                                    napi_value object,
992
                                    const char* utf8name,
993
                                    napi_value value) {
994


88
  NAPI_PREAMBLE(env);
995
44
  CHECK_ARG(env, value);
996
997
44
  v8::Local<v8::Context> context = env->context();
998
  v8::Local<v8::Object> obj;
999
1000

176
  CHECK_TO_OBJECT(env, context, obj, object);
1001
1002
  v8::Local<v8::Name> key;
1003
132
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1004
1005
44
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1006
1007
44
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1008
1009
88
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1010
44
  return GET_RETURN_STATUS(env);
1011
}
1012
1013
3
napi_status napi_has_named_property(napi_env env,
1014
                                    napi_value object,
1015
                                    const char* utf8name,
1016
                                    bool* result) {
1017


6
  NAPI_PREAMBLE(env);
1018
3
  CHECK_ARG(env, result);
1019
1020
3
  v8::Local<v8::Context> context = env->context();
1021
  v8::Local<v8::Object> obj;
1022
1023

12
  CHECK_TO_OBJECT(env, context, obj, object);
1024
1025
  v8::Local<v8::Name> key;
1026
9
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1027
1028
3
  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1029
1030
3
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1031
1032
6
  *result = has_maybe.FromMaybe(false);
1033
3
  return GET_RETURN_STATUS(env);
1034
}
1035
1036
napi_status napi_get_named_property(napi_env env,
1037
                                    napi_value object,
1038
                                    const char* utf8name,
1039
                                    napi_value* result) {
1040
  NAPI_PREAMBLE(env);
1041
  CHECK_ARG(env, result);
1042
1043
  v8::Local<v8::Context> context = env->context();
1044
1045
  v8::Local<v8::Name> key;
1046
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1047
1048
  v8::Local<v8::Object> obj;
1049
1050
  CHECK_TO_OBJECT(env, context, obj, object);
1051
1052
  auto get_maybe = obj->Get(context, key);
1053
1054
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1055
1056
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1057
  *result = v8impl::JsValueFromV8LocalValue(val);
1058
  return GET_RETURN_STATUS(env);
1059
}
1060
1061
11
napi_status napi_set_element(napi_env env,
1062
                             napi_value object,
1063
                             uint32_t index,
1064
                             napi_value value) {
1065


22
  NAPI_PREAMBLE(env);
1066
11
  CHECK_ARG(env, value);
1067
1068
11
  v8::Local<v8::Context> context = env->context();
1069
  v8::Local<v8::Object> obj;
1070
1071

44
  CHECK_TO_OBJECT(env, context, obj, object);
1072
1073
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1074
11
  auto set_maybe = obj->Set(context, index, val);
1075
1076
22
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1077
1078
11
  return GET_RETURN_STATUS(env);
1079
}
1080
1081
2
napi_status napi_has_element(napi_env env,
1082
                             napi_value object,
1083
                             uint32_t index,
1084
                             bool* result) {
1085


4
  NAPI_PREAMBLE(env);
1086
2
  CHECK_ARG(env, result);
1087
1088
2
  v8::Local<v8::Context> context = env->context();
1089
  v8::Local<v8::Object> obj;
1090
1091

8
  CHECK_TO_OBJECT(env, context, obj, object);
1092
1093
2
  v8::Maybe<bool> has_maybe = obj->Has(context, index);
1094
1095
2
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1096
1097
4
  *result = has_maybe.FromMaybe(false);
1098
2
  return GET_RETURN_STATUS(env);
1099
}
1100
1101
27
napi_status napi_get_element(napi_env env,
1102
                             napi_value object,
1103
                             uint32_t index,
1104
                             napi_value* result) {
1105


54
  NAPI_PREAMBLE(env);
1106
27
  CHECK_ARG(env, result);
1107
1108
27
  v8::Local<v8::Context> context = env->context();
1109
  v8::Local<v8::Object> obj;
1110
1111

108
  CHECK_TO_OBJECT(env, context, obj, object);
1112
1113
27
  auto get_maybe = obj->Get(context, index);
1114
1115
27
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1116
1117
54
  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
1118
27
  return GET_RETURN_STATUS(env);
1119
}
1120
1121
1
napi_status napi_delete_element(napi_env env,
1122
                                napi_value object,
1123
                                uint32_t index,
1124
                                bool* result) {
1125


2
  NAPI_PREAMBLE(env);
1126
1127
1
  v8::Local<v8::Context> context = env->context();
1128
  v8::Local<v8::Object> obj;
1129
1130

4
  CHECK_TO_OBJECT(env, context, obj, object);
1131
1
  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
1132
1
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1133
1134
1
  if (result != nullptr)
1135
2
    *result = delete_maybe.FromMaybe(false);
1136
1137
1
  return GET_RETURN_STATUS(env);
1138
}
1139
1140
53
napi_status napi_define_properties(napi_env env,
1141
                                   napi_value object,
1142
                                   size_t property_count,
1143
                                   const napi_property_descriptor* properties) {
1144


106
  NAPI_PREAMBLE(env);
1145
53
  if (property_count > 0) {
1146
53
    CHECK_ARG(env, properties);
1147
  }
1148
1149
53
  v8::Local<v8::Context> context = env->context();
1150
1151
  v8::Local<v8::Object> obj;
1152

212
  CHECK_TO_OBJECT(env, context, obj, object);
1153
1154
676
  for (size_t i = 0; i < property_count; i++) {
1155
285
    const napi_property_descriptor* p = &properties[i];
1156
1157
    v8::Local<v8::Name> property_name;
1158
    napi_status status =
1159
285
        v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
1160
1161
285
    if (status != napi_ok) {
1162
      return napi_set_last_error(env, status);
1163
    }
1164
1165
    v8::PropertyAttribute attributes =
1166
285
        v8impl::V8PropertyAttributesFromDescriptor(p);
1167
1168

285
    if (p->getter != nullptr || p->setter != nullptr) {
1169
      v8::Local<v8::Value> cbdata = v8impl::CreateAccessorCallbackData(
1170
        env,
1171
        p->getter,
1172
        p->setter,
1173
9
        p->data);
1174
1175
      auto set_maybe = obj->SetAccessor(
1176
        context,
1177
        property_name,
1178
        p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
1179
        p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
1180
        cbdata,
1181
        v8::AccessControl::DEFAULT,
1182

18
        attributes);
1183
1184
18
      if (!set_maybe.FromMaybe(false)) {
1185
        return napi_set_last_error(env, napi_invalid_arg);
1186
9
      }
1187
276
    } else if (p->method != nullptr) {
1188
      v8::Local<v8::Value> cbdata =
1189
263
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
1190
1191
263
      CHECK_MAYBE_EMPTY(env, cbdata, napi_generic_failure);
1192
1193
      v8::MaybeLocal<v8::Function> maybe_fn =
1194
          v8::Function::New(context,
1195
                            v8impl::FunctionCallbackWrapper::Invoke,
1196
263
                            cbdata);
1197
1198
263
      CHECK_MAYBE_EMPTY(env, maybe_fn, napi_generic_failure);
1199
1200
      auto define_maybe = obj->DefineOwnProperty(
1201
263
        context, property_name, maybe_fn.ToLocalChecked(), attributes);
1202
1203
526
      if (!define_maybe.FromMaybe(false)) {
1204
        return napi_set_last_error(env, napi_generic_failure);
1205
      }
1206
    } else {
1207
13
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1208
1209
      auto define_maybe =
1210
13
          obj->DefineOwnProperty(context, property_name, value, attributes);
1211
1212
26
      if (!define_maybe.FromMaybe(false)) {
1213
        return napi_set_last_error(env, napi_invalid_arg);
1214
      }
1215
    }
1216
  }
1217
1218
53
  return GET_RETURN_STATUS(env);
1219
}
1220
1221
11
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1222
11
  CHECK_ENV(env);
1223
11
  CHECK_ARG(env, value);
1224
11
  CHECK_ARG(env, result);
1225
1226
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1227
1228
22
  *result = val->IsArray();
1229
11
  return napi_clear_last_error(env);
1230
}
1231
1232
13
napi_status napi_get_array_length(napi_env env,
1233
                                  napi_value value,
1234
                                  uint32_t* result) {
1235


26
  NAPI_PREAMBLE(env);
1236
13
  CHECK_ARG(env, value);
1237
13
  CHECK_ARG(env, result);
1238
1239
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1240
13
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1241
1242
13
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1243
26
  *result = arr->Length();
1244
1245
13
  return GET_RETURN_STATUS(env);
1246
}
1247
1248
9
napi_status napi_strict_equals(napi_env env,
1249
                               napi_value lhs,
1250
                               napi_value rhs,
1251
                               bool* result) {
1252


18
  NAPI_PREAMBLE(env);
1253
9
  CHECK_ARG(env, lhs);
1254
9
  CHECK_ARG(env, rhs);
1255
9
  CHECK_ARG(env, result);
1256
1257
9
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1258
9
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1259
1260
18
  *result = a->StrictEquals(b);
1261
9
  return GET_RETURN_STATUS(env);
1262
}
1263
1264
4
napi_status napi_get_prototype(napi_env env,
1265
                               napi_value object,
1266
                               napi_value* result) {
1267


8
  NAPI_PREAMBLE(env);
1268
4
  CHECK_ARG(env, result);
1269
1270
4
  v8::Local<v8::Context> context = env->context();
1271
1272
  v8::Local<v8::Object> obj;
1273

16
  CHECK_TO_OBJECT(env, context, obj, object);
1274
1275
4
  v8::Local<v8::Value> val = obj->GetPrototype();
1276
4
  *result = v8impl::JsValueFromV8LocalValue(val);
1277
4
  return GET_RETURN_STATUS(env);
1278
}
1279
1280
8
napi_status napi_create_object(napi_env env, napi_value* result) {
1281
8
  CHECK_ENV(env);
1282
8
  CHECK_ARG(env, result);
1283
1284
  *result = v8impl::JsValueFromV8LocalValue(
1285
16
      v8::Object::New(env->isolate));
1286
1287
8
  return napi_clear_last_error(env);
1288
}
1289
1290
1
napi_status napi_create_array(napi_env env, napi_value* result) {
1291
1
  CHECK_ENV(env);
1292
1
  CHECK_ARG(env, result);
1293
1294
  *result = v8impl::JsValueFromV8LocalValue(
1295
2
      v8::Array::New(env->isolate));
1296
1297
1
  return napi_clear_last_error(env);
1298
}
1299
1300
4
napi_status napi_create_array_with_length(napi_env env,
1301
                                          size_t length,
1302
                                          napi_value* result) {
1303
4
  CHECK_ENV(env);
1304
4
  CHECK_ARG(env, result);
1305
1306
  *result = v8impl::JsValueFromV8LocalValue(
1307
8
      v8::Array::New(env->isolate, length));
1308
1309
4
  return napi_clear_last_error(env);
1310
}
1311
1312
11
napi_status napi_create_string_latin1(napi_env env,
1313
                                      const char* str,
1314
                                      size_t length,
1315
                                      napi_value* result) {
1316
11
  CHECK_ENV(env);
1317
11
  CHECK_ARG(env, result);
1318
1319
11
  auto isolate = env->isolate;
1320
  auto str_maybe =
1321
      v8::String::NewFromOneByte(isolate,
1322
                                 reinterpret_cast<const uint8_t*>(str),
1323
                                 v8::NewStringType::kInternalized,
1324
11
                                 length);
1325
11
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1326
1327
22
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1328
11
  return napi_clear_last_error(env);
1329
}
1330
1331
574
napi_status napi_create_string_utf8(napi_env env,
1332
                                    const char* str,
1333
                                    size_t length,
1334
                                    napi_value* result) {
1335
574
  CHECK_ENV(env);
1336
574
  CHECK_ARG(env, result);
1337
1338
  v8::Local<v8::String> s;
1339

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


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

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


1284
  NAPI_PREAMBLE(env);
1734
640
  CHECK_ARG(env, recv);
1735
640
  if (argc > 0) {
1736
594
    CHECK_ARG(env, argv);
1737
  }
1738
1739
640
  v8::Local<v8::Context> context = env->context();
1740
1741
640
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1742
1743
  v8::Local<v8::Function> v8func;
1744

1920
  CHECK_TO_FUNCTION(env, v8func, func);
1745
1746
  auto maybe = v8func->Call(context, v8recv, argc,
1747
1280
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1748
1749
640
  if (try_catch.HasCaught()) {
1750
6
    return napi_set_last_error(env, napi_pending_exception);
1751
  } else {
1752
634
    if (result != nullptr) {
1753
11
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1754
11
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1755
    }
1756
634
    return napi_clear_last_error(env);
1757
640
  }
1758
}
1759
1760
14
napi_status napi_get_global(napi_env env, napi_value* result) {
1761
14
  CHECK_ENV(env);
1762
14
  CHECK_ARG(env, result);
1763
1764
42
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1765
1766
14
  return napi_clear_last_error(env);
1767
}
1768
1769
11
napi_status napi_throw(napi_env env, napi_value error) {
1770


22
  NAPI_PREAMBLE(env);
1771
11
  CHECK_ARG(env, error);
1772
1773
11
  v8::Isolate* isolate = env->isolate;
1774
1775
11
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1776
  // any VM calls after this point and before returning
1777
  // to the javascript invoker will fail
1778
11
  return napi_clear_last_error(env);
1779
}
1780
1781
76
napi_status napi_throw_error(napi_env env,
1782
                             const char* code,
1783
                             const char* msg) {
1784


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


180
  NAPI_PREAMBLE(env);
1804
1805
90
  v8::Isolate* isolate = env->isolate;
1806
  v8::Local<v8::String> str;
1807
270
  CHECK_NEW_FROM_UTF8(env, str, msg);
1808
1809
90
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1810
90
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1811
90
  if (status != napi_ok) return status;
1812
1813
90
  isolate->ThrowException(error_obj);
1814
  // any VM calls after this point and before returning
1815
  // to the javascript invoker will fail
1816
90
  return napi_clear_last_error(env);
1817
}
1818
1819
23
napi_status napi_throw_range_error(napi_env env,
1820
                                   const char* code,
1821
                                   const char* msg) {
1822


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

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


30
  NAPI_PREAMBLE(env);
2152
15
  CHECK_ARG(env, value);
2153
15
  CHECK_ARG(env, result);
2154
2155
15
  v8::Local<v8::Context> context = env->context();
2156
  v8::Local<v8::Object> obj;
2157

60
  CHECK_TO_OBJECT(env, context, obj, value);
2158
2159
30
  *result = v8impl::JsValueFromV8LocalValue(obj);
2160
15
  return GET_RETURN_STATUS(env);
2161
}
2162
2163
14
napi_status napi_coerce_to_bool(napi_env env,
2164
                                napi_value value,
2165
                                napi_value* result) {
2166


28
  NAPI_PREAMBLE(env);
2167
14
  CHECK_ARG(env, value);
2168
14
  CHECK_ARG(env, result);
2169
2170
14
  v8::Isolate* isolate = env->isolate;
2171
  v8::Local<v8::Boolean> b =
2172
28
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2173
28
  *result = v8impl::JsValueFromV8LocalValue(b);
2174
14
  return GET_RETURN_STATUS(env);
2175
}
2176
2177
15
napi_status napi_coerce_to_number(napi_env env,
2178
                                  napi_value value,
2179
                                  napi_value* result) {
2180


30
  NAPI_PREAMBLE(env);
2181
15
  CHECK_ARG(env, value);
2182
15
  CHECK_ARG(env, result);
2183
2184
15
  v8::Local<v8::Context> context = env->context();
2185
  v8::Local<v8::Number> num;
2186
2187

60
  CHECK_TO_NUMBER(env, context, num, value);
2188
2189
28
  *result = v8impl::JsValueFromV8LocalValue(num);
2190
14
  return GET_RETURN_STATUS(env);
2191
}
2192
2193
14
napi_status napi_coerce_to_string(napi_env env,
2194
                                  napi_value value,
2195
                                  napi_value* result) {
2196


28
  NAPI_PREAMBLE(env);
2197
14
  CHECK_ARG(env, value);
2198
14
  CHECK_ARG(env, result);
2199
2200
14
  v8::Local<v8::Context> context = env->context();
2201
  v8::Local<v8::String> str;
2202
2203

56
  CHECK_TO_STRING(env, context, str, value);
2204
2205
26
  *result = v8impl::JsValueFromV8LocalValue(str);
2206
13
  return GET_RETURN_STATUS(env);
2207
}
2208
2209
1019
napi_status napi_wrap(napi_env env,
2210
                      napi_value js_object,
2211
                      void* native_object,
2212
                      napi_finalize finalize_cb,
2213
                      void* finalize_hint,
2214
                      napi_ref* result) {
2215
  return v8impl::Wrap<v8impl::retrievable>(env,
2216
                                           js_object,
2217
                                           native_object,
2218
                                           finalize_cb,
2219
                                           finalize_hint,
2220
1019
                                           result);
2221
}
2222
2223
24
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2224
24
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2225
}
2226
2227
3
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2228
3
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2229
}
2230
2231
7
napi_status napi_create_external(napi_env env,
2232
                                 void* data,
2233
                                 napi_finalize finalize_cb,
2234
                                 void* finalize_hint,
2235
                                 napi_value* result) {
2236


14
  NAPI_PREAMBLE(env);
2237
7
  CHECK_ARG(env, result);
2238
2239
7
  v8::Isolate* isolate = env->isolate;
2240
2241
7
  v8::Local<v8::Value> external_value = v8::External::New(isolate, data);
2242
2243
  // The Reference object will delete itself after invoking the finalizer
2244
  // callback.
2245
  v8impl::Reference::New(env,
2246
      external_value,
2247
      0,
2248
      true,
2249
      finalize_cb,
2250
      data,
2251
7
      finalize_hint);
2252
2253
7
  *result = v8impl::JsValueFromV8LocalValue(external_value);
2254
2255
7
  return napi_clear_last_error(env);
2256
}
2257
2258
3
napi_status napi_get_value_external(napi_env env,
2259
                                    napi_value value,
2260
                                    void** result) {
2261
3
  CHECK_ENV(env);
2262
3
  CHECK_ARG(env, value);
2263
3
  CHECK_ARG(env, result);
2264
2265
3
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2266
3
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
2267
2268
3
  v8::Local<v8::External> external_value = val.As<v8::External>();
2269
6
  *result = external_value->Value();
2270
2271
3
  return napi_clear_last_error(env);
2272
}
2273
2274
// Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
2275
1528
napi_status napi_create_reference(napi_env env,
2276
                                  napi_value value,
2277
                                  uint32_t initial_refcount,
2278
                                  napi_ref* result) {
2279
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2280
  // JS exceptions.
2281
1528
  CHECK_ENV(env);
2282
1528
  CHECK_ARG(env, value);
2283
1528
  CHECK_ARG(env, result);
2284
2285
1528
  v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(value);
2286
2287

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


14
  NAPI_PREAMBLE(env);
2458
7
  CHECK_ARG(env, constructor);
2459
7
  if (argc > 0) {
2460
7
    CHECK_ARG(env, argv);
2461
  }
2462
7
  CHECK_ARG(env, result);
2463
2464
7
  v8::Local<v8::Context> context = env->context();
2465
2466
  v8::Local<v8::Function> ctor;
2467

21
  CHECK_TO_FUNCTION(env, ctor, constructor);
2468
2469
  auto maybe = ctor->NewInstance(context, argc,
2470
14
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2471
2472
7
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2473
2474
14
  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2475
7
  return GET_RETURN_STATUS(env);
2476
}
2477
2478
2278
napi_status napi_instanceof(napi_env env,
2479
                            napi_value object,
2480
                            napi_value constructor,
2481
                            bool* result) {
2482


4556
  NAPI_PREAMBLE(env);
2483
2278
  CHECK_ARG(env, object);
2484
2278
  CHECK_ARG(env, result);
2485
2486
2278
  *result = false;
2487
2488
  v8::Local<v8::Object> ctor;
2489
2278
  v8::Local<v8::Context> context = env->context();
2490
2491

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


4
  NAPI_PREAMBLE(env);
2555
2
  CHECK_ARG(env, result);
2556
2557
2
  v8::Isolate* isolate = env->isolate;
2558
  v8::Local<v8::ArrayBuffer> buffer =
2559
2
      v8::ArrayBuffer::New(isolate, byte_length);
2560
2561
  // Optionally return a pointer to the buffer's data, to avoid another call to
2562
  // retrieve it.
2563
2
  if (data != nullptr) {
2564
2
    *data = buffer->GetContents().Data();
2565
  }
2566
2567
4
  *result = v8impl::JsValueFromV8LocalValue(buffer);
2568
2
  return GET_RETURN_STATUS(env);
2569
}
2570
2571
1
napi_status napi_create_external_arraybuffer(napi_env env,
2572
                                             void* external_data,
2573
                                             size_t byte_length,
2574
                                             napi_finalize finalize_cb,
2575
                                             void* finalize_hint,
2576
                                             napi_value* result) {
2577


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


66
  NAPI_PREAMBLE(env);
2642
33
  CHECK_ARG(env, arraybuffer);
2643
33
  CHECK_ARG(env, result);
2644
2645
33
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2646
33
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2647
2648
33
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2649
  v8::Local<v8::TypedArray> typedArray;
2650
2651



33
  switch (type) {
2652
    case napi_int8_array:
2653
8
      CREATE_TYPED_ARRAY(
2654
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2655
2
      break;
2656
    case napi_uint8_array:
2657
8
      CREATE_TYPED_ARRAY(
2658
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2659
2
      break;
2660
    case napi_uint8_clamped_array:
2661
5
      CREATE_TYPED_ARRAY(
2662
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2663
1
      break;
2664
    case napi_int16_array:
2665

6
      CREATE_TYPED_ARRAY(
2666
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2667
1
      break;
2668
    case napi_uint16_array:
2669

6
      CREATE_TYPED_ARRAY(
2670
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2671
1
      break;
2672
    case napi_int32_array:
2673

6
      CREATE_TYPED_ARRAY(
2674
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2675
1
      break;
2676
    case napi_uint32_array:
2677

6
      CREATE_TYPED_ARRAY(
2678
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2679
1
      break;
2680
    case napi_float32_array:
2681

6
      CREATE_TYPED_ARRAY(
2682
          env, Float32Array, 4, buffer, byte_offset, length, typedArray);
2683
1
      break;
2684
    case napi_float64_array:
2685

9
      CREATE_TYPED_ARRAY(
2686
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2687
2
      break;
2688
    case napi_bigint64_array:
2689

6
      CREATE_TYPED_ARRAY(
2690
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2691
1
      break;
2692
    case napi_biguint64_array:
2693

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


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


10
  NAPI_PREAMBLE(env);
2851
5
  CHECK_ARG(env, deferred);
2852
5
  CHECK_ARG(env, promise);
2853
2854
5
  auto maybe = v8::Promise::Resolver::New(env->context());
2855
5
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2856
2857
5
  auto v8_resolver = maybe.ToLocalChecked();
2858
10
  auto v8_deferred = new v8impl::Persistent<v8::Value>();
2859
5
  v8_deferred->Reset(env->isolate, v8_resolver);
2860
2861
5
  *deferred = v8impl::JsDeferredFromNodePersistent(v8_deferred);
2862
15
  *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise());
2863
5
  return GET_RETURN_STATUS(env);
2864
}
2865
2866
4
napi_status napi_resolve_deferred(napi_env env,
2867
                                  napi_deferred deferred,
2868
                                  napi_value resolution) {
2869
4
  return v8impl::ConcludeDeferred(env, deferred, resolution, true);
2870
}
2871
2872
1
napi_status napi_reject_deferred(napi_env env,
2873
                                 napi_deferred deferred,
2874
                                 napi_value resolution) {
2875
1
  return v8impl::ConcludeDeferred(env, deferred, resolution, false);
2876
}
2877
2878
7
napi_status napi_is_promise(napi_env env,
2879
                            napi_value promise,
2880
                            bool* is_promise) {
2881
7
  CHECK_ENV(env);
2882
7
  CHECK_ARG(env, promise);
2883
7
  CHECK_ARG(env, is_promise);
2884
2885
14
  *is_promise = v8impl::V8LocalValueFromJsValue(promise)->IsPromise();
2886
2887
7
  return napi_clear_last_error(env);
2888
}
2889
2890
2
napi_status napi_run_script(napi_env env,
2891
                            napi_value script,
2892
                            napi_value* result) {
2893


4
  NAPI_PREAMBLE(env);
2894
2
  CHECK_ARG(env, script);
2895
2
  CHECK_ARG(env, result);
2896
2897
2
  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
2898
2899
4
  if (!v8_script->IsString()) {
2900
1
    return napi_set_last_error(env, napi_string_expected);
2901
  }
2902
2903
1
  v8::Local<v8::Context> context = env->context();
2904
2905
  auto maybe_script = v8::Script::Compile(context,
2906
1
      v8::Local<v8::String>::Cast(v8_script));
2907
1
  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
2908
2909
  auto script_result =
2910
2
      maybe_script.ToLocalChecked()->Run(context);
2911
1
  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
2912
2913
2
  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
2914
1
  return GET_RETURN_STATUS(env);
2915
}
2916
2917
3
napi_status napi_add_finalizer(napi_env env,
2918
                               napi_value js_object,
2919
                               void* native_object,
2920
                               napi_finalize finalize_cb,
2921
                               void* finalize_hint,
2922
                               napi_ref* result) {
2923
  return v8impl::Wrap<v8impl::anonymous>(env,
2924
                                         js_object,
2925
                                         native_object,
2926
                                         finalize_cb,
2927
                                         finalize_hint,
2928
3
                                         result);
2929
}
2930
2931
1
napi_status napi_adjust_external_memory(napi_env env,
2932
                                        int64_t change_in_bytes,
2933
                                        int64_t* adjusted_value) {
2934
1
  CHECK_ENV(env);
2935
1
  CHECK_ARG(env, adjusted_value);
2936
2937
  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
2938
2
      change_in_bytes);
2939
2940
1
  return napi_clear_last_error(env);
2941
}