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: 1387 1418 97.8 %
Date: 2021-04-09 04:13:47 Branches: 1062 1694 62.7 %

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

1302
    CHECK_NEW_FROM_UTF8(env, *result, p->utf8name);
69
  } else {
70
    v8::Local<v8::Value> property_value =
71
2
      v8impl::V8LocalValueFromJsValue(p->name);
72
73
2
    RETURN_STATUS_IF_FALSE(env, property_value->IsName(), napi_name_expected);
74
2
    *result = property_value.As<v8::Name>();
75
  }
76
77
436
  return napi_ok;
78
}
79
80
// convert from n-api property attributes to v8::PropertyAttribute
81
21
inline static v8::PropertyAttribute V8PropertyAttributesFromDescriptor(
82
    const napi_property_descriptor* descriptor) {
83
21
  unsigned int attribute_flags = v8::PropertyAttribute::None;
84
85
  // The napi_writable attribute is ignored for accessor descriptors, but
86
  // V8 would throw `TypeError`s on assignment with nonexistence of a setter.
87

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


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

8571
    if ((reference->RefCount() != 0) ||
246

4052
        (reference->_delete_self) ||
247
1018
        (reference->_finalize_ran)) {
248
3022
      delete reference;
249
    } else {
250
      // defer until finalizer runs as
251
      // it may alread be queued
252
12
      reference->_delete_self = true;
253
    }
254
3034
  }
255
256
3
  inline uint32_t Ref() {
257
3
    return ++_refcount;
258
  }
259
260
3
  inline uint32_t Unref() {
261
3
    if (_refcount == 0) {
262
        return 0;
263
    }
264
3
    return --_refcount;
265
  }
266
267
6531
  inline uint32_t RefCount() {
268
6531
    return _refcount;
269
  }
270
271
 protected:
272
2488
  inline void Finalize(bool is_env_teardown = false) override {
273
    // In addition to being called during environment teardown, this method is
274
    // also the entry point for the garbage collector. During environment
275
    // teardown we have to remove the garbage collector's reference to this
276
    // method so that, if, as part of the user's callback, JS gets executed,
277
    // resulting in a garbage collection pass, this method is not re-entered as
278
    // part of that pass, because that'll cause a double free (as seen in
279
    // https://github.com/nodejs/node/issues/37236).
280
    //
281
    // Since this class does not have access to the V8 persistent reference,
282
    // this method is overridden in the `Reference` class below. Therein the
283
    // weak callback is removed, ensuring that the garbage collector does not
284
    // re-enter this method, and the method chains up to continue the process of
285
    // environment-teardown-induced finalization.
286
287
    // During environment teardown we have to convert a strong reference to
288
    // a weak reference to force the deferring behavior if the user's finalizer
289
    // happens to delete this reference so that the code in this function that
290
    // follows the call to the user's finalizer may safely access variables from
291
    // this instance.
292

2488
    if (is_env_teardown && RefCount() > 0) _refcount = 0;
293
294
2488
    if (_finalize_callback != nullptr) {
295
      // This ensures that we never call the finalizer twice.
296
1470
      napi_finalize fini = _finalize_callback;
297
1470
      _finalize_callback = nullptr;
298
1470
      _env->CallFinalizer(fini, _finalize_data, _finalize_hint);
299
    }
300
301
    // this is safe because if a request to delete the reference
302
    // is made in the finalize_callback it will defer deletion
303
    // to this block and set _delete_self to true
304

2488
    if (_delete_self || is_env_teardown) {
305
1482
      Delete(this);
306
    } else {
307
1006
      _finalize_ran = true;
308
    }
309
2488
  }
310
311
 private:
312
  uint32_t _refcount;
313
  bool _delete_self;
314
};
315
316
9045
class Reference : public RefBase {
317
 protected:
318
  template <typename... Args>
319
3023
  Reference(napi_env env,
320
            v8::Local<v8::Value> value,
321
            Args&&... args)
322
15115
      : RefBase(env, std::forward<Args>(args)...),
323
15115
            _persistent(env->isolate, value) {
324
3023
    if (RefCount() == 0) {
325
2485
      _persistent.SetWeak(
326
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
327
    }
328
3023
  }
329
330
 public:
331
3023
  static inline Reference* New(napi_env env,
332
                             v8::Local<v8::Value> value,
333
                             uint32_t initial_refcount,
334
                             bool delete_self,
335
                             napi_finalize finalize_callback = nullptr,
336
                             void* finalize_data = nullptr,
337
                             void* finalize_hint = nullptr) {
338
    return new Reference(env,
339
                         value,
340
                         initial_refcount,
341
                         delete_self,
342
                         finalize_callback,
343
                         finalize_data,
344
3023
                         finalize_hint);
345
  }
346
347
3
  inline uint32_t Ref() {
348
3
    uint32_t refcount = RefBase::Ref();
349
3
    if (refcount == 1) {
350
2
      _persistent.ClearWeak();
351
    }
352
3
    return refcount;
353
  }
354
355
3
  inline uint32_t Unref() {
356
3
    uint32_t old_refcount = RefCount();
357
3
    uint32_t refcount = RefBase::Unref();
358

3
    if (old_refcount == 1 && refcount == 0) {
359
2
      _persistent.SetWeak(
360
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
361
    }
362
3
    return refcount;
363
  }
364
365
1550
  inline v8::Local<v8::Value> Get() {
366
3100
    if (_persistent.IsEmpty()) {
367
1002
      return v8::Local<v8::Value>();
368
    } else {
369
1096
      return v8::Local<v8::Value>::New(_env->isolate, _persistent);
370
    }
371
  }
372
373
 protected:
374
2481
  inline void Finalize(bool is_env_teardown = false) override {
375
    // During env teardown, `~napi_env()` alone is responsible for finalizing.
376
    // Thus, we don't want any stray gc passes to trigger a second call to
377
    // `Finalize()`, so let's reset the persistent here if nothing is
378
    // keeping it alive.
379

2942
    if (is_env_teardown && _persistent.IsWeak()) {
380
450
      _persistent.ClearWeak();
381
    }
382
383
    // Chain up to perform the rest of the finalization.
384
2481
    RefBase::Finalize(is_env_teardown);
385
2481
  }
386
387
 private:
388
  // The N-API finalizer callback may make calls into the engine. V8's heap is
389
  // not in a consistent state during the weak callback, and therefore it does
390
  // not support calls back into it. However, it provides a mechanism for adding
391
  // a finalizer which may make calls back into the engine by allowing us to
392
  // attach such a second-pass finalizer from the first pass finalizer. Thus,
393
  // we do that here to ensure that the N-API finalizer callback is free to call
394
  // into the engine.
395
2020
  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
396
2020
    Reference* reference = data.GetParameter();
397
398
    // The reference must be reset during the first pass.
399
2020
    reference->_persistent.Reset();
400
401
2020
    data.SetSecondPassCallback(SecondPassCallback);
402
2020
  }
403
404
2020
  static void SecondPassCallback(const v8::WeakCallbackInfo<Reference>& data) {
405
2020
    data.GetParameter()->Finalize();
406
2020
  }
407
408
  v8impl::Persistent<v8::Value> _persistent;
409
};
410
411
enum UnwrapAction {
412
  KeepWrap,
413
  RemoveWrap
414
};
415
416
35
inline static napi_status Unwrap(napi_env env,
417
                                 napi_value js_object,
418
                                 void** result,
419
                                 UnwrapAction action) {
420


105
  NAPI_PREAMBLE(env);
421
35
  CHECK_ARG(env, js_object);
422
35
  if (action == KeepWrap) {
423
27
    CHECK_ARG(env, result);
424
  }
425
426
35
  v8::Local<v8::Context> context = env->context();
427
428
35
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
429
35
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
430
35
  v8::Local<v8::Object> obj = value.As<v8::Object>();
431
432
105
  auto val = obj->GetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
433
35
      .ToLocalChecked();
434
35
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
435
  Reference* reference =
436
70
      static_cast<v8impl::Reference*>(val.As<v8::External>()->Value());
437
438
35
  if (result) {
439
35
    *result = reference->Data();
440
  }
441
442
35
  if (action == RemoveWrap) {
443
24
    CHECK(obj->DeletePrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
444
        .FromJust());
445
8
    Reference::Delete(reference);
446
  }
447
448
35
  return GET_RETURN_STATUS(env);
449
}
450
451
//=== Function napi_callback wrapper =================================
452
453
// Use this data structure to associate callback data with each N-API function
454
// exposed to JavaScript. The structure is stored in a v8::External which gets
455
// passed into our callback wrapper. This reduces the performance impact of
456
// calling through N-API.
457
// Ref: benchmark/misc/function_call
458
// Discussion (incl. perf. data): https://github.com/nodejs/node/pull/21072
459
class CallbackBundle {
460
 public:
461
  // Creates an object to be made available to the static function callback
462
  // wrapper, used to retrieve the native callback function and data pointer.
463
  static inline v8::Local<v8::Value>
464
447
  New(napi_env env, napi_callback cb, void* data) {
465
447
    CallbackBundle* bundle = new CallbackBundle();
466
447
    bundle->cb = cb;
467
447
    bundle->cb_data = data;
468
447
    bundle->env = env;
469
470
447
    v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
471
447
    Reference::New(env, cbdata, 0, true, Delete, bundle, nullptr);
472
447
    return cbdata;
473
  }
474
  napi_env       env;      // Necessary to invoke C++ NAPI callback
475
  void*          cb_data;  // The user provided callback data
476
  napi_callback  cb;
477
 private:
478
440
  static void Delete(napi_env env, void* data, void* hint) {
479
440
    CallbackBundle* bundle = static_cast<CallbackBundle*>(data);
480
440
    delete bundle;
481
440
  }
482
};
483
484
// Base class extended by classes that wrap V8 function and property callback
485
// info.
486
class CallbackWrapper {
487
 public:
488
4635
  inline CallbackWrapper(napi_value this_arg, size_t args_length, void* data)
489
4635
      : _this(this_arg), _args_length(args_length), _data(data) {}
490
491
  virtual napi_value GetNewTarget() = 0;
492
  virtual void Args(napi_value* buffer, size_t bufferlength) = 0;
493
  virtual void SetReturnValue(napi_value value) = 0;
494
495
42
  napi_value This() { return _this; }
496
497
4477
  size_t ArgsLength() { return _args_length; }
498
499
6
  void* Data() { return _data; }
500
501
 protected:
502
  const napi_value _this;
503
  const size_t _args_length;
504
  void* _data;
505
};
506
507
class CallbackWrapperBase : public CallbackWrapper {
508
 public:
509
4635
  inline CallbackWrapperBase(const v8::FunctionCallbackInfo<v8::Value>& cbinfo,
510
                             const size_t args_length)
511
4635
      : CallbackWrapper(JsValueFromV8LocalValue(cbinfo.This()),
512
                        args_length,
513
                        nullptr),
514
4635
        _cbinfo(cbinfo) {
515
4635
    _bundle = reinterpret_cast<CallbackBundle*>(
516
13905
        v8::Local<v8::External>::Cast(cbinfo.Data())->Value());
517
4635
    _data = _bundle->cb_data;
518
4635
  }
519
520
 protected:
521
4635
  inline void InvokeCallback() {
522
    napi_callback_info cbinfo_wrapper = reinterpret_cast<napi_callback_info>(
523
4635
        static_cast<CallbackWrapper*>(this));
524
525
    // All other pointers we need are stored in `_bundle`
526
4635
    napi_env env = _bundle->env;
527
4635
    napi_callback cb = _bundle->cb;
528
529
    napi_value result;
530
13905
    env->CallIntoModule([&](napi_env env) {
531
4635
      result = cb(env, cbinfo_wrapper);
532
9270
    });
533
534
4635
    if (result != nullptr) {
535
2809
      this->SetReturnValue(result);
536
    }
537
4635
  }
538
539
  const v8::FunctionCallbackInfo<v8::Value>& _cbinfo;
540
  CallbackBundle* _bundle;
541
};
542
543
class FunctionCallbackWrapper
544
    : public CallbackWrapperBase {
545
 public:
546
4635
  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
547
4635
    FunctionCallbackWrapper cbwrapper(info);
548
4635
    cbwrapper.InvokeCallback();
549
4635
  }
550
551
416
  static inline napi_status NewFunction(napi_env env,
552
                                        napi_callback cb,
553
                                        void* cb_data,
554
                                        v8::Local<v8::Function>* result) {
555
416
    v8::Local<v8::Value> cbdata = v8impl::CallbackBundle::New(env, cb, cb_data);
556
416
    RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
557
558
    v8::MaybeLocal<v8::Function> maybe_function =
559
416
        v8::Function::New(env->context(), Invoke, cbdata);
560
416
    CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
561
562
416
    *result = maybe_function.ToLocalChecked();
563
416
    return napi_clear_last_error(env);
564
  }
565
566
31
  static inline napi_status NewTemplate(napi_env env,
567
                    napi_callback cb,
568
                    void* cb_data,
569
                    v8::Local<v8::FunctionTemplate>* result,
570
                    v8::Local<v8::Signature> sig = v8::Local<v8::Signature>()) {
571
31
    v8::Local<v8::Value> cbdata = v8impl::CallbackBundle::New(env, cb, cb_data);
572
31
    RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
573
574
31
    *result = v8::FunctionTemplate::New(env->isolate, Invoke, cbdata, sig);
575
31
    return napi_clear_last_error(env);
576
  }
577
578
4635
  explicit FunctionCallbackWrapper(
579
      const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
580
9270
      : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
581
582
8
  napi_value GetNewTarget() override {
583
16
    if (_cbinfo.IsConstructCall()) {
584
14
      return v8impl::JsValueFromV8LocalValue(_cbinfo.NewTarget());
585
    } else {
586
1
      return nullptr;
587
    }
588
  }
589
590
  /*virtual*/
591
4465
  void Args(napi_value* buffer, size_t buffer_length) override {
592
4465
    size_t i = 0;
593
4465
    size_t min = std::min(buffer_length, _args_length);
594
595
18545
    for (; i < min; i += 1) {
596
14080
      buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
597
    }
598
599
4465
    if (i < buffer_length) {
600
      napi_value undefined =
601
75
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
602
181
      for (; i < buffer_length; i += 1) {
603
78
        buffer[i] = undefined;
604
      }
605
    }
606
4465
  }
607
608
  /*virtual*/
609
2809
  void SetReturnValue(napi_value value) override {
610
2809
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
611
8427
    _cbinfo.GetReturnValue().Set(val);
612
2809
  }
613
};
614
615
enum WrapType {
616
  retrievable,
617
  anonymous
618
};
619
620
template <WrapType wrap_type>
621
1031
inline napi_status Wrap(napi_env env,
622
                        napi_value js_object,
623
                        void* native_object,
624
                        napi_finalize finalize_cb,
625
                        void* finalize_hint,
626
                        napi_ref* result) {
627




3093
  NAPI_PREAMBLE(env);
628

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

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

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

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

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

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


45
  NAPI_PREAMBLE(env);
733
15
  CHECK_ARG(env, result);
734
15
  CHECK_ARG(env, cb);
735
736
  v8::Local<v8::Function> return_value;
737
15
  v8::EscapableHandleScope scope(env->isolate);
738
  v8::Local<v8::Function> fn;
739
15
  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
740
      env, cb, callback_data, &fn));
