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: 1235 1277 96.7 %
Date: 2019-02-13 22:28:58 Branches: 757 1294 58.5 %

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

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

10
  NAPI_PREAMBLE(env);
164
5
  CHECK_ARG(env, result);
165
166
5
  v8::Local<v8::Context> context = env->isolate->GetCurrentContext();
167
  v8impl::Persistent<v8::Value>* deferred_ref =
168
5
      NodePersistentFromJsDeferred(deferred);
169
  v8::Local<v8::Value> v8_deferred =
170
10
      v8::Local<v8::Value>::New(env->isolate, *deferred_ref);
171
172
5
  auto v8_resolver = v8::Local<v8::Promise::Resolver>::Cast(v8_deferred);
173
174
  v8::Maybe<bool> success = is_resolved ?
175
8
      v8_resolver->Resolve(context, v8impl::V8LocalValueFromJsValue(result)) :
176
10
      v8_resolver->Reject(context, v8impl::V8LocalValueFromJsValue(result));
177
178
10
  delete deferred_ref;
179
180
10
  RETURN_STATUS_IF_FALSE(env, success.FromMaybe(false), napi_generic_failure);
181
182
5
  return GET_RETURN_STATUS(env);
183
}
184
185
// Wrapper around v8impl::Persistent that implements reference counting.
186
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

2031
      NAPI_CALL_INTO_MODULE_THROW(env,
307
        reference->_finalize_callback(
308
            reference->_env,
309
            reference->_finalize_data,
310
            reference->_finalize_hint));
311
    }
312
313
    // this is safe because if a request to delete the reference
314
    // is made in the finalize_callback it will defer deletion
315
    // to this block and set _delete_self to true
316
2019
    if (reference->_delete_self) {
317
2016
      Delete(reference);
318
    } else {
319
3
      reference->_finalize_ran = true;
320
    }
321
2019
  }
322
323
  v8impl::Persistent<v8::Value> _persistent;
324
  uint32_t _refcount;
325
  bool _delete_self;
326
};
327
328
enum UnwrapAction {
329
  KeepWrap,
330
  RemoveWrap
331
};
332
333
27
inline static napi_status Unwrap(napi_env env,
334
                                 napi_value js_object,
335
                                 void** result,
336
                                 UnwrapAction action) {
337

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




10215
    NAPI_CALL_INTO_MODULE_THROW(env, result = cb(env, cbinfo_wrapper));
452
453

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


2044
  NAPI_PREAMBLE(env);
626

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



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

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

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

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

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

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

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

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

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

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

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

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