741
15
  return_value = scope.Escape(fn);
742
743
15
  if (utf8name != nullptr) {
744
    v8::Local<v8::String> name_string;
745

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


43
  NAPI_PREAMBLE(env);
763
14
  CHECK_ARG(env, result);
764
13
  CHECK_ARG(env, constructor);
765
766
12
  if (property_count > 0) {
767
7
    CHECK_ARG(env, properties);
768
  }
769
770
11
  v8::Isolate* isolate = env->isolate;
771
772
11
  v8::EscapableHandleScope scope(isolate);
773
  v8::Local<v8::FunctionTemplate> tpl;
774
11
  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
775
      env, constructor, callback_data, &tpl));
776
777
  v8::Local<v8::String> name_string;
778

12
  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
779
11
  tpl->SetClassName(name_string);
780
20
781
20
  size_t static_property_count = 0;
782
76
  for (size_t i = 0; i < property_count; i++) {
783
28
    const napi_property_descriptor* p = properties + i;
784
785
28
    if ((p->attributes & napi_static) != 0) {
786
      // Static properties are handled separately below.
787
7
      static_property_count++;
788
7
      continue;
789
    }
790
791
    v8::Local<v8::Name> property_name;
792
21
    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
793
794
    v8::PropertyAttribute attributes =
795
21
        v8impl::V8PropertyAttributesFromDescriptor(p);
796
797
    // This code is similar to that in napi_define_properties(); the
798
    // difference is it applies to a template instead of an object,
799
    // and preferred PropertyAttribute for lack of PropertyDescriptor
800
    // support on ObjectTemplate.
801

21
    if (p->getter != nullptr || p->setter != nullptr) {
802
      v8::Local<v8::FunctionTemplate> getter_tpl;
803
      v8::Local<v8::FunctionTemplate> setter_tpl;
804
10
      if (p->getter != nullptr) {
805
10
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
806
            env, p->getter, p->data, &getter_tpl));
807
      }
808
10
      if (p->setter != nullptr) {
809
5
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
810
            env, p->setter, p->data, &setter_tpl));
811
      }
812
813
30
      tpl->PrototypeTemplate()->SetAccessorProperty(
814
        property_name,
815
        getter_tpl,
816
        setter_tpl,
817
        attributes,
818
20
        v8::AccessControl::DEFAULT);
819
11
    } else if (p->method != nullptr) {
820
      v8::Local<v8::FunctionTemplate> t;
821
5
      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
822
          env, p->method, p->data, &t, v8::Signature::New(isolate, tpl)));
823
824
10
      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
825
    } else {
826
6
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
827
12
      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
828
    }
829
  }
830
831
10
  v8::Local<v8::Context> context = env->context();
832
20
  *result = v8impl::JsValueFromV8LocalValue(
833
20
      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
834
835
10
  if (static_property_count > 0) {
836
6
    std::vector<napi_property_descriptor> static_descriptors;
837
3
    static_descriptors.reserve(static_property_count);
838
839
26
    for (size_t i = 0; i < property_count; i++) {
840
23
      const napi_property_descriptor* p = properties + i;
841
23
      if ((p->attributes & napi_static) != 0) {
842
7
        static_descriptors.push_back(*p);
843
      }
844
    }
845
846

3
    STATUS_CALL(napi_define_properties(env,
847
                                       *result,
848
                                       static_descriptors.size(),
849
                                       static_descriptors.data()));
850
  }
851
852
10
  return GET_RETURN_STATUS(env);
853
}
854
855
8
napi_status napi_get_property_names(napi_env env,
856
                                    napi_value object,
857
                                    napi_value* result) {
858
  return napi_get_all_property_names(
859
      env,
860
      object,
861
      napi_key_include_prototypes,
862
      static_cast<napi_key_filter>(napi_key_enumerable |
863
                                   napi_key_skip_symbols),
864
      napi_key_numbers_to_strings,
865
8
      result);
866
}
867
868
12
napi_status napi_get_all_property_names(napi_env env,
869
                                        napi_value object,
870
                                        napi_key_collection_mode key_mode,
871
                                        napi_key_filter key_filter,
872
                                        napi_key_conversion key_conversion,
873
                                        napi_value* result) {
874


32
  NAPI_PREAMBLE(env);
875
10
  CHECK_ARG(env, result);
876
877
8
  v8::Local<v8::Context> context = env->context();
878
  v8::Local<v8::Object> obj;
879

28
  CHECK_TO_OBJECT(env, context, obj, object);
880
881
6
  v8::PropertyFilter filter = v8::PropertyFilter::ALL_PROPERTIES;
882
6
  if (key_filter & napi_key_writable) {
883
    filter =
884
        static_cast<v8::PropertyFilter>(filter |
885
                                        v8::PropertyFilter::ONLY_WRITABLE);
886
  }
887
6
  if (key_filter & napi_key_enumerable) {
888
5
    filter =
889
5
        static_cast<v8::PropertyFilter>(filter |
890
                                        v8::PropertyFilter::ONLY_ENUMERABLE);
891
  }
892
6
  if (key_filter & napi_key_configurable) {
893
    filter =
894
        static_cast<v8::PropertyFilter>(filter |
895
                                        v8::PropertyFilter::ONLY_WRITABLE);
896
  }
897
6
  if (key_filter & napi_key_skip_strings) {
898
1
    filter =
899
1
        static_cast<v8::PropertyFilter>(filter |
900
                                        v8::PropertyFilter::SKIP_STRINGS);
901
  }
902
6
  if (key_filter & napi_key_skip_symbols) {
903
5
    filter =
904
5
        static_cast<v8::PropertyFilter>(filter |
905
                                        v8::PropertyFilter::SKIP_SYMBOLS);
906
  }
907
  v8::KeyCollectionMode collection_mode;
908
  v8::KeyConversionMode conversion_mode;
909
910
6
  switch (key_mode) {
911
    case napi_key_include_prototypes:
912
6
      collection_mode = v8::KeyCollectionMode::kIncludePrototypes;
913
6
      break;
914
    case napi_key_own_only:
915
      collection_mode = v8::KeyCollectionMode::kOwnOnly;
916
      break;
917
    default:
918
      return napi_set_last_error(env, napi_invalid_arg);
919
  }
920
921
6
  switch (key_conversion) {
922
    case napi_key_keep_numbers:
923
      conversion_mode = v8::KeyConversionMode::kKeepNumbers;
924
      break;
925
    case napi_key_numbers_to_strings:
926
6
      conversion_mode = v8::KeyConversionMode::kConvertToString;
927
6
      break;
928
    default:
929
      return napi_set_last_error(env, napi_invalid_arg);
930
  }
931
932
  v8::MaybeLocal<v8::Array> maybe_all_propertynames =
933
      obj->GetPropertyNames(context,
934
                            collection_mode,
935
                            filter,
936
                            v8::IndexFilter::kIncludeIndices,
937
6
                            conversion_mode);
938
939

6
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(
940
      env, maybe_all_propertynames, napi_generic_failure);
941
942
12
  *result =
943
12
      v8impl::JsValueFromV8LocalValue(maybe_all_propertynames.ToLocalChecked());
944
6
  return GET_RETURN_STATUS(env);
945
}
946
947
26
napi_status napi_set_property(napi_env env,
948
                              napi_value object,
949
                              napi_value key,
950
                              napi_value value) {
951


74
  NAPI_PREAMBLE(env);
952
24
  CHECK_ARG(env, key);
953
21
  CHECK_ARG(env, value);
954
955
19
  v8::Local<v8::Context> context = env->context();
956
  v8::Local<v8::Object> obj;
957
958

72
  CHECK_TO_OBJECT(env, context, obj, object);
959
960
17
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
961
17
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
962
963
17
  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
964
965
34
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
966
17
  return GET_RETURN_STATUS(env);
967
}
968
969
16
napi_status napi_has_property(napi_env env,
970
                              napi_value object,
971
                              napi_value key,
972
                              bool* result) {
973


44
  NAPI_PREAMBLE(env);
974
14
  CHECK_ARG(env, result);
975
12
  CHECK_ARG(env, key);
976
977
10
  v8::Local<v8::Context> context = env->context();
978
  v8::Local<v8::Object> obj;
979
980

36
  CHECK_TO_OBJECT(env, context, obj, object);
981
982
8
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
983
8
  v8::Maybe<bool> has_maybe = obj->Has(context, k);
984
985
8
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
986
987
16
  *result = has_maybe.FromMaybe(false);
988
8
  return GET_RETURN_STATUS(env);
989
}
990
991
34
napi_status napi_get_property(napi_env env,
992
                              napi_value object,
993
                              napi_value key,
994
                              napi_value* result) {
995


98
  NAPI_PREAMBLE(env);
996
32
  CHECK_ARG(env, key);
997
28
  CHECK_ARG(env, result);
998
999
26
  v8::Local<v8::Context> context = env->context();
1000
26
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1001
  v8::Local<v8::Object> obj;
1002
1003

100
  CHECK_TO_OBJECT(env, context, obj, object);
1004
1005
24
  auto get_maybe = obj->Get(context, k);
1006
1007
24
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1008
1009
24
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1010
24
  *result = v8impl::JsValueFromV8LocalValue(val);
1011
24
  return GET_RETURN_STATUS(env);
1012
}
1013
1014
9
napi_status napi_delete_property(napi_env env,
1015
                                 napi_value object,
1016
                                 napi_value key,
1017
                                 bool* result) {
1018


25
  NAPI_PREAMBLE(env);
1019
8
  CHECK_ARG(env, key);
1020
1021
7
  v8::Local<v8::Context> context = env->context();
1022
7
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1023
  v8::Local<v8::Object> obj;
1024
1025

26
  CHECK_TO_OBJECT(env, context, obj, object);
1026
6
  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
1027
6
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1028
1029
6
  if (result != nullptr)
1030
10
    *result = delete_maybe.FromMaybe(false);
1031
1032
6
  return GET_RETURN_STATUS(env);
1033
}
1034
1035
19
napi_status napi_has_own_property(napi_env env,
1036
                                  napi_value object,
1037
                                  napi_value key,
1038
                                  bool* result) {
1039


55
  NAPI_PREAMBLE(env);
1040
18
  CHECK_ARG(env, key);
1041
17
  CHECK_ARG(env, result);
1042
1043
16
  v8::Local<v8::Context> context = env->context();
1044
  v8::Local<v8::Object> obj;
1045
1046

62
  CHECK_TO_OBJECT(env, context, obj, object);
1047
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1048
24
  RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected);
1049
6
  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
1050
6
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1051
12
  *result = has_maybe.FromMaybe(false);
1052
1053
6
  return GET_RETURN_STATUS(env);
1054
}
1055
1056
155
napi_status napi_set_named_property(napi_env env,
1057
                                    napi_value object,
1058
                                    const char* utf8name,
1059
                                    napi_value value) {
1060


463
  NAPI_PREAMBLE(env);
1061
154
  CHECK_ARG(env, value);
1062
1063
153
  v8::Local<v8::Context> context = env->context();
1064
  v8::Local<v8::Object> obj;
1065
1066

610
  CHECK_TO_OBJECT(env, context, obj, object);
1067
1068
  v8::Local<v8::Name> key;
1069

455
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1070
1071
151
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1072
1073
151
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1074
1075
302
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1076
151
  return GET_RETURN_STATUS(env);
1077
}
1078
1079
9
napi_status napi_has_named_property(napi_env env,
1080
                                    napi_value object,
1081
                                    const char* utf8name,
1082
                                    bool* result) {
1083


25
  NAPI_PREAMBLE(env);
1084
8
  CHECK_ARG(env, result);
1085
1086
7
  v8::Local<v8::Context> context = env->context();
1087
  v8::Local<v8::Object> obj;
1088
1089

26
  CHECK_TO_OBJECT(env, context, obj, object);
1090
1091
  v8::Local<v8::Name> key;
1092

17
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1093
1094
5
  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1095
1096
5
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1097
1098
10
  *result = has_maybe.FromMaybe(false);
1099
5
  return GET_RETURN_STATUS(env);
1100
}
1101
1102
6
napi_status napi_get_named_property(napi_env env,
1103
                                    napi_value object,
1104
                                    const char* utf8name,
1105
                                    napi_value* result) {
1106


16
  NAPI_PREAMBLE(env);
1107
5
  CHECK_ARG(env, result);
1108
1109
4
  v8::Local<v8::Context> context = env->context();
1110
1111
  v8::Local<v8::Name> key;
1112

11
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1113
1114
  v8::Local<v8::Object> obj;
1115
1116

11
  CHECK_TO_OBJECT(env, context, obj, object);
1117
1118
2
  auto get_maybe = obj->Get(context, key);
1119
1120
2
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1121
1122
2
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1123
2
  *result = v8impl::JsValueFromV8LocalValue(val);
1124
2
  return GET_RETURN_STATUS(env);
1125
}
1126
1127
13
napi_status napi_set_element(napi_env env,
1128
                             napi_value object,
1129
                             uint32_t index,
1130
                             napi_value value) {
1131


37
  NAPI_PREAMBLE(env);
1132
12
  CHECK_ARG(env, value);
1133
1134
12
  v8::Local<v8::Context> context = env->context();
1135
  v8::Local<v8::Object> obj;
1136
1137

46
  CHECK_TO_OBJECT(env, context, obj, object);
1138
1139
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1140
11
  auto set_maybe = obj->Set(context, index, val);
1141
1142
22
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1143
1144
11
  return GET_RETURN_STATUS(env);
1145
}
1146
1147
5
napi_status napi_has_element(napi_env env,
1148
                             napi_value object,
1149
                             uint32_t index,
1150
                             bool* result) {
1151


13
  NAPI_PREAMBLE(env);
1152
4
  CHECK_ARG(env, result);
1153
1154
3
  v8::Local<v8::Context> context = env->context();
1155
  v8::Local<v8::Object> obj;
1156
1157

10
  CHECK_TO_OBJECT(env, context, obj, object);
1158
1159
2
  v8::Maybe<bool> has_maybe = obj->Has(context, index);
1160
1161
2
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1162
1163
4
  *result = has_maybe.FromMaybe(false);
1164
2
  return GET_RETURN_STATUS(env);
1165
}
1166
1167
28
napi_status napi_get_element(napi_env env,
1168
                             napi_value object,
1169
                             uint32_t index,
1170
                             napi_value* result) {
1171


82
  NAPI_PREAMBLE(env);
1172
27
  CHECK_ARG(env, result);
1173
1174
27
  v8::Local<v8::Context> context = env->context();
1175
  v8::Local<v8::Object> obj;
1176
1177

108
  CHECK_TO_OBJECT(env, context, obj, object);
1178
1179
27
  auto get_maybe = obj->Get(context, index);
1180
1181
27
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1182
1183
54
  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
1184
27
  return GET_RETURN_STATUS(env);
1185
}
1186
1187
4
napi_status napi_delete_element(napi_env env,
1188
                                napi_value object,
1189
                                uint32_t index,
1190
                                bool* result) {
1191


10
  NAPI_PREAMBLE(env);
1192
1193
3
  v8::Local<v8::Context> context = env->context();
1194
  v8::Local<v8::Object> obj;
1195
1196

10
  CHECK_TO_OBJECT(env, context, obj, object);
1197
2
  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
1198
2
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1199
1200
2
  if (result != nullptr)
1201
2
    *result = delete_maybe.FromMaybe(false);
1202
1203
2
  return GET_RETURN_STATUS(env);
1204
}
1205
1206
78
napi_status napi_define_properties(napi_env env,
1207
                                   napi_value object,
1208
                                   size_t property_count,
1209
                                   const napi_property_descriptor* properties) {
1210


232
  NAPI_PREAMBLE(env);
1211
77
  if (property_count > 0) {
1212
77
    CHECK_ARG(env, properties);
1213
  }
1214
1215
74
  v8::Local<v8::Context> context = env->context();
1216
1217
  v8::Local<v8::Object> obj;
1218

294
  CHECK_TO_OBJECT(env, context, obj, object);
1219
1220
976
  for (size_t i = 0; i < property_count; i++) {
1221
415
    const napi_property_descriptor* p = &properties[i];
1222
1223
    v8::Local<v8::Name> property_name;
1224
415
    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
1225
1226

415
    if (p->getter != nullptr || p->setter != nullptr) {
1227
      v8::Local<v8::Function> local_getter;
1228
      v8::Local<v8::Function> local_setter;
1229
1230
10
      if (p->getter != nullptr) {
1231
10
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1232
            env, p->getter, p->data, &local_getter));
1233
      }
1234
10
      if (p->setter != nullptr) {
1235
2
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1236
            env, p->setter, p->data, &local_setter));
1237
      }
1238
1239
20
      v8::PropertyDescriptor descriptor(local_getter, local_setter);
1240
10
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1241
10
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1242
1243
      auto define_maybe = obj->DefineProperty(context,
1244
                                              property_name,
1245
10
                                              descriptor);
1246
1247
20
      if (!define_maybe.FromMaybe(false)) {
1248
        return napi_set_last_error(env, napi_invalid_arg);
1249
10
      }
1250
405
    } else if (p->method != nullptr) {
1251
      v8::Local<v8::Function> method;
1252
389
      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1253
          env, p->method, p->data, &method));
1254
      v8::PropertyDescriptor descriptor(method,
1255
1167
                                        (p->attributes & napi_writable) != 0);
1256
389
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1257
389
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1258
1259
      auto define_maybe = obj->DefineProperty(context,
1260
                                              property_name,
1261
389
                                              descriptor);
1262
1263
778
      if (!define_maybe.FromMaybe(false)) {
1264
        return napi_set_last_error(env, napi_generic_failure);
1265
      }
1266
    } else {
1267
16
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1268
1269
      v8::PropertyDescriptor descriptor(value,
1270
32
                                        (p->attributes & napi_writable) != 0);
1271
16
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1272
16
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1273
1274
      auto define_maybe =
1275
16
          obj->DefineProperty(context, property_name, descriptor);
1276
1277
32
      if (!define_maybe.FromMaybe(false)) {
1278
        return napi_set_last_error(env, napi_invalid_arg);
1279
      }
1280
    }
1281
  }
1282
1283
73
  return GET_RETURN_STATUS(env);
1284
}
1285
1286
1
napi_status napi_object_freeze(napi_env env,
1287
                               napi_value object) {
1288


3
  NAPI_PREAMBLE(env);
1289
1290
1
  v8::Local<v8::Context> context = env->context();
1291
  v8::Local<v8::Object> obj;
1292
1293

4
  CHECK_TO_OBJECT(env, context, obj, object);
1294
1295
  v8::Maybe<bool> set_frozen =
1296
1
    obj->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen);
1297
1298

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
1299
    set_frozen.FromMaybe(false), napi_generic_failure);
1300
1301
1
  return GET_RETURN_STATUS(env);
1302
}
1303
1304
1
napi_status napi_object_seal(napi_env env,
1305
                             napi_value object) {
1306


3
  NAPI_PREAMBLE(env);
1307
1308
1
  v8::Local<v8::Context> context = env->context();
1309
  v8::Local<v8::Object> obj;
1310
1311

4
  CHECK_TO_OBJECT(env, context, obj, object);
1312
1313
  v8::Maybe<bool> set_sealed =
1314
1
    obj->SetIntegrityLevel(context, v8::IntegrityLevel::kSealed);
1315
1316

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
1317
    set_sealed.FromMaybe(false), napi_generic_failure);
1318
1319
1
  return GET_RETURN_STATUS(env);
1320
}
1321
1322
11
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1323
11
  CHECK_ENV(env);
1324
11
  CHECK_ARG(env, value);
1325
11
  CHECK_ARG(env, result);
1326
1327
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1328
1329
22
  *result = val->IsArray();
1330
11
  return napi_clear_last_error(env);
1331
}
1332
1333
13
napi_status napi_get_array_length(napi_env env,
1334
                                  napi_value value,
1335
                                  uint32_t* result) {
1336


39
  NAPI_PREAMBLE(env);
1337
13
  CHECK_ARG(env, value);
1338
13
  CHECK_ARG(env, result);
1339
1340
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1341
13
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1342
1343
13
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1344
26
  *result = arr->Length();
1345
1346
13
  return GET_RETURN_STATUS(env);
1347
}
1348
1349
9
napi_status napi_strict_equals(napi_env env,
1350
                               napi_value lhs,
1351
                               napi_value rhs,
1352
                               bool* result) {
1353


27
  NAPI_PREAMBLE(env);
1354
9
  CHECK_ARG(env, lhs);
1355
9
  CHECK_ARG(env, rhs);
1356
9
  CHECK_ARG(env, result);
1357
1358
9
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1359
9
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1360
1361
18
  *result = a->StrictEquals(b);
1362
9
  return GET_RETURN_STATUS(env);
1363
}
1364
1365
7
napi_status napi_get_prototype(napi_env env,
1366
                               napi_value object,
1367
                               napi_value* result) {
1368


19
  NAPI_PREAMBLE(env);
1369
6
  CHECK_ARG(env, result);
1370
1371
5
  v8::Local<v8::Context> context = env->context();
1372
1373
  v8::Local<v8::Object> obj;
1374

18
  CHECK_TO_OBJECT(env, context, obj, object);
1375
1376
4
  v8::Local<v8::Value> val = obj->GetPrototype();
1377
4
  *result = v8impl::JsValueFromV8LocalValue(val);
1378
4
  return GET_RETURN_STATUS(env);
1379
}
1380
1381
64
napi_status napi_create_object(napi_env env, napi_value* result) {
1382
64
  CHECK_ENV(env);
1383
64
  CHECK_ARG(env, result);
1384
1385
192
  *result = v8impl::JsValueFromV8LocalValue(
1386
64
      v8::Object::New(env->isolate));
1387
1388
64
  return napi_clear_last_error(env);
1389
}
1390
1391
1
napi_status napi_create_array(napi_env env, napi_value* result) {
1392
1
  CHECK_ENV(env);
1393
1
  CHECK_ARG(env, result);
1394
1395
3
  *result = v8impl::JsValueFromV8LocalValue(
1396
1
      v8::Array::New(env->isolate));
1397
1398
1
  return napi_clear_last_error(env);
1399
}
1400
1401
4
napi_status napi_create_array_with_length(napi_env env,
1402
                                          size_t length,
1403
                                          napi_value* result) {
1404
4
  CHECK_ENV(env);
1405
4
  CHECK_ARG(env, result);
1406
1407
12
  *result = v8impl::JsValueFromV8LocalValue(
1408
4
      v8::Array::New(env->isolate, length));
1409
1410
4
  return napi_clear_last_error(env);
1411
}
1412
1413
12
napi_status napi_create_string_latin1(napi_env env,
1414
                                      const char* str,
1415
                                      size_t length,
1416
                                      napi_value* result) {
1417
12
  CHECK_ENV(env);
1418
12
  CHECK_ARG(env, result);
1419

12
  RETURN_STATUS_IF_FALSE(env,
1420
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1421
      napi_invalid_arg);
1422
1423
11
  auto isolate = env->isolate;
1424
  auto str_maybe =
1425
      v8::String::NewFromOneByte(isolate,
1426
                                 reinterpret_cast<const uint8_t*>(str),
1427
                                 v8::NewStringType::kNormal,
1428
11
                                 length);
1429
11
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1430
1431
22
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1432
11
  return napi_clear_last_error(env);
1433
}
1434
1435
720
napi_status napi_create_string_utf8(napi_env env,
1436
                                    const char* str,
1437
                                    size_t length,
1438
                                    napi_value* result) {
1439
720
  CHECK_ENV(env);
1440
720
  CHECK_ARG(env, result);
1441

720
  RETURN_STATUS_IF_FALSE(env,
1442
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1443
      napi_invalid_arg);
1444
1445
719
  auto isolate = env->isolate;
1446
  auto str_maybe =
1447
      v8::String::NewFromUtf8(isolate,
1448
                              str,
1449
                              v8::NewStringType::kNormal,
1450
719
                              static_cast<int>(length));
1451
719
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1452
1438
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1453
719
  return napi_clear_last_error(env);
1454
}
1455
1456
14
napi_status napi_create_string_utf16(napi_env env,
1457
                                     const char16_t* str,
1458
                                     size_t length,
1459
                                     napi_value* result) {
1460
14
  CHECK_ENV(env);
1461
14
  CHECK_ARG(env, result);
1462

14
  RETURN_STATUS_IF_FALSE(env,
1463
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1464
      napi_invalid_arg);
1465
1466
13
  auto isolate = env->isolate;
1467
  auto str_maybe =
1468
      v8::String::NewFromTwoByte(isolate,
1469
                                 reinterpret_cast<const uint16_t*>(str),
1470
                                 v8::NewStringType::kNormal,
1471
13
                                 length);
1472
13
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1473
1474
26
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1475
13
  return napi_clear_last_error(env);
1476
}
1477
1478
71
napi_status napi_create_double(napi_env env,
1479
                               double value,
1480
                               napi_value* result) {
1481
71
  CHECK_ENV(env);
1482
71
  CHECK_ARG(env, result);
1483
1484
213
  *result = v8impl::JsValueFromV8LocalValue(
1485
71
      v8::Number::New(env->isolate, value));
1486
1487
71
  return napi_clear_last_error(env);
1488
}
1489
1490
162
napi_status napi_create_int32(napi_env env,
1491
                              int32_t value,
1492
                              napi_value* result) {
1493
162
  CHECK_ENV(env);
1494
162
  CHECK_ARG(env, result);
1495
1496
486
  *result = v8impl::JsValueFromV8LocalValue(
1497
162
      v8::Integer::New(env->isolate, value));
1498
1499
162
  return napi_clear_last_error(env);
1500
}
1501
1502
555
napi_status napi_create_uint32(napi_env env,
1503
                               uint32_t value,
1504
                               napi_value* result) {
1505
555
  CHECK_ENV(env);
1506
555
  CHECK_ARG(env, result);
1507
1508
1665
  *result = v8impl::JsValueFromV8LocalValue(
1509
555
      v8::Integer::NewFromUnsigned(env->isolate, value));
1510
1511
555
  return napi_clear_last_error(env);
1512
}
1513
1514
24
napi_status napi_create_int64(napi_env env,
1515
                              int64_t value,
1516
                              napi_value* result) {
1517
24
  CHECK_ENV(env);
1518
24
  CHECK_ARG(env, result);
1519
1520
72
  *result = v8impl::JsValueFromV8LocalValue(
1521
24
      v8::Number::New(env->isolate, static_cast<double>(value)));
1522
1523
24
  return napi_clear_last_error(env);
1524
}
1525
1526
9
napi_status napi_create_bigint_int64(napi_env env,
1527
                                     int64_t value,
1528
                                     napi_value* result) {
1529
9
  CHECK_ENV(env);
1530
9
  CHECK_ARG(env, result);
1531
1532
27
  *result = v8impl::JsValueFromV8LocalValue(
1533
9
      v8::BigInt::New(env->isolate, value));
1534
1535
9
  return napi_clear_last_error(env);
1536
}
1537
1538
6
napi_status napi_create_bigint_uint64(napi_env env,
1539
                                      uint64_t value,
1540
                                      napi_value* result) {
1541
6
  CHECK_ENV(env);
1542
6
  CHECK_ARG(env, result);
1543
1544
18
  *result = v8impl::JsValueFromV8LocalValue(
1545
6
      v8::BigInt::NewFromUnsigned(env->isolate, value));
1546
1547
6
  return napi_clear_last_error(env);
1548
}
1549
1550
13
napi_status napi_create_bigint_words(napi_env env,
1551
                                     int sign_bit,
1552
                                     size_t word_count,
1553
                                     const uint64_t* words,
1554
                                     napi_value* result) {
1555


39
  NAPI_PREAMBLE(env);
1556
13
  CHECK_ARG(env, words);
1557
13
  CHECK_ARG(env, result);
1558
1559
13
  v8::Local<v8::Context> context = env->context();
1560
1561
13
  RETURN_STATUS_IF_FALSE(
1562
      env, word_count <= INT_MAX, napi_invalid_arg);
1563
1564
  v8::MaybeLocal<v8::BigInt> b = v8::BigInt::NewFromWords(
1565
12
      context, sign_bit, word_count, words);
1566
1567

12
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, b, napi_generic_failure);
1568
1569
22
  *result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
1570
11
  return GET_RETURN_STATUS(env);
1571
}
1572
1573
1292
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
1574
1292
  CHECK_ENV(env);
1575
1292
  CHECK_ARG(env, result);
1576
1577
1292
  v8::Isolate* isolate = env->isolate;
1578
1579
1292
  if (value) {
1580
1460
    *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
1581
  } else {
1582
1124
    *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
1583
  }
1584
1585
1292
  return napi_clear_last_error(env);
1586
}
1587
1588
13
napi_status napi_create_symbol(napi_env env,
1589
                               napi_value description,
1590
                               napi_value* result) {
1591
13
  CHECK_ENV(env);
1592
13
  CHECK_ARG(env, result);
1593
1594
13
  v8::Isolate* isolate = env->isolate;
1595
1596
13
  if (description == nullptr) {
1597
6
    *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
1598
  } else {
1599
11
    v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
1600
22
    RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
1601
1602
33
    *result = v8impl::JsValueFromV8LocalValue(
1603
      v8::Symbol::New(isolate, desc.As<v8::String>()));
1604
  }
1605
1606
13
  return napi_clear_last_error(env);
1607
}
1608
1609
194
static inline napi_status set_error_code(napi_env env,
1610
                                         v8::Local<v8::Value> error,
1611
                                         napi_value code,
1612
                                         const char* code_cstring) {
1613

194
  if ((code != nullptr) || (code_cstring != nullptr)) {
1614
116
    v8::Local<v8::Context> context = env->context();
1615
116
    v8::Local<v8::Object> err_object = error.As<v8::Object>();
1616
1617
116
    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1618
116
    if (code != nullptr) {
1619
5
      code_value = v8impl::V8LocalValueFromJsValue(code);
1620
10
      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1621
    } else {
1622

333
      CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
1623
    }
1624
1625
    v8::Local<v8::Name> code_key;
1626
348
    CHECK_NEW_FROM_UTF8(env, code_key, "code");
1627
1628
116
    v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
1629
232
    RETURN_STATUS_IF_FALSE(env,
1630
                           set_maybe.FromMaybe(false),
1631
                           napi_generic_failure);
1632
  }
1633
194
  return napi_ok;
1634
}
1635
1636
5
napi_status napi_create_error(napi_env env,
1637
                              napi_value code,
1638
                              napi_value msg,
1639
                              napi_value* result) {
1640
5
  CHECK_ENV(env);
1641
5
  CHECK_ARG(env, msg);
1642
5
  CHECK_ARG(env, result);
1643
1644
5
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1645
10
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1646
1647
  v8::Local<v8::Value> error_obj =
1648
5
      v8::Exception::Error(message_value.As<v8::String>());
1649
5
  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
1650
1651
5
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1652
1653
5
  return napi_clear_last_error(env);
1654
}
1655
1656
2
napi_status napi_create_type_error(napi_env env,
1657
                                   napi_value code,
1658
                                   napi_value msg,
1659
                                   napi_value* result) {
1660
2
  CHECK_ENV(env);
1661
2
  CHECK_ARG(env, msg);
1662
2
  CHECK_ARG(env, result);
1663
1664
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1665
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1666
1667
  v8::Local<v8::Value> error_obj =
1668
2
      v8::Exception::TypeError(message_value.As<v8::String>());
1669
2
  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
1670
1671
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1672
1673
2
  return napi_clear_last_error(env);
1674
}
1675
1676
2
napi_status napi_create_range_error(napi_env env,
1677
                                    napi_value code,
1678
                                    napi_value msg,
1679
                                    napi_value* result) {
1680
2
  CHECK_ENV(env);
1681
2
  CHECK_ARG(env, msg);
1682
2
  CHECK_ARG(env, result);
1683
1684
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1685
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1686
1687
  v8::Local<v8::Value> error_obj =
1688
2
      v8::Exception::RangeError(message_value.As<v8::String>());
1689
2
  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
1690
1691
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1692
1693
2
  return napi_clear_last_error(env);
1694
}
1695
1696
436
napi_status napi_typeof(napi_env env,
1697
                        napi_value value,
1698
                        napi_valuetype* result) {
1699
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1700
  // JS exceptions.
1701
436
  CHECK_ENV(env);
1702
436
  CHECK_ARG(env, value);
1703
436
  CHECK_ARG(env, result);
1704
1705
436
  v8::Local<v8::Value> v = v8impl::V8LocalValueFromJsValue(value);
1706
1707
436
  if (v->IsNumber()) {
1708
136
    *result = napi_number;
1709
300
  } else if (v->IsBigInt()) {
1710
26
    *result = napi_bigint;
1711
548
  } else if (v->IsString()) {
1712
87
    *result = napi_string;
1713
187
  } else if (v->IsFunction()) {
1714
    // This test has to come before IsObject because IsFunction
1715
    // implies IsObject
1716
32
    *result = napi_function;
1717
155
  } else if (v->IsExternal()) {
1718
    // This test has to come before IsObject because IsExternal
1719
    // implies IsObject
1720
2
    *result = napi_external;
1721
153
  } else if (v->IsObject()) {
1722
139
    *result = napi_object;
1723
14
  } else if (v->IsBoolean()) {
1724
1
    *result = napi_boolean;
1725
26
  } else if (v->IsUndefined()) {
1726
3
    *result = napi_undefined;
1727
10
  } else if (v->IsSymbol()) {
1728
9
    *result = napi_symbol;
1729
2
  } else if (v->IsNull()) {
1730
1
    *result = napi_null;
1731
  } else {
1732
    // Should not get here unless V8 has added some new kind of value.
1733
    return napi_set_last_error(env, napi_invalid_arg);
1734
  }
1735
1736
436
  return napi_clear_last_error(env);
1737
}
1738
1739
137
napi_status napi_get_undefined(napi_env env, napi_value* result) {
1740
137
  CHECK_ENV(env);
1741
137
  CHECK_ARG(env, result);
1742
1743
274
  *result = v8impl::JsValueFromV8LocalValue(
1744
137
      v8::Undefined(env->isolate));
1745
1746
137
  return napi_clear_last_error(env);
1747
}
1748
1749
5
napi_status napi_get_null(napi_env env, napi_value* result) {
1750
5
  CHECK_ENV(env);
1751
5
  CHECK_ARG(env, result);
1752
1753
10
  *result = v8impl::JsValueFromV8LocalValue(
1754
5
        v8::Null(env->isolate));
1755
1756
5
  return napi_clear_last_error(env);
1757
}
1758
1759
// Gets all callback info in a single call. (Ugly, but faster.)
1760
4497
napi_status napi_get_cb_info(
1761
    napi_env env,               // [in] NAPI environment handle
1762
    napi_callback_info cbinfo,  // [in] Opaque callback-info handle
1763
    size_t* argc,      // [in-out] Specifies the size of the provided argv array
1764
                       // and receives the actual count of args.
1765
    napi_value* argv,  // [out] Array of values
1766
    napi_value* this_arg,  // [out] Receives the JS 'this' arg for the call
1767
    void** data) {         // [out] Receives the data pointer for the callback.
1768
4497
  CHECK_ENV(env);
1769
4497
  CHECK_ARG(env, cbinfo);
1770
1771
  v8impl::CallbackWrapper* info =
1772
4497
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1773
1774
4497
  if (argv != nullptr) {
1775
4465
    CHECK_ARG(env, argc);
1776
4465
    info->Args(argv, *argc);
1777
  }
1778
4497
  if (argc != nullptr) {
1779
4477
    *argc = info->ArgsLength();
1780
  }
1781
4497
  if (this_arg != nullptr) {
1782
42
    *this_arg = info->This();
1783
  }
1784
4497
  if (data != nullptr) {
1785
6
    *data = info->Data();
1786
  }
1787
1788
4497
  return napi_clear_last_error(env);
1789
}
1790
1791
8
napi_status napi_get_new_target(napi_env env,
1792
                                napi_callback_info cbinfo,
1793
                                napi_value* result) {
1794
8
  CHECK_ENV(env);
1795
8
  CHECK_ARG(env, cbinfo);
1796
8
  CHECK_ARG(env, result);
1797
1798
  v8impl::CallbackWrapper* info =
1799
8
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1800
1801
8
  *result = info->GetNewTarget();
1802
8
  return napi_clear_last_error(env);
1803
}
1804
1805
656
napi_status napi_call_function(napi_env env,
1806
                               napi_value recv,
1807
                               napi_value func,
1808
                               size_t argc,
1809
                               const napi_value* argv,
1810
                               napi_value* result) {
1811


1966
  NAPI_PREAMBLE(env);
1812
654
  CHECK_ARG(env, recv);
1813
654
  if (argc > 0) {
1814
602
    CHECK_ARG(env, argv);
1815
  }
1816
1817
654
  v8::Local<v8::Context> context = env->context();
1818
1819
654
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1820
1821
  v8::Local<v8::Function> v8func;
1822

1962
  CHECK_TO_FUNCTION(env, v8func, func);
1823
1824
  auto maybe = v8func->Call(context, v8recv, argc,
1825
1308
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1826
1827
654
  if (try_catch.HasCaught()) {
1828
7
    return napi_set_last_error(env, napi_pending_exception);
1829
  } else {
1830
647
    if (result != nullptr) {
1831
7
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1832
7
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1833
    }
1834
647
    return napi_clear_last_error(env);
1835
  }
1836
}
1837
1838
11
napi_status napi_get_global(napi_env env, napi_value* result) {
1839
11
  CHECK_ENV(env);
1840
11
  CHECK_ARG(env, result);
1841
1842
33
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1843
1844
11
  return napi_clear_last_error(env);
1845
}
1846
1847
12
napi_status napi_throw(napi_env env, napi_value error) {
1848


36
  NAPI_PREAMBLE(env);
1849
12
  CHECK_ARG(env, error);
1850
1851
12
  v8::Isolate* isolate = env->isolate;
1852
1853
12
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1854
  // any VM calls after this point and before returning
1855
  // to the javascript invoker will fail
1856
12
  return napi_clear_last_error(env);
1857
}
1858
1859
78
napi_status napi_throw_error(napi_env env,
1860
                             const char* code,
1861
                             const char* msg) {
1862


229
  NAPI_PREAMBLE(env);
1863
1864
73
  v8::Isolate* isolate = env->isolate;
1865
  v8::Local<v8::String> str;
1866

219
  CHECK_NEW_FROM_UTF8(env, str, msg);
1867
1868
73
  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1869
73
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1870
1871
73
  isolate->ThrowException(error_obj);
1872
  // any VM calls after this point and before returning
1873
  // to the javascript invoker will fail
1874
73
  return napi_clear_last_error(env);
1875
}
1876
1877
90
napi_status napi_throw_type_error(napi_env env,
1878
                                  const char* code,
1879
                                  const char* msg) {
1880


270
  NAPI_PREAMBLE(env);
1881
1882
90
  v8::Isolate* isolate = env->isolate;
1883
  v8::Local<v8::String> str;
1884

270
  CHECK_NEW_FROM_UTF8(env, str, msg);
1885
1886
90
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1887
90
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1888
1889
90
  isolate->ThrowException(error_obj);
1890
  // any VM calls after this point and before returning
1891
  // to the javascript invoker will fail
1892
90
  return napi_clear_last_error(env);
1893
}
1894
1895
22
napi_status napi_throw_range_error(napi_env env,
1896
                                   const char* code,
1897
                                   const char* msg) {
1898


66
  NAPI_PREAMBLE(env);
1899
1900
22
  v8::Isolate* isolate = env->isolate;
1901
  v8::Local<v8::String> str;
1902

66
  CHECK_NEW_FROM_UTF8(env, str, msg);
1903
1904
22
  v8::Local<v8::Value> error_obj = v8::Exception::RangeError(str);
1905
22
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1906
1907
22
  isolate->ThrowException(error_obj);
1908
  // any VM calls after this point and before returning
1909
  // to the javascript invoker will fail
1910
22
  return napi_clear_last_error(env);
1911
}
1912
1913
10
napi_status napi_is_error(napi_env env, napi_value value, bool* result) {
1914
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot
1915
  // throw JS exceptions.
1916
10
  CHECK_ENV(env);
1917
10
  CHECK_ARG(env, value);
1918
10
  CHECK_ARG(env, result);
1919
1920
10
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1921
20
  *result = val->IsNativeError();
1922
1923
10
  return napi_clear_last_error(env);
1924
}
1925
1926
73
napi_status napi_get_value_double(napi_env env,
1927
                                  napi_value value,
1928
                                  double* result) {
1929
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1930
  // JS exceptions.
1931
73
  CHECK_ENV(env);
1932
72
  CHECK_ARG(env, value);
1933
71
  CHECK_ARG(env, result);
1934
1935
70
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1936
70
  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1937
1938
180
  *result = val.As<v8::Number>()->Value();
1939
1940
60
  return napi_clear_last_error(env);
1941
}
1942
1943
61
napi_status napi_get_value_int32(napi_env env,
1944
                                 napi_value value,
1945
                                 int32_t* result) {
1946
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1947
  // JS exceptions.
1948
61
  CHECK_ENV(env);
1949
60
  CHECK_ARG(env, value);
1950
59
  CHECK_ARG(env, result);
1951
1952
58
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1953
1954
58
  if (val->IsInt32()) {
1955
75
    *result = val.As<v8::Int32>()->Value();
1956
  } else {
1957
33
    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1958
1959
    // Empty context: https://github.com/nodejs/node/issues/14379
1960
    v8::Local<v8::Context> context;
1961
72
    *result = val->Int32Value(context).FromJust();
1962
  }
1963
1964
49
  return napi_clear_last_error(env);
1965
}
1966
1967
100
napi_status napi_get_value_uint32(napi_env env,
1968
                                  napi_value value,
1969
                                  uint32_t* result) {
1970
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1971
  // JS exceptions.
1972
100
  CHECK_ENV(env);
1973
99
  CHECK_ARG(env, value);
1974
98
  CHECK_ARG(env, result);
1975
1976
97
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1977
1978
97
  if (val->IsUint32()) {
1979
231
    *result = val.As<v8::Uint32>()->Value();
1980
  } else {
1981
20
    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1982
1983
    // Empty context: https://github.com/nodejs/node/issues/14379
1984
    v8::Local<v8::Context> context;
1985
33
    *result = val->Uint32Value(context).FromJust();
1986
  }
1987
1988
88
  return napi_clear_last_error(env);
1989
}
1990
1991
36
napi_status napi_get_value_int64(napi_env env,
1992
                                 napi_value value,
1993
                                 int64_t* result) {
1994
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1995
  // JS exceptions.
1996
36
  CHECK_ENV(env);
1997
35
  CHECK_ARG(env, value);
1998
34
  CHECK_ARG(env, result);
1999
2000
33
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2001
2002
  // This is still a fast path very likely to be taken.
2003
33
  if (val->IsInt32()) {
2004
15
    *result = val.As<v8::Int32>()->Value();
2005
5
    return napi_clear_last_error(env);
2006
  }
2007
2008
28
  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
2009
2010
  // v8::Value::IntegerValue() converts NaN, +Inf, and -Inf to INT64_MIN,
2011
  // inconsistent with v8::Value::Int32Value() which converts those values to 0.
2012
  // Special-case all non-finite values to match that behavior.
2013
38
  double doubleValue = val.As<v8::Number>()->Value();
2014
19
  if (std::isfinite(doubleValue)) {
2015
    // Empty context: https://github.com/nodejs/node/issues/14379
2016
    v8::Local<v8::Context> context;
2017
45
    *result = val->IntegerValue(context).FromJust();
2018
  } else {
2019
4
    *result = 0;
2020
  }
2021
2022
19
  return napi_clear_last_error(env);
2023
}
2024
2025
20
napi_status napi_get_value_bigint_int64(napi_env env,
2026
                                        napi_value value,
2027
                                        int64_t* result,
2028
                                        bool* lossless) {
2029
20
  CHECK_ENV(env);
2030
20
  CHECK_ARG(env, value);
2031
20
  CHECK_ARG(env, result);
2032
20
  CHECK_ARG(env, lossless);
2033
2034
20
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2035
2036
20
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
2037
2038
60
  *result = val.As<v8::BigInt>()->Int64Value(lossless);
2039
2040
20
  return napi_clear_last_error(env);
2041
}
2042
2043
17
napi_status napi_get_value_bigint_uint64(napi_env env,
2044
                                         napi_value value,
2045
                                         uint64_t* result,
2046
                                         bool* lossless) {
2047
17
  CHECK_ENV(env);
2048
17
  CHECK_ARG(env, value);
2049
17
  CHECK_ARG(env, result);
2050
17
  CHECK_ARG(env, lossless);
2051
2052
17
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2053
2054
17
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
2055
2056
51
  *result = val.As<v8::BigInt>()->Uint64Value(lossless);
2057
2058
17
  return napi_clear_last_error(env);
2059
}
2060
2061
22
napi_status napi_get_value_bigint_words(napi_env env,
2062
                                        napi_value value,
2063
                                        int* sign_bit,
2064
                                        size_t* word_count,
2065
                                        uint64_t* words) {
2066
22
  CHECK_ENV(env);
2067
22
  CHECK_ARG(env, value);
2068
22
  CHECK_ARG(env, word_count);
2069
2070
22
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2071
2072
22
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
2073
2074
22
  v8::Local<v8::BigInt> big = val.As<v8::BigInt>();
2075
2076
22
  int word_count_int = *word_count;
2077
2078

22
  if (sign_bit == nullptr && words == nullptr) {
2079
11
    word_count_int = big->WordCount();
2080
  } else {
2081
11
    CHECK_ARG(env, sign_bit);
2082
11
    CHECK_ARG(env, words);
2083
22
    big->ToWordsArray(sign_bit, &word_count_int, words);
2084
  }
2085
2086
22
  *word_count = word_count_int;
2087
2088
22
  return napi_clear_last_error(env);
2089
}
2090
2091
90
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) {
2092
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2093
  // JS exceptions.
2094
90
  CHECK_ENV(env);
2095
89
  CHECK_ARG(env, value);
2096
88
  CHECK_ARG(env, result);
2097
2098
87
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2099
87
  RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected);
2100
2101
222
  *result = val.As<v8::Boolean>()->Value();
2102
2103
74
  return napi_clear_last_error(env);
2104
}
2105
2106
// Copies a JavaScript string into a LATIN-1 string buffer. The result is the
2107
// number of bytes (excluding the null terminator) copied into buf.
2108
// A sufficient buffer size should be greater than the length of string,
2109
// reserving space for null terminator.
2110
// If bufsize is insufficient, the string will be truncated and null terminated.
2111
// If buf is NULL, this method returns the length of the string (in bytes)
2112
// via the result parameter.
2113
// The result argument is optional unless buf is NULL.
2114
15
napi_status napi_get_value_string_latin1(napi_env env,
2115
                                         napi_value value,
2116
                                         char* buf,
2117
                                         size_t bufsize,
2118
                                         size_t* result) {
2119
15
  CHECK_ENV(env);
2120
14
  CHECK_ARG(env, value);
2121
2122
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2123
26
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2124
2125
12
  if (!buf) {
2126
1
    CHECK_ARG(env, result);
2127
    *result = val.As<v8::String>()->Length();
2128
11
  } else if (bufsize != 0) {
2129
    int copied =
2130
44
        val.As<v8::String>()->WriteOneByte(env->isolate,
2131
                                           reinterpret_cast<uint8_t*>(buf),
2132
                                           0,
2133
11
                                           bufsize - 1,
2134
11
                                           v8::String::NO_NULL_TERMINATION);
2135
2136
11
    buf[copied] = '\0';
2137
11
    if (result != nullptr) {
2138
11
      *result = copied;
2139
    }
2140
  } else if (result != nullptr) {
2141
    *result = 0;
2142
  }
2143
2144
11
  return napi_clear_last_error(env);
2145
}
2146
2147
// Copies a JavaScript string into a UTF-8 string buffer. The result is the
2148
// number of bytes (excluding the null terminator) copied into buf.
2149
// A sufficient buffer size should be greater than the length of string,
2150
// reserving space for null terminator.
2151
// If bufsize is insufficient, the string will be truncated and null terminated.
2152
// If buf is NULL, this method returns the length of the string (in bytes)
2153
// via the result parameter.
2154
// The result argument is optional unless buf is NULL.
2155
43
napi_status napi_get_value_string_utf8(napi_env env,
2156
                                       napi_value value,
2157
                                       char* buf,
2158
                                       size_t bufsize,
2159
                                       size_t* result) {
2160
43
  CHECK_ENV(env);
2161
42
  CHECK_ARG(env, value);
2162
2163
41
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2164
82
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2165
2166
31
  if (!buf) {
2167
8
    CHECK_ARG(env, result);
2168
21
    *result = val.As<v8::String>()->Utf8Length(env->isolate);
2169
23
  } else if (bufsize != 0) {
2170
88
    int copied = val.As<v8::String>()->WriteUtf8(
2171
22
        env->isolate,
2172
        buf,
2173
22
        bufsize - 1,
2174
        nullptr,
2175
22
        v8::String::REPLACE_INVALID_UTF8 | v8::String::NO_NULL_TERMINATION);
2176
2177
22
    buf[copied] = '\0';
2178
22
    if (result != nullptr) {
2179
20
      *result = copied;
2180
    }
2181
1
  } else if (result != nullptr) {
2182
    *result = 0;
2183
  }
2184
2185
30
  return napi_clear_last_error(env);
2186
}
2187
2188
// Copies a JavaScript string into a UTF-16 string buffer. The result is the
2189
// number of 2-byte code units (excluding the null terminator) copied into buf.
2190
// A sufficient buffer size should be greater than the length of string,
2191
// reserving space for null terminator.
2192
// If bufsize is insufficient, the string will be truncated and null terminated.
2193
// If buf is NULL, this method returns the length of the string (in 2-byte
2194
// code units) via the result parameter.
2195
// The result argument is optional unless buf is NULL.
2196
24
napi_status napi_get_value_string_utf16(napi_env env,
2197
                                        napi_value value,
2198
                                        char16_t* buf,
2199
                                        size_t bufsize,
2200
                                        size_t* result) {
2201
24
  CHECK_ENV(env);
2202
23
  CHECK_ARG(env, value);
2203
2204
22
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2205
44
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2206
2207
21
  if (!buf) {
2208
8
    CHECK_ARG(env, result);
2209
    // V8 assumes UTF-16 length is the same as the number of characters.
2210
21
    *result = val.As<v8::String>()->Length();
2211
13
  } else if (bufsize != 0) {
2212
52
    int copied = val.As<v8::String>()->Write(env->isolate,
2213
                                             reinterpret_cast<uint16_t*>(buf),
2214
                                             0,
2215
13
                                             bufsize - 1,
2216
13
                                             v8::String::NO_NULL_TERMINATION);
2217
2218
13
    buf[copied] = '\0';
2219
13
    if (result != nullptr) {
2220
13
      *result = copied;
2221
    }
2222
  } else if (result != nullptr) {
2223
    *result = 0;
2224
  }
2225
2226
20
  return napi_clear_last_error(env);
2227
}
2228
2229
18
napi_status napi_coerce_to_bool(napi_env env,
2230
                                napi_value value,
2231
                                napi_value* result) {
2232


52
  NAPI_PREAMBLE(env);
2233
17
  CHECK_ARG(env, value);
2234
16
  CHECK_ARG(env, result);
2235
2236
15
  v8::Isolate* isolate = env->isolate;
2237
  v8::Local<v8::Boolean> b =
2238
30
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2239
30
  *result = v8impl::JsValueFromV8LocalValue(b);
2240
15
  return GET_RETURN_STATUS(env);
2241
}
2242
2243
#define GEN_COERCE_FUNCTION(UpperCaseName, MixedCaseName, LowerCaseName)      \
2244
  napi_status napi_coerce_to_##LowerCaseName(napi_env env,                    \
2245
                                             napi_value value,                \
2246
                                             napi_value* result) {            \
2247
    NAPI_PREAMBLE(env);                                                       \
2248
    CHECK_ARG(env, value);                                                    \
2249
    CHECK_ARG(env, result);                                                   \
2250
                                                                              \
2251
    v8::Local<v8::Context> context = env->context();                          \
2252
    v8::Local<v8::MixedCaseName> str;                                         \
2253
                                                                              \
2254
    CHECK_TO_##UpperCaseName(env, context, str, value);                       \
2255
                                                                              \
2256
    *result = v8impl::JsValueFromV8LocalValue(str);                           \
2257
    return GET_RETURN_STATUS(env);                                            \
2258
  }
2259
2260
15
GEN_COERCE_FUNCTION(NUMBER, Number, number)
2261


49
GEN_COERCE_FUNCTION(OBJECT, Object, object)
2262


69
GEN_COERCE_FUNCTION(STRING, String, string)
2263


67
2264

35
#undef GEN_COERCE_FUNCTION
2265

48
2266

1092
napi_status napi_wrap(napi_env env,
2267

63
                      napi_value js_object,
2268

59
                      void* native_object,
2269
47
                      napi_finalize finalize_cb,
2270
44
                      void* finalize_hint,
2271
14
                      napi_ref* result) {
2272
  return v8impl::Wrap<v8impl::retrievable>(env,
2273
                                           js_object,
2274
                                           native_object,
2275
                                           finalize_cb,
2276
                                           finalize_hint,
2277
1028
                                           result);
2278
}
2279
2280
27
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2281
27
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2282
}
2283
2284
8
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2285
8
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2286
}
2287
2288
7
napi_status napi_create_external(napi_env env,
2289
                                 void* data,
2290
                                 napi_finalize finalize_cb,
2291
                                 void* finalize_hint,
2292
                                 napi_value* result) {
2293


21
  NAPI_PREAMBLE(env);
2294
7
  CHECK_ARG(env, result);
2295
2296
7
  v8::Isolate* isolate = env->isolate;
2297
2298
7
  v8::Local<v8::Value> external_value = v8::External::New(isolate, data);
2299
2300
  // The Reference object will delete itself after invoking the finalizer
2301
  // callback.
2302
  v8impl::Reference::New(env,
2303
      external_value,
2304
      0,
2305
      true,
2306
      finalize_cb,
2307
      data,
2308
7
      finalize_hint);
2309
2310
7
  *result = v8impl::JsValueFromV8LocalValue(external_value);
2311
2312
7
  return napi_clear_last_error(env);
2313
}
2314
2315
2
NAPI_EXTERN napi_status napi_type_tag_object(napi_env env,
2316
                                             napi_value object,
2317
                                             const napi_type_tag* type_tag) {
2318


6
  NAPI_PREAMBLE(env);
2319
2
  v8::Local<v8::Context> context = env->context();
2320
  v8::Local<v8::Object> obj;
2321


8
  CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, obj, object);
2322

2
  CHECK_ARG_WITH_PREAMBLE(env, type_tag);
2323
2324
2
  auto key = NAPI_PRIVATE_KEY(context, type_tag);
2325
2
  auto maybe_has = obj->HasPrivate(context, key);
2326

2
  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_has, napi_generic_failure);
2327

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
2328
                                       !maybe_has.FromJust(),
2329
                                       napi_invalid_arg);
2330
2331
  auto tag = v8::BigInt::NewFromWords(context,
2332
                                   0,
2333
                                   2,
2334
2
                                   reinterpret_cast<const uint64_t*>(type_tag));
2335

2
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, tag, napi_generic_failure);
2336
2337
2
  auto maybe_set = obj->SetPrivate(context, key, tag.ToLocalChecked());
2338

2
  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_set, napi_generic_failure);
2339

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
2340
                                       maybe_set.FromJust(),
2341
                                       napi_generic_failure);
2342
2343
2
  return GET_RETURN_STATUS(env);
2344
}
2345
2346
NAPI_EXTERN napi_status
2347
6
napi_check_object_type_tag(napi_env env,
2348
                           napi_value object,
2349
                           const napi_type_tag* type_tag,
2350
                           bool* result) {
2351


18
  NAPI_PREAMBLE(env);
2352
6
  v8::Local<v8::Context> context = env->context();
2353
  v8::Local<v8::Object> obj;
2354


24
  CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, obj, object);
2355

6
  CHECK_ARG_WITH_PREAMBLE(env, type_tag);
2356

6
  CHECK_ARG_WITH_PREAMBLE(env, result);
2357
2358
  auto maybe_value = obj->GetPrivate(context,
2359
12
                                     NAPI_PRIVATE_KEY(context, type_tag));
2360

6
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe_value, napi_generic_failure);
2361
6
  v8::Local<v8::Value> val = maybe_value.ToLocalChecked();
2362
2363
  // We consider the type check to have failed unless we reach the line below
2364
  // where we set whether the type check succeeded or not based on the
2365
  // comparison of the two type tags.
2366
6
  *result = false;
2367
6
  if (val->IsBigInt()) {
2368
    int sign;
2369
4
    int size = 2;
2370
    napi_type_tag tag;
2371
12
    val.As<v8::BigInt>()->ToWordsArray(&sign,
2372
                                       &size,
2373
4
                                       reinterpret_cast<uint64_t*>(&tag));
2374

4
    if (size == 2 && sign == 0)
2375

4
      *result = (tag.lower == type_tag->lower && tag.upper == type_tag->upper);
2376
  }
2377
2378
6
  return GET_RETURN_STATUS(env);
2379
}
2380
2381
2
napi_status napi_get_value_external(napi_env env,
2382
                                    napi_value value,
2383
                                    void** result) {
2384
2
  CHECK_ENV(env);
2385
2
  CHECK_ARG(env, value);
2386
2
  CHECK_ARG(env, result);
2387
2388
2
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2389
2
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
2390
2391
2
  v8::Local<v8::External> external_value = val.As<v8::External>();
2392
4
  *result = external_value->Value();
2393
2394
2
  return napi_clear_last_error(env);
2395
}
2396
2397
// Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
2398
1539
napi_status napi_create_reference(napi_env env,
2399
                                  napi_value value,
2400
                                  uint32_t initial_refcount,
2401
                                  napi_ref* result) {
2402
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2403
  // JS exceptions.
2404
1539
  CHECK_ENV(env);
2405
1539
  CHECK_ARG(env, value);
2406
1539
  CHECK_ARG(env, result);
2407
2408
1539
  v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(value);
2409
2410

1539
  if (!(v8_value->IsObject() || v8_value->IsFunction())) {
2411
    return napi_set_last_error(env, napi_object_expected);
2412
  }
2413
2414
  v8impl::Reference* reference =
2415
1539
      v8impl::Reference::New(env, v8_value, initial_refcount, false);
2416
2417
1539
  *result = reinterpret_cast<napi_ref>(reference);
2418
1539
  return napi_clear_last_error(env);
2419
}
2420
2421
// Deletes a reference. The referenced value is released, and may be GC'd unless
2422
// there are other references to it.
2423
1544
napi_status napi_delete_reference(napi_env env, napi_ref ref) {
2424
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2425
  // JS exceptions.
2426
1544
  CHECK_ENV(env);
2427
1544
  CHECK_ARG(env, ref);
2428
2429
1544
  v8impl::Reference::Delete(reinterpret_cast<v8impl::Reference*>(ref));
2430
2431
1544
  return napi_clear_last_error(env);
2432
}
2433
2434
// Increments the reference count, optionally returning the resulting count.
2435
// After this call the reference will be a strong reference because its
2436
// refcount is >0, and the referenced object is effectively "pinned".
2437
// Calling this when the refcount is 0 and the object is unavailable
2438
// results in an error.
2439
3
napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) {
2440
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2441
  // JS exceptions.
2442
3
  CHECK_ENV(env);
2443
3
  CHECK_ARG(env, ref);
2444
2445
3
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2446
3
  uint32_t count = reference->Ref();
2447
2448
3
  if (result != nullptr) {
2449
1
    *result = count;
2450
  }
2451
2452
3
  return napi_clear_last_error(env);
2453
}
2454
2455
// Decrements the reference count, optionally returning the resulting count. If
2456
// the result is 0 the reference is now weak and the object may be GC'd at any
2457
// time if there are no other references. Calling this when the refcount is
2458
// already 0 results in an error.
2459
3
napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) {
2460
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2461
  // JS exceptions.
2462
3
  CHECK_ENV(env);
2463
3
  CHECK_ARG(env, ref);
2464
2465
3
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2466
2467
3
  if (reference->RefCount() == 0) {
2468
    return napi_set_last_error(env, napi_generic_failure);
2469
  }
2470
2471
3
  uint32_t count = reference->Unref();
2472
2473
3
  if (result != nullptr) {
2474
3
    *result = count;
2475
  }
2476
2477
3
  return napi_clear_last_error(env);
2478
}
2479
2480
// Attempts to get a referenced value. If the reference is weak, the value might
2481
// no longer be available, in that case the call is still successful but the
2482
// result is NULL.
2483
1552
napi_status napi_get_reference_value(napi_env env,
2484
                                     napi_ref ref,
2485
                                     napi_value* result) {
2486
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2487
  // JS exceptions.
2488
1552
  CHECK_ENV(env);
2489
1552
  CHECK_ARG(env, ref);
2490
1550
  CHECK_ARG(env, result);
2491
2492
1550
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2493
1550
  *result = v8impl::JsValueFromV8LocalValue(reference->Get());
2494
2495
1550
  return napi_clear_last_error(env);
2496
}
2497
2498
4
napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result) {
2499
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2500
  // JS exceptions.
2501
4
  CHECK_ENV(env);
2502
4
  CHECK_ARG(env, result);
2503
2504
8
  *result = v8impl::JsHandleScopeFromV8HandleScope(
2505
4
      new v8impl::HandleScopeWrapper(env->isolate));
2506
4
  env->open_handle_scopes++;
2507
4
  return napi_clear_last_error(env);
2508
}
2509
2510
4
napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) {
2511
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2512
  // JS exceptions.
2513
4
  CHECK_ENV(env);
2514
4
  CHECK_ARG(env, scope);
2515
4
  if (env->open_handle_scopes == 0) {
2516
    return napi_handle_scope_mismatch;
2517
  }
2518
2519
4
  env->open_handle_scopes--;
2520
4
  delete v8impl::V8HandleScopeFromJsHandleScope(scope);
2521
4
  return napi_clear_last_error(env);
2522
}
2523
2524
2
napi_status napi_open_escapable_handle_scope(
2525
    napi_env env,
2526
    napi_escapable_handle_scope* result) {
2527
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2528
  // JS exceptions.
2529
2
  CHECK_ENV(env);
2530
2
  CHECK_ARG(env, result);
2531
2532
4
  *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope(
2533
2
      new v8impl::EscapableHandleScopeWrapper(env->isolate));
2534
2
  env->open_handle_scopes++;
2535
2
  return napi_clear_last_error(env);
2536
}
2537
2538
2
napi_status napi_close_escapable_handle_scope(
2539
    napi_env env,
2540
    napi_escapable_handle_scope scope) {
2541
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2542
  // JS exceptions.
2543
2
  CHECK_ENV(env);
2544
2
  CHECK_ARG(env, scope);
2545
2
  if (env->open_handle_scopes == 0) {
2546
    return napi_handle_scope_mismatch;
2547
  }
2548
2549
2
  delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2550
2
  env->open_handle_scopes--;
2551
2
  return napi_clear_last_error(env);
2552
}
2553
2554
3
napi_status napi_escape_handle(napi_env env,
2555
                               napi_escapable_handle_scope scope,
2556
                               napi_value escapee,
2557
                               napi_value* result) {
2558
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2559
  // JS exceptions.
2560
3
  CHECK_ENV(env);
2561
3
  CHECK_ARG(env, scope);
2562
3
  CHECK_ARG(env, escapee);
2563
3
  CHECK_ARG(env, result);
2564
2565
  v8impl::EscapableHandleScopeWrapper* s =
2566
3
      v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2567
3
  if (!s->escape_called()) {
2568
2
    *result = v8impl::JsValueFromV8LocalValue(
2569
        s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
2570
2
    return napi_clear_last_error(env);
2571
  }
2572
1
  return napi_set_last_error(env, napi_escape_called_twice);
2573
}
2574
2575
7
napi_status napi_new_instance(napi_env env,
2576
                              napi_value constructor,
2577
                              size_t argc,
2578
                              const napi_value* argv,
2579
                              napi_value* result) {
2580


21
  NAPI_PREAMBLE(env);
2581
7
  CHECK_ARG(env, constructor);
2582
7
  if (argc > 0) {
2583
7
    CHECK_ARG(env, argv);
2584
  }
2585
7
  CHECK_ARG(env, result);
2586
2587
7
  v8::Local<v8::Context> context = env->context();
2588
2589
  v8::Local<v8::Function> ctor;
2590

21
  CHECK_TO_FUNCTION(env, ctor, constructor);
2591
2592
  auto maybe = ctor->NewInstance(context, argc,
2593
14
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2594
2595
7
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2596
2597
14
  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2598
7
  return GET_RETURN_STATUS(env);
2599
}
2600
2601
2278
napi_status napi_instanceof(napi_env env,
2602
                            napi_value object,
2603
                            napi_value constructor,
2604
                            bool* result) {
2605


6834
  NAPI_PREAMBLE(env);
2606
2278
  CHECK_ARG(env, object);
2607
2278
  CHECK_ARG(env, result);
2608
2609
2278
  *result = false;
2610
2611
  v8::Local<v8::Object> ctor;
2612
2278
  v8::Local<v8::Context> context = env->context();
2613
2614

9112
  CHECK_TO_OBJECT(env, context, ctor, constructor);
2615
2616
2278
  if (!ctor->IsFunction()) {
2617
    napi_throw_type_error(env,
2618
                          "ERR_NAPI_CONS_FUNCTION",
2619
88
                          "Constructor must be a function");
2620
2621
88
    return napi_set_last_error(env, napi_function_expected);
2622
  }
2623
2624
2190
  napi_status status = napi_generic_failure;
2625
2626
2190
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(object);
2627
2190
  auto maybe_result = val->InstanceOf(context, ctor);
2628
2190
  CHECK_MAYBE_NOTHING(env, maybe_result, status);
2629
2332
  *result = maybe_result.FromJust();
2630
1166
  return GET_RETURN_STATUS(env);
2631
}
2632
2633
// Methods to support catching exceptions
2634
1228
napi_status napi_is_exception_pending(napi_env env, bool* result) {
2635
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2636
  // pending exception.
2637
1228
  CHECK_ENV(env);
2638
1228
  CHECK_ARG(env, result);
2639
2640
2456
  *result = !env->last_exception.IsEmpty();
2641
1228
  return napi_clear_last_error(env);
2642
}
2643
2644
1
napi_status napi_get_and_clear_last_exception(napi_env env,
2645
                                              napi_value* result) {
2646
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2647
  // pending exception.
2648
1
  CHECK_ENV(env);
2649
1
  CHECK_ARG(env, result);
2650
2651
2
  if (env->last_exception.IsEmpty()) {
2652
    return napi_get_undefined(env, result);
2653
  } else {
2654
2
    *result = v8impl::JsValueFromV8LocalValue(
2655
1
      v8::Local<v8::Value>::New(env->isolate, env->last_exception));
2656
1
    env->last_exception.Reset();
2657
  }
2658
2659
1
  return napi_clear_last_error(env);
2660
}
2661
2662
57
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) {
2663
57
  CHECK_ENV(env);
2664
57
  CHECK_ARG(env, value);
2665
57
  CHECK_ARG(env, result);
2666
2667
57
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2668
114
  *result = val->IsArrayBuffer();
2669
2670
57
  return napi_clear_last_error(env);
2671
}
2672
2673
2
napi_status napi_create_arraybuffer(napi_env env,
2674
                                    size_t byte_length,
2675
                                    void** data,
2676
                                    napi_value* result) {
2677


6
  NAPI_PREAMBLE(env);
2678
2
  CHECK_ARG(env, result);
2679
2680
2
  v8::Isolate* isolate = env->isolate;
2681
  v8::Local<v8::ArrayBuffer> buffer =
2682
2
      v8::ArrayBuffer::New(isolate, byte_length);
2683
2684
  // Optionally return a pointer to the buffer's data, to avoid another call to
2685
  // retrieve it.
2686
2
  if (data != nullptr) {
2687
2
    *data = buffer->GetBackingStore()->Data();
2688
  }
2689
2690
4
  *result = v8impl::JsValueFromV8LocalValue(buffer);
2691
2
  return GET_RETURN_STATUS(env);
2692
}
2693
2694
6
napi_status napi_create_external_arraybuffer(napi_env env,
2695
                                             void* external_data,
2696
                                             size_t byte_length,
2697
                                             napi_finalize finalize_cb,
2698
                                             void* finalize_hint,
2699
                                             napi_value* result) {
2700
  // The API contract here is that the cleanup function runs on the JS thread,
2701
  // and is able to use napi_env. Implementing that properly is hard, so use the
2702
  // `Buffer` variant for easier implementation.
2703
  napi_value buffer;
2704
6
  STATUS_CALL(napi_create_external_buffer(
2705
      env,
2706
      byte_length,
2707
      external_data,
2708
      finalize_cb,
2709
      finalize_hint,
2710
      &buffer));
2711
6
  return napi_get_typedarray_info(
2712
      env,
2713
      buffer,
2714
      nullptr,
2715
      nullptr,
2716
      nullptr,
2717
      result,
2718
6
      nullptr);
2719
}
2720
2721
2
napi_status napi_get_arraybuffer_info(napi_env env,
2722
                                      napi_value arraybuffer,
2723
                                      void** data,
2724
                                      size_t* byte_length) {
2725
2
  CHECK_ENV(env);
2726
2
  CHECK_ARG(env, arraybuffer);
2727
2728
2
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2729
2
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2730
2731
  std::shared_ptr<v8::BackingStore> backing_store =
2732
6
      value.As<v8::ArrayBuffer>()->GetBackingStore();
2733
2734
2
  if (data != nullptr) {
2735
2
    *data = backing_store->Data();
2736
  }
2737
2738
2
  if (byte_length != nullptr) {
2739
2
    *byte_length = backing_store->ByteLength();
2740
  }
2741
2742
2
  return napi_clear_last_error(env);
2743
}
2744
2745
44
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) {
2746
44
  CHECK_ENV(env);
2747
44
  CHECK_ARG(env, value);
2748
44
  CHECK_ARG(env, result);
2749
2750
44
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2751
88
  *result = val->IsTypedArray();
2752
2753
44
  return napi_clear_last_error(env);
2754
}
2755
2756
34
napi_status napi_create_typedarray(napi_env env,
2757
                                   napi_typedarray_type type,
2758
                                   size_t length,
2759
                                   napi_value arraybuffer,
2760
                                   size_t byte_offset,
2761
                                   napi_value* result) {
2762


102
  NAPI_PREAMBLE(env);
2763
34
  CHECK_ARG(env, arraybuffer);
2764
34
  CHECK_ARG(env, result);
2765
2766
34
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2767
34
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2768
2769
34
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2770
  v8::Local<v8::TypedArray> typedArray;
2771
2772



34
  switch (type) {
2773
    case napi_int8_array:
2774
8
      CREATE_TYPED_ARRAY(
2775
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2776
3
      break;
2777
    case napi_uint8_array:
2778
4
      CREATE_TYPED_ARRAY(
2779
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2780
8
      break;
2781
1
    case napi_uint8_clamped_array:
2782
3
      CREATE_TYPED_ARRAY(
2783
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2784
5
      break;
2785
1
    case napi_int16_array:
2786
5
      CREATE_TYPED_ARRAY(
2787
1
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2788
4
      break;
2789
1
    case napi_uint16_array:
2790
5
      CREATE_TYPED_ARRAY(
2791
1
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2792
4
      break;
2793
1
    case napi_int32_array:
2794
5
      CREATE_TYPED_ARRAY(
2795
1
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2796
4
      break;
2797
1
    case napi_uint32_array:
2798
5
      CREATE_TYPED_ARRAY(
2799
1
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2800
4
      break;
2801
1
    case napi_float32_array:
2802
5
      CREATE_TYPED_ARRAY(
2803
1
          env, Float32Array, 4, buffer, byte_offset, length, typedArray);
2804
4
      break;
2805
1
    case napi_float64_array:
2806
6
      CREATE_TYPED_ARRAY(
2807
1
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2808
6
      break;
2809
1
    case napi_bigint64_array:
2810
6
      CREATE_TYPED_ARRAY(
2811
1
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2812
4
      break;
2813
1
    case napi_biguint64_array:
2814
5
      CREATE_TYPED_ARRAY(
2815
1
          env, BigUint64Array, 8, buffer, byte_offset, length, typedArray);
2816
4
      break;
2817
1
    default:
2818
2
      return napi_set_last_error(env, napi_invalid_arg);
2819
  }
2820
2821
30
  *result = v8impl::JsValueFromV8LocalValue(typedArray);
2822
15
  return GET_RETURN_STATUS(env);
2823
}
2824
2825
50
napi_status napi_get_typedarray_info(napi_env env,
2826
                                     napi_value typedarray,
2827
                                     napi_typedarray_type* type,
2828
                                     size_t* length,
2829
                                     void** data,
2830
                                     napi_value* arraybuffer,
2831
                                     size_t* byte_offset) {
2832
50
  CHECK_ENV(env);
2833
50
  CHECK_ARG(env, typedarray);
2834
2835
50
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(typedarray);
2836
50
  RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), napi_invalid_arg);
2837
2838
50
  v8::Local<v8::TypedArray> array = value.As<v8::TypedArray>();
2839
2840
50
  if (type != nullptr) {
2841
32
    if (value->IsInt8Array()) {
2842
2
      *type = napi_int8_array;
2843
30
    } else if (value->IsUint8Array()) {
2844
3
      *type = napi_uint8_array;
2845
27
    } else if (value->IsUint8ClampedArray()) {
2846
2
      *type = napi_uint8_clamped_array;
2847
25
    } else if (value->IsInt16Array()) {
2848
3
      *type = napi_int16_array;
2849
22
    } else if (value->IsUint16Array()) {
2850
3
      *type = napi_uint16_array;
2851
19
    } else if (value->IsInt32Array()) {
2852
3
      *type = napi_int32_array;
2853
16
    } else if (value->IsUint32Array()) {
2854
3
      *type = napi_uint32_array;
2855
13
    } else if (value->IsFloat32Array()) {
2856
3
      *type = napi_float32_array;
2857
10
    } else if (value->IsFloat64Array()) {
2858
4
      *type = napi_float64_array;
2859
6
    } else if (value->IsBigInt64Array()) {
2860
3
      *type = napi_bigint64_array;
2861
3
    } else if (value->IsBigUint64Array()) {
2862
3
      *type = napi_biguint64_array;
2863
    }
2864
  }
2865
2866
50
  if (length != nullptr) {
2867
32
    *length = array->Length();
2868
  }
2869
2870
  v8::Local<v8::ArrayBuffer> buffer;
2871

50
  if (data != nullptr || arraybuffer != nullptr) {
2872
    // Calling Buffer() may have the side effect of allocating the buffer,
2873
    // so only do this when it’s needed.
2874
50
    buffer = array->Buffer();
2875
  }
2876
2877
50
  if (data != nullptr) {
2878
    *data = static_cast<uint8_t*>(buffer->GetBackingStore()->Data()) +
2879
            array->ByteOffset();
2880
  }
2881
2882
50
  if (arraybuffer != nullptr) {
2883
50
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2884
  }
2885
2886
50
  if (byte_offset != nullptr) {
2887
32
    *byte_offset = array->ByteOffset();
2888
  }
2889
2890
50
  return napi_clear_last_error(env);
2891
}
2892
2893
2
napi_status napi_create_dataview(napi_env env,
2894
                                 size_t byte_length,
2895
                                 napi_value arraybuffer,
2896
                                 size_t byte_offset,
2897
                                 napi_value* result) {
2898


6
  NAPI_PREAMBLE(env);
2899
2
  CHECK_ARG(env, arraybuffer);
2900
2
  CHECK_ARG(env, result);
2901
2902
2
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2903
2
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2904
2905
2
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2906
4
  if (byte_length + byte_offset > buffer->ByteLength()) {
2907
    napi_throw_range_error(
2908
        env,
2909
        "ERR_NAPI_INVALID_DATAVIEW_ARGS",
2910
        "byte_offset + byte_length should be less than or "
2911
1
        "equal to the size in bytes of the array passed in");
2912
1
    return napi_set_last_error(env, napi_pending_exception);
2913
  }
2914
  v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset,
2915
1
                                                       byte_length);
2916
2917
2
  *result = v8impl::JsValueFromV8LocalValue(DataView);
2918
1
  return GET_RETURN_STATUS(env);
2919
}
2920
2921
1
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) {
2922
1
  CHECK_ENV(env);
2923
1
  CHECK_ARG(env, value);
2924
1
  CHECK_ARG(env, result);
2925
2926
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2927
2
  *result = val->IsDataView();
2928
2929
1
  return napi_clear_last_error(env);
2930
}
2931
2932
1
napi_status napi_get_dataview_info(napi_env env,
2933
                                   napi_value dataview,
2934
                                   size_t* byte_length,
2935
                                   void** data,
2936
                                   napi_value* arraybuffer,
2937
                                   size_t* byte_offset) {
2938
1
  CHECK_ENV(env);
2939
1
  CHECK_ARG(env, dataview);
2940
2941
1
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(dataview);
2942
1
  RETURN_STATUS_IF_FALSE(env, value->IsDataView(), napi_invalid_arg);
2943
2944
1
  v8::Local<v8::DataView> array = value.As<v8::DataView>();
2945
2946
1
  if (byte_length != nullptr) {
2947
1
    *byte_length = array->ByteLength();
2948
  }
2949
2950
  v8::Local<v8::ArrayBuffer> buffer;
2951

1
  if (data != nullptr || arraybuffer != nullptr) {
2952
    // Calling Buffer() may have the side effect of allocating the buffer,
2953
    // so only do this when it’s needed.
2954
1
    buffer = array->Buffer();
2955
  }
2956
2957
1
  if (data != nullptr) {
2958
    *data = static_cast<uint8_t*>(buffer->GetBackingStore()->Data()) +
2959
            array->ByteOffset();
2960
  }
2961
2962
1
  if (arraybuffer != nullptr) {
2963
1
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2964
  }
2965
2966
1
  if (byte_offset != nullptr) {
2967
1
    *byte_offset = array->ByteOffset();
2968
  }
2969
2970
1
  return napi_clear_last_error(env);
2971
}
2972
2973
1
napi_status napi_get_version(napi_env env, uint32_t* result) {
2974
1
  CHECK_ENV(env);
2975
1
  CHECK_ARG(env, result);
2976
1
  *result = NAPI_VERSION;
2977
1
  return napi_clear_last_error(env);
2978
}
2979
2980
5
napi_status napi_create_promise(napi_env env,
2981
                                napi_deferred* deferred,
2982
                                napi_value* promise) {
2983


15
  NAPI_PREAMBLE(env);
2984
5
  CHECK_ARG(env, deferred);
2985
5
  CHECK_ARG(env, promise);
2986
2987
5
  auto maybe = v8::Promise::Resolver::New(env->context());
2988
5
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2989
2990
5
  auto v8_resolver = maybe.ToLocalChecked();
2991
10
  auto v8_deferred = new v8impl::Persistent<v8::Value>();
2992
5
  v8_deferred->Reset(env->isolate, v8_resolver);
2993
2994
5
  *deferred = v8impl::JsDeferredFromNodePersistent(v8_deferred);
2995
15
  *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise());
2996
5
  return GET_RETURN_STATUS(env);
2997
}
2998
2999
4
napi_status napi_resolve_deferred(napi_env env,
3000
                                  napi_deferred deferred,
3001
                                  napi_value resolution) {
3002
4
  return v8impl::ConcludeDeferred(env, deferred, resolution, true);
3003
}
3004
3005
1
napi_status napi_reject_deferred(napi_env env,
3006
                                 napi_deferred deferred,
3007
                                 napi_value resolution) {
3008
1
  return v8impl::ConcludeDeferred(env, deferred, resolution, false);
3009
}
3010
3011
7
napi_status napi_is_promise(napi_env env,
3012
                            napi_value value,
3013
                            bool* is_promise) {
3014
7
  CHECK_ENV(env);
3015
7
  CHECK_ARG(env, value);
3016
7
  CHECK_ARG(env, is_promise);
3017
3018
14
  *is_promise = v8impl::V8LocalValueFromJsValue(value)->IsPromise();
3019
3020
7
  return napi_clear_last_error(env);
3021
}
3022
3023
1
napi_status napi_create_date(napi_env env,
3024
                             double time,
3025
                             napi_value* result) {
3026


3
  NAPI_PREAMBLE(env);
3027
1
  CHECK_ARG(env, result);
3028
3029
1
  v8::MaybeLocal<v8::Value> maybe_date = v8::Date::New(env->context(), time);
3030
1
  CHECK_MAYBE_EMPTY(env, maybe_date, napi_generic_failure);
3031
3032
2
  *result = v8impl::JsValueFromV8LocalValue(maybe_date.ToLocalChecked());
3033
3034
1
  return GET_RETURN_STATUS(env);
3035
}
3036
3037
7
napi_status napi_is_date(napi_env env,
3038
                         napi_value value,
3039
                         bool* is_date) {
3040
7
  CHECK_ENV(env);
3041
7
  CHECK_ARG(env, value);
3042
7
  CHECK_ARG(env, is_date);
3043
3044
14
  *is_date = v8impl::V8LocalValueFromJsValue(value)->IsDate();
3045
3046
7
  return napi_clear_last_error(env);
3047
}
3048
3049
1
napi_status napi_get_date_value(napi_env env,
3050
                                napi_value value,
3051
                                double* result) {
3052


3
  NAPI_PREAMBLE(env);
3053
1
  CHECK_ARG(env, value);
3054
1
  CHECK_ARG(env, result);
3055
3056
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
3057
1
  RETURN_STATUS_IF_FALSE(env, val->IsDate(), napi_date_expected);
3058
3059
1
  v8::Local<v8::Date> date = val.As<v8::Date>();
3060
2
  *result = date->ValueOf();
3061
3062
1
  return GET_RETURN_STATUS(env);
3063
}
3064
3065
2
napi_status napi_run_script(napi_env env,
3066
                            napi_value script,
3067
                            napi_value* result) {
3068


6
  NAPI_PREAMBLE(env);
3069
2
  CHECK_ARG(env, script);
3070
2
  CHECK_ARG(env, result);
3071
3072
2
  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
3073
3074
4
  if (!v8_script->IsString()) {
3075
1
    return napi_set_last_error(env, napi_string_expected);
3076
  }
3077
3078
1
  v8::Local<v8::Context> context = env->context();
3079
3080
  auto maybe_script = v8::Script::Compile(context,
3081
1
      v8::Local<v8::String>::Cast(v8_script));
3082
1
  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
3083
3084
  auto script_result =
3085
2
      maybe_script.ToLocalChecked()->Run(context);
3086
1
  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
3087
3088
2
  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
3089
1
  return GET_RETURN_STATUS(env);
3090
}
3091
3092
3
napi_status napi_add_finalizer(napi_env env,
3093
                               napi_value js_object,
3094
                               void* native_object,
3095
                               napi_finalize finalize_cb,
3096
                               void* finalize_hint,
3097
                               napi_ref* result) {
3098
  return v8impl::Wrap<v8impl::anonymous>(env,
3099
                                         js_object,
3100
                                         native_object,
3101
                                         finalize_cb,
3102
                                         finalize_hint,
3103
3
                                         result);
3104
}
3105
3106
1
napi_status napi_adjust_external_memory(napi_env env,
3107
                                        int64_t change_in_bytes,
3108
                                        int64_t* adjusted_value) {
3109
1
  CHECK_ENV(env);
3110
1
  CHECK_ARG(env, adjusted_value);
3111
3112
1
  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
3113
      change_in_bytes);
3114
3115
1
  return napi_clear_last_error(env);
3116
}
3117
3118
7
napi_status napi_set_instance_data(napi_env env,
3119
                                   void* data,
3120
                                   napi_finalize finalize_cb,
3121
                                   void* finalize_hint) {
3122
7
  CHECK_ENV(env);
3123
3124
7
  v8impl::RefBase* old_data = static_cast<v8impl::RefBase*>(env->instance_data);
3125
7
  if (old_data != nullptr) {
3126
    // Our contract so far has been to not finalize any old data there may be.
3127
    // So we simply delete it.
3128
    v8impl::RefBase::Delete(old_data);
3129
  }
3130
3131
7
  env->instance_data = v8impl::RefBase::New(env,
3132
                                            0,
3133
                                            true,
3134
                                            finalize_cb,
3135
                                            data,
3136
                                            finalize_hint);
3137
3138
7
  return napi_clear_last_error(env);
3139
}
3140
3141
22
napi_status napi_get_instance_data(napi_env env,
3142
                                   void** data) {
3143
22
  CHECK_ENV(env);
3144
22
  CHECK_ARG(env, data);
3145
3146
22
  v8impl::RefBase* idata = static_cast<v8impl::RefBase*>(env->instance_data);
3147
3148
22
  *data = (idata == nullptr ? nullptr : idata->Data());
3149
3150
22
  return napi_clear_last_error(env);
3151
}
3152
3153
12
napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) {
3154
12
  CHECK_ENV(env);
3155
12
  CHECK_ARG(env, arraybuffer);
3156
3157
12
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3158
12
  RETURN_STATUS_IF_FALSE(
3159
      env, value->IsArrayBuffer(), napi_arraybuffer_expected);
3160
3161
12
  v8::Local<v8::ArrayBuffer> it = value.As<v8::ArrayBuffer>();
3162
12
  RETURN_STATUS_IF_FALSE(
3163
      env, it->IsDetachable(), napi_detachable_arraybuffer_expected);
3164
3165
12
  it->Detach();
3166
3167
12
  return napi_clear_last_error(env);
3168
}
3169
3170
26
napi_status napi_is_detached_arraybuffer(napi_env env,
3171
                                         napi_value arraybuffer,
3172
                                         bool* result) {
3173
26
  CHECK_ENV(env);
3174
26
  CHECK_ARG(env, arraybuffer);
3175
26
  CHECK_ARG(env, result);
3176
3177
26
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3178
3179

104
  *result = value->IsArrayBuffer() &&
3180
104
            value.As<v8::ArrayBuffer>()->GetBackingStore()->Data() == nullptr;
3181
3182
26
  return napi_clear_last_error(env);
3183

14271
}