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: 1378 1410 97.7 %
Date: 2021-02-11 04:11:15 Branches: 1048 1682 62.3 %

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
3025
  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
3025
       : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
201
        _refcount(initial_refcount),
202
3025
        _delete_self(delete_self) {
203
3025
    Link(finalize_callback == nullptr
204
        ? &env->reflist
205
3025
        : &env->finalizing_reflist);
206
3025
  }
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
3024
  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
3022
  static inline void Delete(RefBase* reference) {
245

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

4033
        (reference->_delete_self) ||
247
1011
        (reference->_finalize_ran)) {
248
3017
      delete reference;
249
    } else {
250
      // defer until finalizer runs as
251
      // it may alread be queued
252
5
      reference->_delete_self = true;
253
    }
254
3022
  }
255
256
1
  inline uint32_t Ref() {
257
1
    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
6046
  inline uint32_t RefCount() {
268
6046
    return _refcount;
269
  }
270
271
 protected:
272
2478
  inline void Finalize(bool is_env_teardown = false) override {
273
2478
    if (_finalize_callback != nullptr) {
274
1465
      _env->CallFinalizer(_finalize_callback, _finalize_data, _finalize_hint);
275
    }
276
277
    // this is safe because if a request to delete the reference
278
    // is made in the finalize_callback it will defer deletion
279
    // to this block and set _delete_self to true
280

2478
    if (_delete_self || is_env_teardown) {
281
1472
      Delete(this);
282
    } else {
283
1006
      _finalize_ran = true;
284
    }
285
2478
  }
286
287
 private:
288
  uint32_t _refcount;
289
  bool _delete_self;
290
};
291
292
9030
class Reference : public RefBase {
293
 protected:
294
  template <typename... Args>
295
3018
  Reference(napi_env env,
296
            v8::Local<v8::Value> value,
297
            Args&&... args)
298
15090
      : RefBase(env, std::forward<Args>(args)...),
299
15090
            _persistent(env->isolate, value) {
300
3018
    if (RefCount() == 0) {
301
2480
      _persistent.SetWeak(
302
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
303
    }
304
3018
  }
305
306
 public:
307
3018
  static inline Reference* New(napi_env env,
308
                             v8::Local<v8::Value> value,
309
                             uint32_t initial_refcount,
310
                             bool delete_self,
311
                             napi_finalize finalize_callback = nullptr,
312
                             void* finalize_data = nullptr,
313
                             void* finalize_hint = nullptr) {
314
    return new Reference(env,
315
                         value,
316
                         initial_refcount,
317
                         delete_self,
318
                         finalize_callback,
319
                         finalize_data,
320
3018
                         finalize_hint);
321
  }
322
323
1
  inline uint32_t Ref() {
324
1
    uint32_t refcount = RefBase::Ref();
325
1
    if (refcount == 1) {
326
      _persistent.ClearWeak();
327
    }
328
1
    return refcount;
329
  }
330
331
3
  inline uint32_t Unref() {
332
3
    uint32_t old_refcount = RefCount();
333
3
    uint32_t refcount = RefBase::Unref();
334

3
    if (old_refcount == 1 && refcount == 0) {
335
2
      _persistent.SetWeak(
336
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
337
    }
338
3
    return refcount;
339
  }
340
341
1550
  inline v8::Local<v8::Value> Get() {
342
3100
    if (_persistent.IsEmpty()) {
343
1002
      return v8::Local<v8::Value>();
344
    } else {
345
1096
      return v8::Local<v8::Value>::New(_env->isolate, _persistent);
346
    }
347
  }
348
349
 private:
350
  // The N-API finalizer callback may make calls into the engine. V8's heap is
351
  // not in a consistent state during the weak callback, and therefore it does
352
  // not support calls back into it. However, it provides a mechanism for adding
353
  // a finalizer which may make calls back into the engine by allowing us to
354
  // attach such a second-pass finalizer from the first pass finalizer. Thus,
355
  // we do that here to ensure that the N-API finalizer callback is free to call
356
  // into the engine.
357
2020
  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
358
2020
    Reference* reference = data.GetParameter();
359
360
    // The reference must be reset during the first pass.
361
2020
    reference->_persistent.Reset();
362
363
2020
    data.SetSecondPassCallback(SecondPassCallback);
364
2020
  }
365
366
2020
  static void SecondPassCallback(const v8::WeakCallbackInfo<Reference>& data) {
367
2020
    data.GetParameter()->Finalize();
368
2020
  }
369
370
  v8impl::Persistent<v8::Value> _persistent;
371
};
372
373
enum UnwrapAction {
374
  KeepWrap,
375
  RemoveWrap
376
};
377
378
35
inline static napi_status Unwrap(napi_env env,
379
                                 napi_value js_object,
380
                                 void** result,
381
                                 UnwrapAction action) {
382


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




3084
  NAPI_PREAMBLE(env);
590

1028
  CHECK_ARG(env, js_object);
591
592
1028
  v8::Local<v8::Context> context = env->context();
593
594
1028
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
595

1028
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
596
1028
  v8::Local<v8::Object> obj = value.As<v8::Object>();
597
598
  if (wrap_type == retrievable) {
599
    // If we've already wrapped this object, we error out.
600
3075
    RETURN_STATUS_IF_FALSE(env,
601
        !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
602
            .FromJust(),
603
        napi_invalid_arg);
604
  } else if (wrap_type == anonymous) {
605
    // If no finalize callback is provided, we error out.
606
3
    CHECK_ARG(env, finalize_cb);
607
  }
608
609
1027
  v8impl::Reference* reference = nullptr;
610

1027
  if (result != nullptr) {
611
    // The returned reference should be deleted via napi_delete_reference()
612
    // ONLY in response to the finalize callback invocation. (If it is deleted
613
    // before then, then the finalize callback will never be invoked.)
614
    // Therefore a finalize callback is required when returning a reference.
615

8
    CHECK_ARG(env, finalize_cb);
616
16
    reference = v8impl::Reference::New(
617
        env, obj, 0, false, finalize_cb, native_object, finalize_hint);
618
8
    *result = reinterpret_cast<napi_ref>(reference);
619
  } else {
620
    // Create a self-deleting reference.
621

2038
    reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb,
622
1019
        native_object, finalize_cb == nullptr ? nullptr : finalize_hint);
623
  }
624
625
  if (wrap_type == retrievable) {
626
4096
    CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper),
627
          v8::External::New(env->isolate, reference)).FromJust());
628
  }
629
630

1027
  return GET_RETURN_STATUS(env);
631
}
632
633
}  // end of anonymous namespace
634
635
}  // end of namespace v8impl
636
637
// Warning: Keep in-sync with napi_status enum
638
static
639
const char* error_messages[] = {nullptr,
640
                                "Invalid argument",
641
                                "An object was expected",
642
                                "A string was expected",
643
                                "A string or symbol was expected",
644
                                "A function was expected",
645
                                "A number was expected",
646
                                "A boolean was expected",
647
                                "An array was expected",
648
                                "Unknown failure",
649
                                "An exception is pending",
650
                                "The async work item was cancelled",
651
                                "napi_escape_handle already called on scope",
652
                                "Invalid handle scope usage",
653
                                "Invalid callback scope usage",
654
                                "Thread-safe function queue is full",
655
                                "Thread-safe function handle is closing",
656
                                "A bigint was expected",
657
                                "A date was expected",
658
                                "An arraybuffer was expected",
659
                                "A detachable arraybuffer was expected",
660
                                "Main thread would deadlock",
661
};
662
663
1300
napi_status napi_get_last_error_info(napi_env env,
664
                                     const napi_extended_error_info** result) {
665
1300
  CHECK_ENV(env);
666
1300
  CHECK_ARG(env, result);
667
668
  // The value of the constant below must be updated to reference the last
669
  // message in the `napi_status` enum each time a new error message is added.
670
  // We don't have a napi_status_last as this would result in an ABI
671
  // change each time a message was added.
672
1300
  const int last_status = napi_would_deadlock;
673
674
  static_assert(
675
      NAPI_ARRAYSIZE(error_messages) == last_status + 1,
676
      "Count of error messages must match count of error values");
677
1300
  CHECK_LE(env->last_error.error_code, last_status);
678
679
  // Wait until someone requests the last error information to fetch the error
680
  // message string
681
2600
  env->last_error.error_message =
682
1300
      error_messages[env->last_error.error_code];
683
684
1300
  *result = &(env->last_error);
685
1300
  return napi_ok;
686
}
687
688
15
napi_status napi_create_function(napi_env env,
689
                                 const char* utf8name,
690
                                 size_t length,
691
                                 napi_callback cb,
692
                                 void* callback_data,
693
                                 napi_value* result) {
694


45
  NAPI_PREAMBLE(env);
695
15
  CHECK_ARG(env, result);
696
15
  CHECK_ARG(env, cb);
697
698
  v8::Local<v8::Function> return_value;
699
15
  v8::EscapableHandleScope scope(env->isolate);
700
  v8::Local<v8::Function> fn;
701
15
  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
702
      env, cb, callback_data, &fn));
703
15
  return_value = scope.Escape(fn);
704
705
15
  if (utf8name != nullptr) {
706
    v8::Local<v8::String> name_string;
707

3
    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
708
3
    return_value->SetName(name_string);
709
6
  }
710
3
711
30
  *result = v8impl::JsValueFromV8LocalValue(return_value);
712
713
15
  return GET_RETURN_STATUS(env);
714
}
715
716
13
napi_status napi_define_class(napi_env env,
717
                              const char* utf8name,
718
                              size_t length,
719
                              napi_callback constructor,
720
                              void* callback_data,
721
                              size_t property_count,
722
                              const napi_property_descriptor* properties,
723
                              napi_value* result) {
724


37
  NAPI_PREAMBLE(env);
725
12
  CHECK_ARG(env, result);
726
11
  CHECK_ARG(env, constructor);
727
728
10
  if (property_count > 0) {
729
7
    CHECK_ARG(env, properties);
730
  }
731
732
9
  v8::Isolate* isolate = env->isolate;
733
734
9
  v8::EscapableHandleScope scope(isolate);
735
  v8::Local<v8::FunctionTemplate> tpl;
736
9
  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
737
      env, constructor, callback_data, &tpl));
738
739
  v8::Local<v8::String> name_string;
740

10
  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
741
9
  tpl->SetClassName(name_string);
742
16
743
16
  size_t static_property_count = 0;
744
72
  for (size_t i = 0; i < property_count; i++) {
745
28
    const napi_property_descriptor* p = properties + i;
746
747
28
    if ((p->attributes & napi_static) != 0) {
748
      // Static properties are handled separately below.
749
7
      static_property_count++;
750
7
      continue;
751
    }
752
753
    v8::Local<v8::Name> property_name;
754
21
    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
755
756
    v8::PropertyAttribute attributes =
757
21
        v8impl::V8PropertyAttributesFromDescriptor(p);
758
759
    // This code is similar to that in napi_define_properties(); the
760
    // difference is it applies to a template instead of an object,
761
    // and preferred PropertyAttribute for lack of PropertyDescriptor
762
    // support on ObjectTemplate.
763

21
    if (p->getter != nullptr || p->setter != nullptr) {
764
      v8::Local<v8::FunctionTemplate> getter_tpl;
765
      v8::Local<v8::FunctionTemplate> setter_tpl;
766
10
      if (p->getter != nullptr) {
767
10
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
768
            env, p->getter, p->data, &getter_tpl));
769
      }
770
10
      if (p->setter != nullptr) {
771
5
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
772
            env, p->setter, p->data, &setter_tpl));
773
      }
774
775
30
      tpl->PrototypeTemplate()->SetAccessorProperty(
776
        property_name,
777
        getter_tpl,
778
        setter_tpl,
779
        attributes,
780
20
        v8::AccessControl::DEFAULT);
781
11
    } else if (p->method != nullptr) {
782
      v8::Local<v8::FunctionTemplate> t;
783
5
      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
784
          env, p->method, p->data, &t, v8::Signature::New(isolate, tpl)));
785
786
10
      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
787
    } else {
788
6
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
789
12
      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
790
    }
791
  }
792
793
8
  v8::Local<v8::Context> context = env->context();
794
16
  *result = v8impl::JsValueFromV8LocalValue(
795
16
      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
796
797
8
  if (static_property_count > 0) {
798
6
    std::vector<napi_property_descriptor> static_descriptors;
799
3
    static_descriptors.reserve(static_property_count);
800
801
26
    for (size_t i = 0; i < property_count; i++) {
802
23
      const napi_property_descriptor* p = properties + i;
803
23
      if ((p->attributes & napi_static) != 0) {
804
7
        static_descriptors.push_back(*p);
805
      }
806
    }
807
808

3
    STATUS_CALL(napi_define_properties(env,
809
                                       *result,
810
                                       static_descriptors.size(),
811
                                       static_descriptors.data()));
812
  }
813
814
8
  return GET_RETURN_STATUS(env);
815
}
816
817
8
napi_status napi_get_property_names(napi_env env,
818
                                    napi_value object,
819
                                    napi_value* result) {
820
  return napi_get_all_property_names(
821
      env,
822
      object,
823
      napi_key_include_prototypes,
824
      static_cast<napi_key_filter>(napi_key_enumerable |
825
                                   napi_key_skip_symbols),
826
      napi_key_numbers_to_strings,
827
8
      result);
828
}
829
830
12
napi_status napi_get_all_property_names(napi_env env,
831
                                        napi_value object,
832
                                        napi_key_collection_mode key_mode,
833
                                        napi_key_filter key_filter,
834
                                        napi_key_conversion key_conversion,
835
                                        napi_value* result) {
836


32
  NAPI_PREAMBLE(env);
837
10
  CHECK_ARG(env, result);
838
839
8
  v8::Local<v8::Context> context = env->context();
840
  v8::Local<v8::Object> obj;
841

28
  CHECK_TO_OBJECT(env, context, obj, object);
842
843
6
  v8::PropertyFilter filter = v8::PropertyFilter::ALL_PROPERTIES;
844
6
  if (key_filter & napi_key_writable) {
845
    filter =
846
        static_cast<v8::PropertyFilter>(filter |
847
                                        v8::PropertyFilter::ONLY_WRITABLE);
848
  }
849
6
  if (key_filter & napi_key_enumerable) {
850
5
    filter =
851
5
        static_cast<v8::PropertyFilter>(filter |
852
                                        v8::PropertyFilter::ONLY_ENUMERABLE);
853
  }
854
6
  if (key_filter & napi_key_configurable) {
855
    filter =
856
        static_cast<v8::PropertyFilter>(filter |
857
                                        v8::PropertyFilter::ONLY_WRITABLE);
858
  }
859
6
  if (key_filter & napi_key_skip_strings) {
860
1
    filter =
861
1
        static_cast<v8::PropertyFilter>(filter |
862
                                        v8::PropertyFilter::SKIP_STRINGS);
863
  }
864
6
  if (key_filter & napi_key_skip_symbols) {
865
5
    filter =
866
5
        static_cast<v8::PropertyFilter>(filter |
867
                                        v8::PropertyFilter::SKIP_SYMBOLS);
868
  }
869
  v8::KeyCollectionMode collection_mode;
870
  v8::KeyConversionMode conversion_mode;
871
872
6
  switch (key_mode) {
873
    case napi_key_include_prototypes:
874
6
      collection_mode = v8::KeyCollectionMode::kIncludePrototypes;
875
6
      break;
876
    case napi_key_own_only:
877
      collection_mode = v8::KeyCollectionMode::kOwnOnly;
878
      break;
879
    default:
880
      return napi_set_last_error(env, napi_invalid_arg);
881
  }
882
883
6
  switch (key_conversion) {
884
    case napi_key_keep_numbers:
885
      conversion_mode = v8::KeyConversionMode::kKeepNumbers;
886
      break;
887
    case napi_key_numbers_to_strings:
888
6
      conversion_mode = v8::KeyConversionMode::kConvertToString;
889
6
      break;
890
    default:
891
      return napi_set_last_error(env, napi_invalid_arg);
892
  }
893
894
  v8::MaybeLocal<v8::Array> maybe_all_propertynames =
895
      obj->GetPropertyNames(context,
896
                            collection_mode,
897
                            filter,
898
                            v8::IndexFilter::kIncludeIndices,
899
6
                            conversion_mode);
900
901

6
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(
902
      env, maybe_all_propertynames, napi_generic_failure);
903
904
12
  *result =
905
12
      v8impl::JsValueFromV8LocalValue(maybe_all_propertynames.ToLocalChecked());
906
6
  return GET_RETURN_STATUS(env);
907
}
908
909
26
napi_status napi_set_property(napi_env env,
910
                              napi_value object,
911
                              napi_value key,
912
                              napi_value value) {
913


74
  NAPI_PREAMBLE(env);
914
24
  CHECK_ARG(env, key);
915
21
  CHECK_ARG(env, value);
916
917
19
  v8::Local<v8::Context> context = env->context();
918
  v8::Local<v8::Object> obj;
919
920

72
  CHECK_TO_OBJECT(env, context, obj, object);
921
922
17
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
923
17
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
924
925
17
  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
926
927
34
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
928
17
  return GET_RETURN_STATUS(env);
929
}
930
931
16
napi_status napi_has_property(napi_env env,
932
                              napi_value object,
933
                              napi_value key,
934
                              bool* result) {
935


44
  NAPI_PREAMBLE(env);
936
14
  CHECK_ARG(env, result);
937
12
  CHECK_ARG(env, key);
938
939
10
  v8::Local<v8::Context> context = env->context();
940
  v8::Local<v8::Object> obj;
941
942

36
  CHECK_TO_OBJECT(env, context, obj, object);
943
944
8
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
945
8
  v8::Maybe<bool> has_maybe = obj->Has(context, k);
946
947
8
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
948
949
16
  *result = has_maybe.FromMaybe(false);
950
8
  return GET_RETURN_STATUS(env);
951
}
952
953
34
napi_status napi_get_property(napi_env env,
954
                              napi_value object,
955
                              napi_value key,
956
                              napi_value* result) {
957


98
  NAPI_PREAMBLE(env);
958
32
  CHECK_ARG(env, key);
959
28
  CHECK_ARG(env, result);
960
961
26
  v8::Local<v8::Context> context = env->context();
962
26
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
963
  v8::Local<v8::Object> obj;
964
965

100
  CHECK_TO_OBJECT(env, context, obj, object);
966
967
24
  auto get_maybe = obj->Get(context, k);
968
969
24
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
970
971
24
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
972
24
  *result = v8impl::JsValueFromV8LocalValue(val);
973
24
  return GET_RETURN_STATUS(env);
974
}
975
976
9
napi_status napi_delete_property(napi_env env,
977
                                 napi_value object,
978
                                 napi_value key,
979
                                 bool* result) {
980


25
  NAPI_PREAMBLE(env);
981
8
  CHECK_ARG(env, key);
982
983
7
  v8::Local<v8::Context> context = env->context();
984
7
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
985
  v8::Local<v8::Object> obj;
986
987

26
  CHECK_TO_OBJECT(env, context, obj, object);
988
6
  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
989
6
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
990
991
6
  if (result != nullptr)
992
10
    *result = delete_maybe.FromMaybe(false);
993
994
6
  return GET_RETURN_STATUS(env);
995
}
996
997
19
napi_status napi_has_own_property(napi_env env,
998
                                  napi_value object,
999
                                  napi_value key,
1000
                                  bool* result) {
1001


55
  NAPI_PREAMBLE(env);
1002
18
  CHECK_ARG(env, key);
1003
17
  CHECK_ARG(env, result);
1004
1005
16
  v8::Local<v8::Context> context = env->context();
1006
  v8::Local<v8::Object> obj;
1007
1008

62
  CHECK_TO_OBJECT(env, context, obj, object);
1009
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1010
24
  RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected);
1011
6
  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
1012
6
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1013
12
  *result = has_maybe.FromMaybe(false);
1014
1015
6
  return GET_RETURN_STATUS(env);
1016
}
1017
1018
153
napi_status napi_set_named_property(napi_env env,
1019
                                    napi_value object,
1020
                                    const char* utf8name,
1021
                                    napi_value value) {
1022


457
  NAPI_PREAMBLE(env);
1023
152
  CHECK_ARG(env, value);
1024
1025
151
  v8::Local<v8::Context> context = env->context();
1026
  v8::Local<v8::Object> obj;
1027
1028

602
  CHECK_TO_OBJECT(env, context, obj, object);
1029
1030
  v8::Local<v8::Name> key;
1031

449
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1032
1033
149
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1034
1035
149
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1036
1037
298
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1038
149
  return GET_RETURN_STATUS(env);
1039
}
1040
1041
9
napi_status napi_has_named_property(napi_env env,
1042
                                    napi_value object,
1043
                                    const char* utf8name,
1044
                                    bool* result) {
1045


25
  NAPI_PREAMBLE(env);
1046
8
  CHECK_ARG(env, result);
1047
1048
7
  v8::Local<v8::Context> context = env->context();
1049
  v8::Local<v8::Object> obj;
1050
1051

26
  CHECK_TO_OBJECT(env, context, obj, object);
1052
1053
  v8::Local<v8::Name> key;
1054

17
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1055
1056
5
  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1057
1058
5
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1059
1060
10
  *result = has_maybe.FromMaybe(false);
1061
5
  return GET_RETURN_STATUS(env);
1062
}
1063
1064
5
napi_status napi_get_named_property(napi_env env,
1065
                                    napi_value object,
1066
                                    const char* utf8name,
1067
                                    napi_value* result) {
1068


13
  NAPI_PREAMBLE(env);
1069
4
  CHECK_ARG(env, result);
1070
1071
3
  v8::Local<v8::Context> context = env->context();
1072
1073
  v8::Local<v8::Name> key;
1074

8
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1075
1076
  v8::Local<v8::Object> obj;
1077
1078

7
  CHECK_TO_OBJECT(env, context, obj, object);
1079
1080
1
  auto get_maybe = obj->Get(context, key);
1081
1082
1
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1083
1084
1
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1085
1
  *result = v8impl::JsValueFromV8LocalValue(val);
1086
1
  return GET_RETURN_STATUS(env);
1087
}
1088
1089
13
napi_status napi_set_element(napi_env env,
1090
                             napi_value object,
1091
                             uint32_t index,
1092
                             napi_value value) {
1093


37
  NAPI_PREAMBLE(env);
1094
12
  CHECK_ARG(env, value);
1095
1096
12
  v8::Local<v8::Context> context = env->context();
1097
  v8::Local<v8::Object> obj;
1098
1099

46
  CHECK_TO_OBJECT(env, context, obj, object);
1100
1101
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1102
11
  auto set_maybe = obj->Set(context, index, val);
1103
1104
22
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1105
1106
11
  return GET_RETURN_STATUS(env);
1107
}
1108
1109
5
napi_status napi_has_element(napi_env env,
1110
                             napi_value object,
1111
                             uint32_t index,
1112
                             bool* result) {
1113


13
  NAPI_PREAMBLE(env);
1114
4
  CHECK_ARG(env, result);
1115
1116
3
  v8::Local<v8::Context> context = env->context();
1117
  v8::Local<v8::Object> obj;
1118
1119

10
  CHECK_TO_OBJECT(env, context, obj, object);
1120
1121
2
  v8::Maybe<bool> has_maybe = obj->Has(context, index);
1122
1123
2
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1124
1125
4
  *result = has_maybe.FromMaybe(false);
1126
2
  return GET_RETURN_STATUS(env);
1127
}
1128
1129
28
napi_status napi_get_element(napi_env env,
1130
                             napi_value object,
1131
                             uint32_t index,
1132
                             napi_value* result) {
1133


82
  NAPI_PREAMBLE(env);
1134
27
  CHECK_ARG(env, result);
1135
1136
27
  v8::Local<v8::Context> context = env->context();
1137
  v8::Local<v8::Object> obj;
1138
1139

108
  CHECK_TO_OBJECT(env, context, obj, object);
1140
1141
27
  auto get_maybe = obj->Get(context, index);
1142
1143
27
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1144
1145
54
  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
1146
27
  return GET_RETURN_STATUS(env);
1147
}
1148
1149
4
napi_status napi_delete_element(napi_env env,
1150
                                napi_value object,
1151
                                uint32_t index,
1152
                                bool* result) {
1153


10
  NAPI_PREAMBLE(env);
1154
1155
3
  v8::Local<v8::Context> context = env->context();
1156
  v8::Local<v8::Object> obj;
1157
1158

10
  CHECK_TO_OBJECT(env, context, obj, object);
1159
2
  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
1160
2
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1161
1162
2
  if (result != nullptr)
1163
2
    *result = delete_maybe.FromMaybe(false);
1164
1165
2
  return GET_RETURN_STATUS(env);
1166
}
1167
1168
78
napi_status napi_define_properties(napi_env env,
1169
                                   napi_value object,
1170
                                   size_t property_count,
1171
                                   const napi_property_descriptor* properties) {
1172


232
  NAPI_PREAMBLE(env);
1173
77
  if (property_count > 0) {
1174
77
    CHECK_ARG(env, properties);
1175
  }
1176
1177
74
  v8::Local<v8::Context> context = env->context();
1178
1179
  v8::Local<v8::Object> obj;
1180

294
  CHECK_TO_OBJECT(env, context, obj, object);
1181
1182
976
  for (size_t i = 0; i < property_count; i++) {
1183
415
    const napi_property_descriptor* p = &properties[i];
1184
1185
    v8::Local<v8::Name> property_name;
1186
415
    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
1187
1188

415
    if (p->getter != nullptr || p->setter != nullptr) {
1189
      v8::Local<v8::Function> local_getter;
1190
      v8::Local<v8::Function> local_setter;
1191
1192
10
      if (p->getter != nullptr) {
1193
10
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1194
            env, p->getter, p->data, &local_getter));
1195
      }
1196
10
      if (p->setter != nullptr) {
1197
2
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1198
            env, p->setter, p->data, &local_setter));
1199
      }
1200
1201
20
      v8::PropertyDescriptor descriptor(local_getter, local_setter);
1202
10
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1203
10
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1204
1205
      auto define_maybe = obj->DefineProperty(context,
1206
                                              property_name,
1207
10
                                              descriptor);
1208
1209
20
      if (!define_maybe.FromMaybe(false)) {
1210
        return napi_set_last_error(env, napi_invalid_arg);
1211
10
      }
1212
405
    } else if (p->method != nullptr) {
1213
      v8::Local<v8::Function> method;
1214
389
      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1215
          env, p->method, p->data, &method));
1216
      v8::PropertyDescriptor descriptor(method,
1217
1167
                                        (p->attributes & napi_writable) != 0);
1218
389
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1219
389
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1220
1221
      auto define_maybe = obj->DefineProperty(context,
1222
                                              property_name,
1223
389
                                              descriptor);
1224
1225
778
      if (!define_maybe.FromMaybe(false)) {
1226
        return napi_set_last_error(env, napi_generic_failure);
1227
      }
1228
    } else {
1229
16
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1230
1231
      v8::PropertyDescriptor descriptor(value,
1232
32
                                        (p->attributes & napi_writable) != 0);
1233
16
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1234
16
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1235
1236
      auto define_maybe =
1237
16
          obj->DefineProperty(context, property_name, descriptor);
1238
1239
32
      if (!define_maybe.FromMaybe(false)) {
1240
        return napi_set_last_error(env, napi_invalid_arg);
1241
      }
1242
    }
1243
  }
1244
1245
73
  return GET_RETURN_STATUS(env);
1246
}
1247
1248
1
napi_status napi_object_freeze(napi_env env,
1249
                               napi_value object) {
1250


3
  NAPI_PREAMBLE(env);
1251
1252
1
  v8::Local<v8::Context> context = env->context();
1253
  v8::Local<v8::Object> obj;
1254
1255

4
  CHECK_TO_OBJECT(env, context, obj, object);
1256
1257
  v8::Maybe<bool> set_frozen =
1258
1
    obj->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen);
1259
1260

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
1261
    set_frozen.FromMaybe(false), napi_generic_failure);
1262
1263
1
  return GET_RETURN_STATUS(env);
1264
}
1265
1266
1
napi_status napi_object_seal(napi_env env,
1267
                             napi_value object) {
1268


3
  NAPI_PREAMBLE(env);
1269
1270
1
  v8::Local<v8::Context> context = env->context();
1271
  v8::Local<v8::Object> obj;
1272
1273

4
  CHECK_TO_OBJECT(env, context, obj, object);
1274
1275
  v8::Maybe<bool> set_sealed =
1276
1
    obj->SetIntegrityLevel(context, v8::IntegrityLevel::kSealed);
1277
1278

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
1279
    set_sealed.FromMaybe(false), napi_generic_failure);
1280
1281
1
  return GET_RETURN_STATUS(env);
1282
}
1283
1284
11
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1285
11
  CHECK_ENV(env);
1286
11
  CHECK_ARG(env, value);
1287
11
  CHECK_ARG(env, result);
1288
1289
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1290
1291
22
  *result = val->IsArray();
1292
11
  return napi_clear_last_error(env);
1293
}
1294
1295
13
napi_status napi_get_array_length(napi_env env,
1296
                                  napi_value value,
1297
                                  uint32_t* result) {
1298


39
  NAPI_PREAMBLE(env);
1299
13
  CHECK_ARG(env, value);
1300
13
  CHECK_ARG(env, result);
1301
1302
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1303
13
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1304
1305
13
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1306
26
  *result = arr->Length();
1307
1308
13
  return GET_RETURN_STATUS(env);
1309
}
1310
1311
9
napi_status napi_strict_equals(napi_env env,
1312
                               napi_value lhs,
1313
                               napi_value rhs,
1314
                               bool* result) {
1315


27
  NAPI_PREAMBLE(env);
1316
9
  CHECK_ARG(env, lhs);
1317
9
  CHECK_ARG(env, rhs);
1318
9
  CHECK_ARG(env, result);
1319
1320
9
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1321
9
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1322
1323
18
  *result = a->StrictEquals(b);
1324
9
  return GET_RETURN_STATUS(env);
1325
}
1326
1327
7
napi_status napi_get_prototype(napi_env env,
1328
                               napi_value object,
1329
                               napi_value* result) {
1330


19
  NAPI_PREAMBLE(env);
1331
6
  CHECK_ARG(env, result);
1332
1333
5
  v8::Local<v8::Context> context = env->context();
1334
1335
  v8::Local<v8::Object> obj;
1336

18
  CHECK_TO_OBJECT(env, context, obj, object);
1337
1338
4
  v8::Local<v8::Value> val = obj->GetPrototype();
1339
4
  *result = v8impl::JsValueFromV8LocalValue(val);
1340
4
  return GET_RETURN_STATUS(env);
1341
}
1342
1343
64
napi_status napi_create_object(napi_env env, napi_value* result) {
1344
64
  CHECK_ENV(env);
1345
64
  CHECK_ARG(env, result);
1346
1347
192
  *result = v8impl::JsValueFromV8LocalValue(
1348
64
      v8::Object::New(env->isolate));
1349
1350
64
  return napi_clear_last_error(env);
1351
}
1352
1353
1
napi_status napi_create_array(napi_env env, napi_value* result) {
1354
1
  CHECK_ENV(env);
1355
1
  CHECK_ARG(env, result);
1356
1357
3
  *result = v8impl::JsValueFromV8LocalValue(
1358
1
      v8::Array::New(env->isolate));
1359
1360
1
  return napi_clear_last_error(env);
1361
}
1362
1363
4
napi_status napi_create_array_with_length(napi_env env,
1364
                                          size_t length,
1365
                                          napi_value* result) {
1366
4
  CHECK_ENV(env);
1367
4
  CHECK_ARG(env, result);
1368
1369
12
  *result = v8impl::JsValueFromV8LocalValue(
1370
4
      v8::Array::New(env->isolate, length));
1371
1372
4
  return napi_clear_last_error(env);
1373
}
1374
1375
12
napi_status napi_create_string_latin1(napi_env env,
1376
                                      const char* str,
1377
                                      size_t length,
1378
                                      napi_value* result) {
1379
12
  CHECK_ENV(env);
1380
12
  CHECK_ARG(env, result);
1381

12
  RETURN_STATUS_IF_FALSE(env,
1382
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1383
      napi_invalid_arg);
1384
1385
11
  auto isolate = env->isolate;
1386
  auto str_maybe =
1387
      v8::String::NewFromOneByte(isolate,
1388
                                 reinterpret_cast<const uint8_t*>(str),
1389
                                 v8::NewStringType::kNormal,
1390
11
                                 length);
1391
11
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1392
1393
22
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1394
11
  return napi_clear_last_error(env);
1395
}
1396
1397
720
napi_status napi_create_string_utf8(napi_env env,
1398
                                    const char* str,
1399
                                    size_t length,
1400
                                    napi_value* result) {
1401
720
  CHECK_ENV(env);
1402
720
  CHECK_ARG(env, result);
1403

720
  RETURN_STATUS_IF_FALSE(env,
1404
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1405
      napi_invalid_arg);
1406
1407
719
  auto isolate = env->isolate;
1408
  auto str_maybe =
1409
      v8::String::NewFromUtf8(isolate,
1410
                              str,
1411
                              v8::NewStringType::kNormal,
1412
719
                              static_cast<int>(length));
1413
719
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1414
1438
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1415
719
  return napi_clear_last_error(env);
1416
}
1417
1418
14
napi_status napi_create_string_utf16(napi_env env,
1419
                                     const char16_t* str,
1420
                                     size_t length,
1421
                                     napi_value* result) {
1422
14
  CHECK_ENV(env);
1423
14
  CHECK_ARG(env, result);
1424

14
  RETURN_STATUS_IF_FALSE(env,
1425
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1426
      napi_invalid_arg);
1427
1428
13
  auto isolate = env->isolate;
1429
  auto str_maybe =
1430
      v8::String::NewFromTwoByte(isolate,
1431
                                 reinterpret_cast<const uint16_t*>(str),
1432
                                 v8::NewStringType::kNormal,
1433
13
                                 length);
1434
13
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1435
1436
26
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1437
13
  return napi_clear_last_error(env);
1438
}
1439
1440
71
napi_status napi_create_double(napi_env env,
1441
                               double value,
1442
                               napi_value* result) {
1443
71
  CHECK_ENV(env);
1444
71
  CHECK_ARG(env, result);
1445
1446
213
  *result = v8impl::JsValueFromV8LocalValue(
1447
71
      v8::Number::New(env->isolate, value));
1448
1449
71
  return napi_clear_last_error(env);
1450
}
1451
1452
162
napi_status napi_create_int32(napi_env env,
1453
                              int32_t value,
1454
                              napi_value* result) {
1455
162
  CHECK_ENV(env);
1456
162
  CHECK_ARG(env, result);
1457
1458
486
  *result = v8impl::JsValueFromV8LocalValue(
1459
162
      v8::Integer::New(env->isolate, value));
1460
1461
162
  return napi_clear_last_error(env);
1462
}
1463
1464
555
napi_status napi_create_uint32(napi_env env,
1465
                               uint32_t value,
1466
                               napi_value* result) {
1467
555
  CHECK_ENV(env);
1468
555
  CHECK_ARG(env, result);
1469
1470
1665
  *result = v8impl::JsValueFromV8LocalValue(
1471
555
      v8::Integer::NewFromUnsigned(env->isolate, value));
1472
1473
555
  return napi_clear_last_error(env);
1474
}
1475
1476
24
napi_status napi_create_int64(napi_env env,
1477
                              int64_t value,
1478
                              napi_value* result) {
1479
24
  CHECK_ENV(env);
1480
24
  CHECK_ARG(env, result);
1481
1482
72
  *result = v8impl::JsValueFromV8LocalValue(
1483
24
      v8::Number::New(env->isolate, static_cast<double>(value)));
1484
1485
24
  return napi_clear_last_error(env);
1486
}
1487
1488
9
napi_status napi_create_bigint_int64(napi_env env,
1489
                                     int64_t value,
1490
                                     napi_value* result) {
1491
9
  CHECK_ENV(env);
1492
9
  CHECK_ARG(env, result);
1493
1494
27
  *result = v8impl::JsValueFromV8LocalValue(
1495
9
      v8::BigInt::New(env->isolate, value));
1496
1497
9
  return napi_clear_last_error(env);
1498
}
1499
1500
6
napi_status napi_create_bigint_uint64(napi_env env,
1501
                                      uint64_t value,
1502
                                      napi_value* result) {
1503
6
  CHECK_ENV(env);
1504
6
  CHECK_ARG(env, result);
1505
1506
18
  *result = v8impl::JsValueFromV8LocalValue(
1507
6
      v8::BigInt::NewFromUnsigned(env->isolate, value));
1508
1509
6
  return napi_clear_last_error(env);
1510
}
1511
1512
13
napi_status napi_create_bigint_words(napi_env env,
1513
                                     int sign_bit,
1514
                                     size_t word_count,
1515
                                     const uint64_t* words,
1516
                                     napi_value* result) {
1517


39
  NAPI_PREAMBLE(env);
1518
13
  CHECK_ARG(env, words);
1519
13
  CHECK_ARG(env, result);
1520
1521
13
  v8::Local<v8::Context> context = env->context();
1522
1523
13
  RETURN_STATUS_IF_FALSE(
1524
      env, word_count <= INT_MAX, napi_invalid_arg);
1525
1526
  v8::MaybeLocal<v8::BigInt> b = v8::BigInt::NewFromWords(
1527
12
      context, sign_bit, word_count, words);
1528
1529

12
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, b, napi_generic_failure);
1530
1531
22
  *result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
1532
11
  return GET_RETURN_STATUS(env);
1533
}
1534
1535
1292
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
1536
1292
  CHECK_ENV(env);
1537
1292
  CHECK_ARG(env, result);
1538
1539
1292
  v8::Isolate* isolate = env->isolate;
1540
1541
1292
  if (value) {
1542
1460
    *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
1543
  } else {
1544
1124
    *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
1545
  }
1546
1547
1292
  return napi_clear_last_error(env);
1548
}
1549
1550
13
napi_status napi_create_symbol(napi_env env,
1551
                               napi_value description,
1552
                               napi_value* result) {
1553
13
  CHECK_ENV(env);
1554
13
  CHECK_ARG(env, result);
1555
1556
13
  v8::Isolate* isolate = env->isolate;
1557
1558
13
  if (description == nullptr) {
1559
6
    *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
1560
  } else {
1561
11
    v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
1562
22
    RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
1563
1564
33
    *result = v8impl::JsValueFromV8LocalValue(
1565
      v8::Symbol::New(isolate, desc.As<v8::String>()));
1566
  }
1567
1568
13
  return napi_clear_last_error(env);
1569
}
1570
1571
194
static inline napi_status set_error_code(napi_env env,
1572
                                         v8::Local<v8::Value> error,
1573
                                         napi_value code,
1574
                                         const char* code_cstring) {
1575

194
  if ((code != nullptr) || (code_cstring != nullptr)) {
1576
116
    v8::Local<v8::Context> context = env->context();
1577
116
    v8::Local<v8::Object> err_object = error.As<v8::Object>();
1578
1579
116
    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1580
116
    if (code != nullptr) {
1581
5
      code_value = v8impl::V8LocalValueFromJsValue(code);
1582
10
      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1583
    } else {
1584

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


1963
  NAPI_PREAMBLE(env);
1774
653
  CHECK_ARG(env, recv);
1775
653
  if (argc > 0) {
1776
602
    CHECK_ARG(env, argv);
1777
  }
1778
1779
653
  v8::Local<v8::Context> context = env->context();
1780
1781
653
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1782
1783
  v8::Local<v8::Function> v8func;
1784

1959
  CHECK_TO_FUNCTION(env, v8func, func);
1785
1786
  auto maybe = v8func->Call(context, v8recv, argc,
1787
1306
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1788
1789
653
  if (try_catch.HasCaught()) {
1790
6
    return napi_set_last_error(env, napi_pending_exception);
1791
  } else {
1792
647
    if (result != nullptr) {
1793
7
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1794
7
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1795
    }
1796
647
    return napi_clear_last_error(env);
1797
  }
1798
}
1799
1800
10
napi_status napi_get_global(napi_env env, napi_value* result) {
1801
10
  CHECK_ENV(env);
1802
10
  CHECK_ARG(env, result);
1803
1804
30
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1805
1806
10
  return napi_clear_last_error(env);
1807
}
1808
1809
12
napi_status napi_throw(napi_env env, napi_value error) {
1810


36
  NAPI_PREAMBLE(env);
1811
12
  CHECK_ARG(env, error);
1812
1813
12
  v8::Isolate* isolate = env->isolate;
1814
1815
12
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1816
  // any VM calls after this point and before returning
1817
  // to the javascript invoker will fail
1818
12
  return napi_clear_last_error(env);
1819
}
1820
1821
78
napi_status napi_throw_error(napi_env env,
1822
                             const char* code,
1823
                             const char* msg) {
1824


229
  NAPI_PREAMBLE(env);
1825
1826
73
  v8::Isolate* isolate = env->isolate;
1827
  v8::Local<v8::String> str;
1828

219
  CHECK_NEW_FROM_UTF8(env, str, msg);
1829
1830
73
  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1831
73
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1832
1833
73
  isolate->ThrowException(error_obj);
1834
  // any VM calls after this point and before returning
1835
  // to the javascript invoker will fail
1836
73
  return napi_clear_last_error(env);
1837
}
1838
1839
90
napi_status napi_throw_type_error(napi_env env,
1840
                                  const char* code,
1841
                                  const char* msg) {
1842


270
  NAPI_PREAMBLE(env);
1843
1844
90
  v8::Isolate* isolate = env->isolate;
1845
  v8::Local<v8::String> str;
1846

270
  CHECK_NEW_FROM_UTF8(env, str, msg);
1847
1848
90
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1849
90
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1850
1851
90
  isolate->ThrowException(error_obj);
1852
  // any VM calls after this point and before returning
1853
  // to the javascript invoker will fail
1854
90
  return napi_clear_last_error(env);
1855
}
1856
1857
22
napi_status napi_throw_range_error(napi_env env,
1858
                                   const char* code,
1859
                                   const char* msg) {
1860


66
  NAPI_PREAMBLE(env);
1861
1862
22
  v8::Isolate* isolate = env->isolate;
1863
  v8::Local<v8::String> str;
1864

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

22
  if (sign_bit == nullptr && words == nullptr) {
2041
11
    word_count_int = big->WordCount();
2042
  } else {
2043
11
    CHECK_ARG(env, sign_bit);
2044
11
    CHECK_ARG(env, words);
2045
22
    big->ToWordsArray(sign_bit, &word_count_int, words);
2046
  }
2047
2048
22
  *word_count = word_count_int;
2049
2050
22
  return napi_clear_last_error(env);
2051
}
2052
2053
88
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) {
2054
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2055
  // JS exceptions.
2056
88
  CHECK_ENV(env);
2057
87
  CHECK_ARG(env, value);
2058
86
  CHECK_ARG(env, result);
2059
2060
85
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2061
85
  RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected);
2062
2063
216
  *result = val.As<v8::Boolean>()->Value();
2064
2065
72
  return napi_clear_last_error(env);
2066
}
2067
2068
// Copies a JavaScript string into a LATIN-1 string buffer. The result is the
2069
// number of bytes (excluding the null terminator) copied into buf.
2070
// A sufficient buffer size should be greater than the length of string,
2071
// reserving space for null terminator.
2072
// If bufsize is insufficient, the string will be truncated and null terminated.
2073
// If buf is NULL, this method returns the length of the string (in bytes)
2074
// via the result parameter.
2075
// The result argument is optional unless buf is NULL.
2076
15
napi_status napi_get_value_string_latin1(napi_env env,
2077
                                         napi_value value,
2078
                                         char* buf,
2079
                                         size_t bufsize,
2080
                                         size_t* result) {
2081
15
  CHECK_ENV(env);
2082
14
  CHECK_ARG(env, value);
2083
2084
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2085
26
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2086
2087
12
  if (!buf) {
2088
1
    CHECK_ARG(env, result);
2089
    *result = val.As<v8::String>()->Length();
2090
11
  } else if (bufsize != 0) {
2091
    int copied =
2092
44
        val.As<v8::String>()->WriteOneByte(env->isolate,
2093
                                           reinterpret_cast<uint8_t*>(buf),
2094
                                           0,
2095
11
                                           bufsize - 1,
2096
11
                                           v8::String::NO_NULL_TERMINATION);
2097
2098
11
    buf[copied] = '\0';
2099
11
    if (result != nullptr) {
2100
11
      *result = copied;
2101
    }
2102
  } else if (result != nullptr) {
2103
    *result = 0;
2104
  }
2105
2106
11
  return napi_clear_last_error(env);
2107
}
2108
2109
// Copies a JavaScript string into a UTF-8 string buffer. The result is the
2110
// number of bytes (excluding the null terminator) copied into buf.
2111
// A sufficient buffer size should be greater than the length of string,
2112
// reserving space for null terminator.
2113
// If bufsize is insufficient, the string will be truncated and null terminated.
2114
// If buf is NULL, this method returns the length of the string (in bytes)
2115
// via the result parameter.
2116
// The result argument is optional unless buf is NULL.
2117
43
napi_status napi_get_value_string_utf8(napi_env env,
2118
                                       napi_value value,
2119
                                       char* buf,
2120
                                       size_t bufsize,
2121
                                       size_t* result) {
2122
43
  CHECK_ENV(env);
2123
42
  CHECK_ARG(env, value);
2124
2125
41
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2126
82
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2127
2128
31
  if (!buf) {
2129
8
    CHECK_ARG(env, result);
2130
21
    *result = val.As<v8::String>()->Utf8Length(env->isolate);
2131
23
  } else if (bufsize != 0) {
2132
88
    int copied = val.As<v8::String>()->WriteUtf8(
2133
22
        env->isolate,
2134
        buf,
2135
22
        bufsize - 1,
2136
        nullptr,
2137
22
        v8::String::REPLACE_INVALID_UTF8 | v8::String::NO_NULL_TERMINATION);
2138
2139
22
    buf[copied] = '\0';
2140
22
    if (result != nullptr) {
2141
20
      *result = copied;
2142
    }
2143
1
  } else if (result != nullptr) {
2144
    *result = 0;
2145
  }
2146
2147
30
  return napi_clear_last_error(env);
2148
}
2149
2150
// Copies a JavaScript string into a UTF-16 string buffer. The result is the
2151
// number of 2-byte code units (excluding the null terminator) copied into buf.
2152
// A sufficient buffer size should be greater than the length of string,
2153
// reserving space for null terminator.
2154
// If bufsize is insufficient, the string will be truncated and null terminated.
2155
// If buf is NULL, this method returns the length of the string (in 2-byte
2156
// code units) via the result parameter.
2157
// The result argument is optional unless buf is NULL.
2158
24
napi_status napi_get_value_string_utf16(napi_env env,
2159
                                        napi_value value,
2160
                                        char16_t* buf,
2161
                                        size_t bufsize,
2162
                                        size_t* result) {
2163
24
  CHECK_ENV(env);
2164
23
  CHECK_ARG(env, value);
2165
2166
22
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2167
44
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2168
2169
21
  if (!buf) {
2170
8
    CHECK_ARG(env, result);
2171
    // V8 assumes UTF-16 length is the same as the number of characters.
2172
21
    *result = val.As<v8::String>()->Length();
2173
13
  } else if (bufsize != 0) {
2174
52
    int copied = val.As<v8::String>()->Write(env->isolate,
2175
                                             reinterpret_cast<uint16_t*>(buf),
2176
                                             0,
2177
13
                                             bufsize - 1,
2178
13
                                             v8::String::NO_NULL_TERMINATION);
2179
2180
13
    buf[copied] = '\0';
2181
13
    if (result != nullptr) {
2182
13
      *result = copied;
2183
    }
2184
  } else if (result != nullptr) {
2185
    *result = 0;
2186
  }
2187
2188
20
  return napi_clear_last_error(env);
2189
}
2190
2191
18
napi_status napi_coerce_to_bool(napi_env env,
2192
                                napi_value value,
2193
                                napi_value* result) {
2194


52
  NAPI_PREAMBLE(env);
2195
17
  CHECK_ARG(env, value);
2196
16
  CHECK_ARG(env, result);
2197
2198
15
  v8::Isolate* isolate = env->isolate;
2199
  v8::Local<v8::Boolean> b =
2200
30
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2201
30
  *result = v8impl::JsValueFromV8LocalValue(b);
2202
15
  return GET_RETURN_STATUS(env);
2203
}
2204
2205
#define GEN_COERCE_FUNCTION(UpperCaseName, MixedCaseName, LowerCaseName)      \
2206
  napi_status napi_coerce_to_##LowerCaseName(napi_env env,                    \
2207
                                             napi_value value,                \
2208
                                             napi_value* result) {            \
2209
    NAPI_PREAMBLE(env);                                                       \
2210
    CHECK_ARG(env, value);                                                    \
2211
    CHECK_ARG(env, result);                                                   \
2212
                                                                              \
2213
    v8::Local<v8::Context> context = env->context();                          \
2214
    v8::Local<v8::MixedCaseName> str;                                         \
2215
                                                                              \
2216
    CHECK_TO_##UpperCaseName(env, context, str, value);                       \
2217
                                                                              \
2218
    *result = v8impl::JsValueFromV8LocalValue(str);                           \
2219
    return GET_RETURN_STATUS(env);                                            \
2220
  }
2221
2222
15
GEN_COERCE_FUNCTION(NUMBER, Number, number)
2223


49
GEN_COERCE_FUNCTION(OBJECT, Object, object)
2224


69
GEN_COERCE_FUNCTION(STRING, String, string)
2225


67
2226

35
#undef GEN_COERCE_FUNCTION
2227

48
2228

1089
napi_status napi_wrap(napi_env env,
2229

63
                      napi_value js_object,
2230

59
                      void* native_object,
2231
47
                      napi_finalize finalize_cb,
2232
44
                      void* finalize_hint,
2233
14
                      napi_ref* result) {
2234
  return v8impl::Wrap<v8impl::retrievable>(env,
2235
                                           js_object,
2236
                                           native_object,
2237
                                           finalize_cb,
2238
                                           finalize_hint,
2239
1025
                                           result);
2240
}
2241
2242
27
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2243
27
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2244
}
2245
2246
8
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2247
8
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2248
}
2249
2250
7
napi_status napi_create_external(napi_env env,
2251
                                 void* data,
2252
                                 napi_finalize finalize_cb,
2253
                                 void* finalize_hint,
2254
                                 napi_value* result) {
2255


21
  NAPI_PREAMBLE(env);
2256
7
  CHECK_ARG(env, result);
2257
2258
7
  v8::Isolate* isolate = env->isolate;
2259
2260
7
  v8::Local<v8::Value> external_value = v8::External::New(isolate, data);
2261
2262
  // The Reference object will delete itself after invoking the finalizer
2263
  // callback.
2264
  v8impl::Reference::New(env,
2265
      external_value,
2266
      0,
2267
      true,
2268
      finalize_cb,
2269
      data,
2270
7
      finalize_hint);
2271
2272
7
  *result = v8impl::JsValueFromV8LocalValue(external_value);
2273
2274
7
  return napi_clear_last_error(env);
2275
}
2276
2277
2
NAPI_EXTERN napi_status napi_type_tag_object(napi_env env,
2278
                                             napi_value object,
2279
                                             const napi_type_tag* type_tag) {
2280


6
  NAPI_PREAMBLE(env);
2281
2
  v8::Local<v8::Context> context = env->context();
2282
  v8::Local<v8::Object> obj;
2283


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

2
  CHECK_ARG_WITH_PREAMBLE(env, type_tag);
2285
2286
2
  auto key = NAPI_PRIVATE_KEY(context, type_tag);
2287
2
  auto maybe_has = obj->HasPrivate(context, key);
2288

2
  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_has, napi_generic_failure);
2289

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
2290
                                       !maybe_has.FromJust(),
2291
                                       napi_invalid_arg);
2292
2293
  auto tag = v8::BigInt::NewFromWords(context,
2294
                                   0,
2295
                                   2,
2296
2
                                   reinterpret_cast<const uint64_t*>(type_tag));
2297

2
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, tag, napi_generic_failure);
2298
2299
2
  auto maybe_set = obj->SetPrivate(context, key, tag.ToLocalChecked());
2300

2
  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_set, napi_generic_failure);
2301

2
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
2302
                                       maybe_set.FromJust(),
2303
                                       napi_generic_failure);
2304
2305
2
  return GET_RETURN_STATUS(env);
2306
}
2307
2308
NAPI_EXTERN napi_status
2309
6
napi_check_object_type_tag(napi_env env,
2310
                           napi_value object,
2311
                           const napi_type_tag* type_tag,
2312
                           bool* result) {
2313


18
  NAPI_PREAMBLE(env);
2314
6
  v8::Local<v8::Context> context = env->context();
2315
  v8::Local<v8::Object> obj;
2316


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

6
  CHECK_ARG_WITH_PREAMBLE(env, type_tag);
2318

6
  CHECK_ARG_WITH_PREAMBLE(env, result);
2319
2320
  auto maybe_value = obj->GetPrivate(context,
2321
12
                                     NAPI_PRIVATE_KEY(context, type_tag));
2322

6
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe_value, napi_generic_failure);
2323
6
  v8::Local<v8::Value> val = maybe_value.ToLocalChecked();
2324
2325
  // We consider the type check to have failed unless we reach the line below
2326
  // where we set whether the type check succeeded or not based on the
2327
  // comparison of the two type tags.
2328
6
  *result = false;
2329
6
  if (val->IsBigInt()) {
2330
    int sign;
2331
4
    int size = 2;
2332
    napi_type_tag tag;
2333
12
    val.As<v8::BigInt>()->ToWordsArray(&sign,
2334
                                       &size,
2335
4
                                       reinterpret_cast<uint64_t*>(&tag));
2336

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

4
      *result = (tag.lower == type_tag->lower && tag.upper == type_tag->upper);
2338
  }
2339
2340
6
  return GET_RETURN_STATUS(env);
2341
}
2342
2343
2
napi_status napi_get_value_external(napi_env env,
2344
                                    napi_value value,
2345
                                    void** result) {
2346
2
  CHECK_ENV(env);
2347
2
  CHECK_ARG(env, value);
2348
2
  CHECK_ARG(env, result);
2349
2350
2
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2351
2
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
2352
2353
2
  v8::Local<v8::External> external_value = val.As<v8::External>();
2354
4
  *result = external_value->Value();
2355
2356
2
  return napi_clear_last_error(env);
2357
}
2358
2359
// Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
2360
1539
napi_status napi_create_reference(napi_env env,
2361
                                  napi_value value,
2362
                                  uint32_t initial_refcount,
2363
                                  napi_ref* result) {
2364
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2365
  // JS exceptions.
2366
1539
  CHECK_ENV(env);
2367
1539
  CHECK_ARG(env, value);
2368
1539
  CHECK_ARG(env, result);
2369
2370
1539
  v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(value);
2371
2372

1539
  if (!(v8_value->IsObject() || v8_value->IsFunction())) {
2373
    return napi_set_last_error(env, napi_object_expected);
2374
  }
2375
2376
  v8impl::Reference* reference =
2377
1539
      v8impl::Reference::New(env, v8_value, initial_refcount, false);
2378
2379
1539
  *result = reinterpret_cast<napi_ref>(reference);
2380
1539
  return napi_clear_last_error(env);
2381
}
2382
2383
// Deletes a reference. The referenced value is released, and may be GC'd unless
2384
// there are other references to it.
2385
1542
napi_status napi_delete_reference(napi_env env, napi_ref ref) {
2386
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2387
  // JS exceptions.
2388
1542
  CHECK_ENV(env);
2389
1542
  CHECK_ARG(env, ref);
2390
2391
1542
  v8impl::Reference::Delete(reinterpret_cast<v8impl::Reference*>(ref));
2392
2393
1542
  return napi_clear_last_error(env);
2394
}
2395
2396
// Increments the reference count, optionally returning the resulting count.
2397
// After this call the reference will be a strong reference because its
2398
// refcount is >0, and the referenced object is effectively "pinned".
2399
// Calling this when the refcount is 0 and the object is unavailable
2400
// results in an error.
2401
1
napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) {
2402
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2403
  // JS exceptions.
2404
1
  CHECK_ENV(env);
2405
1
  CHECK_ARG(env, ref);
2406
2407
1
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2408
1
  uint32_t count = reference->Ref();
2409
2410
1
  if (result != nullptr) {
2411
1
    *result = count;
2412
  }
2413
2414
1
  return napi_clear_last_error(env);
2415
}
2416
2417
// Decrements the reference count, optionally returning the resulting count. If
2418
// the result is 0 the reference is now weak and the object may be GC'd at any
2419
// time if there are no other references. Calling this when the refcount is
2420
// already 0 results in an error.
2421
3
napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) {
2422
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2423
  // JS exceptions.
2424
3
  CHECK_ENV(env);
2425
3
  CHECK_ARG(env, ref);
2426
2427
3
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2428
2429
3
  if (reference->RefCount() == 0) {
2430
    return napi_set_last_error(env, napi_generic_failure);
2431
  }
2432
2433
3
  uint32_t count = reference->Unref();
2434
2435
3
  if (result != nullptr) {
2436
3
    *result = count;
2437
  }
2438
2439
3
  return napi_clear_last_error(env);
2440
}
2441
2442
// Attempts to get a referenced value. If the reference is weak, the value might
2443
// no longer be available, in that case the call is still successful but the
2444
// result is NULL.
2445
1552
napi_status napi_get_reference_value(napi_env env,
2446
                                     napi_ref ref,
2447
                                     napi_value* result) {
2448
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2449
  // JS exceptions.
2450
1552
  CHECK_ENV(env);
2451
1552
  CHECK_ARG(env, ref);
2452
1550
  CHECK_ARG(env, result);
2453
2454
1550
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2455
1550
  *result = v8impl::JsValueFromV8LocalValue(reference->Get());
2456
2457
1550
  return napi_clear_last_error(env);
2458
}
2459
2460
4
napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result) {
2461
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2462
  // JS exceptions.
2463
4
  CHECK_ENV(env);
2464
4
  CHECK_ARG(env, result);
2465
2466
8
  *result = v8impl::JsHandleScopeFromV8HandleScope(
2467
4
      new v8impl::HandleScopeWrapper(env->isolate));
2468
4
  env->open_handle_scopes++;
2469
4
  return napi_clear_last_error(env);
2470
}
2471
2472
4
napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) {
2473
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2474
  // JS exceptions.
2475
4
  CHECK_ENV(env);
2476
4
  CHECK_ARG(env, scope);
2477
4
  if (env->open_handle_scopes == 0) {
2478
    return napi_handle_scope_mismatch;
2479
  }
2480
2481
4
  env->open_handle_scopes--;
2482
4
  delete v8impl::V8HandleScopeFromJsHandleScope(scope);
2483
4
  return napi_clear_last_error(env);
2484
}
2485
2486
2
napi_status napi_open_escapable_handle_scope(
2487
    napi_env env,
2488
    napi_escapable_handle_scope* result) {
2489
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2490
  // JS exceptions.
2491
2
  CHECK_ENV(env);
2492
2
  CHECK_ARG(env, result);
2493
2494
4
  *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope(
2495
2
      new v8impl::EscapableHandleScopeWrapper(env->isolate));
2496
2
  env->open_handle_scopes++;
2497
2
  return napi_clear_last_error(env);
2498
}
2499
2500
2
napi_status napi_close_escapable_handle_scope(
2501
    napi_env env,
2502
    napi_escapable_handle_scope scope) {
2503
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2504
  // JS exceptions.
2505
2
  CHECK_ENV(env);
2506
2
  CHECK_ARG(env, scope);
2507
2
  if (env->open_handle_scopes == 0) {
2508
    return napi_handle_scope_mismatch;
2509
  }
2510
2511
2
  delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2512
2
  env->open_handle_scopes--;
2513
2
  return napi_clear_last_error(env);
2514
}
2515
2516
3
napi_status napi_escape_handle(napi_env env,
2517
                               napi_escapable_handle_scope scope,
2518
                               napi_value escapee,
2519
                               napi_value* result) {
2520
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2521
  // JS exceptions.
2522
3
  CHECK_ENV(env);
2523
3
  CHECK_ARG(env, scope);
2524
3
  CHECK_ARG(env, escapee);
2525
3
  CHECK_ARG(env, result);
2526
2527
  v8impl::EscapableHandleScopeWrapper* s =
2528
3
      v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2529
3
  if (!s->escape_called()) {
2530
2
    *result = v8impl::JsValueFromV8LocalValue(
2531
        s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
2532
2
    return napi_clear_last_error(env);
2533
  }
2534
1
  return napi_set_last_error(env, napi_escape_called_twice);
2535
}
2536
2537
7
napi_status napi_new_instance(napi_env env,
2538
                              napi_value constructor,
2539
                              size_t argc,
2540
                              const napi_value* argv,
2541
                              napi_value* result) {
2542


21
  NAPI_PREAMBLE(env);
2543
7
  CHECK_ARG(env, constructor);
2544
7
  if (argc > 0) {
2545
7
    CHECK_ARG(env, argv);
2546
  }
2547
7
  CHECK_ARG(env, result);
2548
2549
7
  v8::Local<v8::Context> context = env->context();
2550
2551
  v8::Local<v8::Function> ctor;
2552

21
  CHECK_TO_FUNCTION(env, ctor, constructor);
2553
2554
  auto maybe = ctor->NewInstance(context, argc,
2555
14
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2556
2557
7
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2558
2559
14
  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2560
7
  return GET_RETURN_STATUS(env);
2561
}
2562
2563
2278
napi_status napi_instanceof(napi_env env,
2564
                            napi_value object,
2565
                            napi_value constructor,
2566
                            bool* result) {
2567


6834
  NAPI_PREAMBLE(env);
2568
2278
  CHECK_ARG(env, object);
2569
2278
  CHECK_ARG(env, result);
2570
2571
2278
  *result = false;
2572
2573
  v8::Local<v8::Object> ctor;
2574
2278
  v8::Local<v8::Context> context = env->context();
2575
2576

9112
  CHECK_TO_OBJECT(env, context, ctor, constructor);
2577
2578
2278
  if (!ctor->IsFunction()) {
2579
    napi_throw_type_error(env,
2580
                          "ERR_NAPI_CONS_FUNCTION",
2581
88
                          "Constructor must be a function");
2582
2583
88
    return napi_set_last_error(env, napi_function_expected);
2584
  }
2585
2586
2190
  napi_status status = napi_generic_failure;
2587
2588
2190
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(object);
2589
2190
  auto maybe_result = val->InstanceOf(context, ctor);
2590
2190
  CHECK_MAYBE_NOTHING(env, maybe_result, status);
2591
2332
  *result = maybe_result.FromJust();
2592
1166
  return GET_RETURN_STATUS(env);
2593
}
2594
2595
// Methods to support catching exceptions
2596
1228
napi_status napi_is_exception_pending(napi_env env, bool* result) {
2597
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2598
  // pending exception.
2599
1228
  CHECK_ENV(env);
2600
1228
  CHECK_ARG(env, result);
2601
2602
2456
  *result = !env->last_exception.IsEmpty();
2603
1228
  return napi_clear_last_error(env);
2604
}
2605
2606
1
napi_status napi_get_and_clear_last_exception(napi_env env,
2607
                                              napi_value* result) {
2608
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2609
  // pending exception.
2610
1
  CHECK_ENV(env);
2611
1
  CHECK_ARG(env, result);
2612
2613
2
  if (env->last_exception.IsEmpty()) {
2614
    return napi_get_undefined(env, result);
2615
  } else {
2616
2
    *result = v8impl::JsValueFromV8LocalValue(
2617
1
      v8::Local<v8::Value>::New(env->isolate, env->last_exception));
2618
1
    env->last_exception.Reset();
2619
  }
2620
2621
1
  return napi_clear_last_error(env);
2622
}
2623
2624
57
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) {
2625
57
  CHECK_ENV(env);
2626
57
  CHECK_ARG(env, value);
2627
57
  CHECK_ARG(env, result);
2628
2629
57
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2630
114
  *result = val->IsArrayBuffer();
2631
2632
57
  return napi_clear_last_error(env);
2633
}
2634
2635
2
napi_status napi_create_arraybuffer(napi_env env,
2636
                                    size_t byte_length,
2637
                                    void** data,
2638
                                    napi_value* result) {
2639


6
  NAPI_PREAMBLE(env);
2640
2
  CHECK_ARG(env, result);
2641
2642
2
  v8::Isolate* isolate = env->isolate;
2643
  v8::Local<v8::ArrayBuffer> buffer =
2644
2
      v8::ArrayBuffer::New(isolate, byte_length);
2645
2646
  // Optionally return a pointer to the buffer's data, to avoid another call to
2647
  // retrieve it.
2648
2
  if (data != nullptr) {
2649
2
    *data = buffer->GetBackingStore()->Data();
2650
  }
2651
2652
4
  *result = v8impl::JsValueFromV8LocalValue(buffer);
2653
2
  return GET_RETURN_STATUS(env);
2654
}
2655
2656
6
napi_status napi_create_external_arraybuffer(napi_env env,
2657
                                             void* external_data,
2658
                                             size_t byte_length,
2659
                                             napi_finalize finalize_cb,
2660
                                             void* finalize_hint,
2661
                                             napi_value* result) {
2662
  // The API contract here is that the cleanup function runs on the JS thread,
2663
  // and is able to use napi_env. Implementing that properly is hard, so use the
2664
  // `Buffer` variant for easier implementation.
2665
  napi_value buffer;
2666
6
  STATUS_CALL(napi_create_external_buffer(
2667
      env,
2668
      byte_length,
2669
      external_data,
2670
      finalize_cb,
2671
      finalize_hint,
2672
      &buffer));
2673
6
  return napi_get_typedarray_info(
2674
      env,
2675
      buffer,
2676
      nullptr,
2677
      nullptr,
2678
      nullptr,
2679
      result,
2680
6
      nullptr);
2681
}
2682
2683
2
napi_status napi_get_arraybuffer_info(napi_env env,
2684
                                      napi_value arraybuffer,
2685
                                      void** data,
2686
                                      size_t* byte_length) {
2687
2
  CHECK_ENV(env);
2688
2
  CHECK_ARG(env, arraybuffer);
2689
2690
2
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2691
2
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2692
2693
  std::shared_ptr<v8::BackingStore> backing_store =
2694
6
      value.As<v8::ArrayBuffer>()->GetBackingStore();
2695
2696
2
  if (data != nullptr) {
2697
2
    *data = backing_store->Data();
2698
  }
2699
2700
2
  if (byte_length != nullptr) {
2701
2
    *byte_length = backing_store->ByteLength();
2702
  }
2703
2704
2
  return napi_clear_last_error(env);
2705
}
2706
2707
44
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) {
2708
44
  CHECK_ENV(env);
2709
44
  CHECK_ARG(env, value);
2710
44
  CHECK_ARG(env, result);
2711
2712
44
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2713
88
  *result = val->IsTypedArray();
2714
2715
44
  return napi_clear_last_error(env);
2716
}
2717
2718
34
napi_status napi_create_typedarray(napi_env env,
2719
                                   napi_typedarray_type type,
2720
                                   size_t length,
2721
                                   napi_value arraybuffer,
2722
                                   size_t byte_offset,
2723
                                   napi_value* result) {
2724


102
  NAPI_PREAMBLE(env);
2725
34
  CHECK_ARG(env, arraybuffer);
2726
34
  CHECK_ARG(env, result);
2727
2728
34
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2729
34
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2730
2731
34
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2732
  v8::Local<v8::TypedArray> typedArray;
2733
2734



34
  switch (type) {
2735
    case napi_int8_array:
2736
8
      CREATE_TYPED_ARRAY(
2737
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2738
3
      break;
2739
    case napi_uint8_array:
2740
4
      CREATE_TYPED_ARRAY(
2741
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2742
8
      break;
2743
1
    case napi_uint8_clamped_array:
2744
3
      CREATE_TYPED_ARRAY(
2745
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2746
5
      break;
2747
1
    case napi_int16_array:
2748
5
      CREATE_TYPED_ARRAY(
2749
1
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2750
4
      break;
2751
1
    case napi_uint16_array:
2752
5
      CREATE_TYPED_ARRAY(
2753
1
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2754
4
      break;
2755
1
    case napi_int32_array:
2756
5
      CREATE_TYPED_ARRAY(
2757
1
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2758
4
      break;
2759
1
    case napi_uint32_array:
2760
5
      CREATE_TYPED_ARRAY(
2761
1
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2762
4
      break;
2763
1
    case napi_float32_array:
2764
5
      CREATE_TYPED_ARRAY(
2765
1
          env, Float32Array, 4, buffer, byte_offset, length, typedArray);
2766
4
      break;
2767
1
    case napi_float64_array:
2768
6
      CREATE_TYPED_ARRAY(
2769
1
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2770
6
      break;
2771
1
    case napi_bigint64_array:
2772
6
      CREATE_TYPED_ARRAY(
2773
1
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2774
4
      break;
2775
1
    case napi_biguint64_array:
2776
5
      CREATE_TYPED_ARRAY(
2777
1
          env, BigUint64Array, 8, buffer, byte_offset, length, typedArray);
2778
4
      break;
2779
1
    default:
2780
2
      return napi_set_last_error(env, napi_invalid_arg);
2781
  }
2782
2783
30
  *result = v8impl::JsValueFromV8LocalValue(typedArray);
2784
15
  return GET_RETURN_STATUS(env);
2785
}
2786
2787
50
napi_status napi_get_typedarray_info(napi_env env,
2788
                                     napi_value typedarray,
2789
                                     napi_typedarray_type* type,
2790
                                     size_t* length,
2791
                                     void** data,
2792
                                     napi_value* arraybuffer,
2793
                                     size_t* byte_offset) {
2794
50
  CHECK_ENV(env);
2795
50
  CHECK_ARG(env, typedarray);
2796
2797
50
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(typedarray);
2798
50
  RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), napi_invalid_arg);
2799
2800
50
  v8::Local<v8::TypedArray> array = value.As<v8::TypedArray>();
2801
2802
50
  if (type != nullptr) {
2803
32
    if (value->IsInt8Array()) {
2804
2
      *type = napi_int8_array;
2805
30
    } else if (value->IsUint8Array()) {
2806
3
      *type = napi_uint8_array;
2807
27
    } else if (value->IsUint8ClampedArray()) {
2808
2
      *type = napi_uint8_clamped_array;
2809
25
    } else if (value->IsInt16Array()) {
2810
3
      *type = napi_int16_array;
2811
22
    } else if (value->IsUint16Array()) {
2812
3
      *type = napi_uint16_array;
2813
19
    } else if (value->IsInt32Array()) {
2814
3
      *type = napi_int32_array;
2815
16
    } else if (value->IsUint32Array()) {
2816
3
      *type = napi_uint32_array;
2817
13
    } else if (value->IsFloat32Array()) {
2818
3
      *type = napi_float32_array;
2819
10
    } else if (value->IsFloat64Array()) {
2820
4
      *type = napi_float64_array;
2821
6
    } else if (value->IsBigInt64Array()) {
2822
3
      *type = napi_bigint64_array;
2823
3
    } else if (value->IsBigUint64Array()) {
2824
3
      *type = napi_biguint64_array;
2825
    }
2826
  }
2827
2828
50
  if (length != nullptr) {
2829
32
    *length = array->Length();
2830
  }
2831
2832
  v8::Local<v8::ArrayBuffer> buffer;
2833

50
  if (data != nullptr || arraybuffer != nullptr) {
2834
    // Calling Buffer() may have the side effect of allocating the buffer,
2835
    // so only do this when it’s needed.
2836
50
    buffer = array->Buffer();
2837
  }
2838
2839
50
  if (data != nullptr) {
2840
    *data = static_cast<uint8_t*>(buffer->GetBackingStore()->Data()) +
2841
            array->ByteOffset();
2842
  }
2843
2844
50
  if (arraybuffer != nullptr) {
2845
50
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2846
  }
2847
2848
50
  if (byte_offset != nullptr) {
2849
32
    *byte_offset = array->ByteOffset();
2850
  }
2851
2852
50
  return napi_clear_last_error(env);
2853
}
2854
2855
2
napi_status napi_create_dataview(napi_env env,
2856
                                 size_t byte_length,
2857
                                 napi_value arraybuffer,
2858
                                 size_t byte_offset,
2859
                                 napi_value* result) {
2860


6
  NAPI_PREAMBLE(env);
2861
2
  CHECK_ARG(env, arraybuffer);
2862
2
  CHECK_ARG(env, result);
2863
2864
2
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2865
2
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2866
2867
2
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2868
4
  if (byte_length + byte_offset > buffer->ByteLength()) {
2869
    napi_throw_range_error(
2870
        env,
2871
        "ERR_NAPI_INVALID_DATAVIEW_ARGS",
2872
        "byte_offset + byte_length should be less than or "
2873
1
        "equal to the size in bytes of the array passed in");
2874
1
    return napi_set_last_error(env, napi_pending_exception);
2875
  }
2876
  v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset,
2877
1
                                                       byte_length);
2878
2879
2
  *result = v8impl::JsValueFromV8LocalValue(DataView);
2880
1
  return GET_RETURN_STATUS(env);
2881
}
2882
2883
1
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) {
2884
1
  CHECK_ENV(env);
2885
1
  CHECK_ARG(env, value);
2886
1
  CHECK_ARG(env, result);
2887
2888
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2889
2
  *result = val->IsDataView();
2890
2891
1
  return napi_clear_last_error(env);
2892
}
2893
2894
1
napi_status napi_get_dataview_info(napi_env env,
2895
                                   napi_value dataview,
2896
                                   size_t* byte_length,
2897
                                   void** data,
2898
                                   napi_value* arraybuffer,
2899
                                   size_t* byte_offset) {
2900
1
  CHECK_ENV(env);
2901
1
  CHECK_ARG(env, dataview);
2902
2903
1
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(dataview);
2904
1
  RETURN_STATUS_IF_FALSE(env, value->IsDataView(), napi_invalid_arg);
2905
2906
1
  v8::Local<v8::DataView> array = value.As<v8::DataView>();
2907
2908
1
  if (byte_length != nullptr) {
2909
1
    *byte_length = array->ByteLength();
2910
  }
2911
2912
  v8::Local<v8::ArrayBuffer> buffer;
2913

1
  if (data != nullptr || arraybuffer != nullptr) {
2914
    // Calling Buffer() may have the side effect of allocating the buffer,
2915
    // so only do this when it’s needed.
2916
1
    buffer = array->Buffer();
2917
  }
2918
2919
1
  if (data != nullptr) {
2920
    *data = static_cast<uint8_t*>(buffer->GetBackingStore()->Data()) +
2921
            array->ByteOffset();
2922
  }
2923
2924
1
  if (arraybuffer != nullptr) {
2925
1
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2926
  }
2927
2928
1
  if (byte_offset != nullptr) {
2929
1
    *byte_offset = array->ByteOffset();
2930
  }
2931
2932
1
  return napi_clear_last_error(env);
2933
}
2934
2935
1
napi_status napi_get_version(napi_env env, uint32_t* result) {
2936
1
  CHECK_ENV(env);
2937
1
  CHECK_ARG(env, result);
2938
1
  *result = NAPI_VERSION;
2939
1
  return napi_clear_last_error(env);
2940
}
2941
2942
5
napi_status napi_create_promise(napi_env env,
2943
                                napi_deferred* deferred,
2944
                                napi_value* promise) {
2945


15
  NAPI_PREAMBLE(env);
2946
5
  CHECK_ARG(env, deferred);
2947
5
  CHECK_ARG(env, promise);
2948
2949
5
  auto maybe = v8::Promise::Resolver::New(env->context());
2950
5
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2951
2952
5
  auto v8_resolver = maybe.ToLocalChecked();
2953
10
  auto v8_deferred = new v8impl::Persistent<v8::Value>();
2954
5
  v8_deferred->Reset(env->isolate, v8_resolver);
2955
2956
5
  *deferred = v8impl::JsDeferredFromNodePersistent(v8_deferred);
2957
15
  *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise());
2958
5
  return GET_RETURN_STATUS(env);
2959
}
2960
2961
4
napi_status napi_resolve_deferred(napi_env env,
2962
                                  napi_deferred deferred,
2963
                                  napi_value resolution) {
2964
4
  return v8impl::ConcludeDeferred(env, deferred, resolution, true);
2965
}
2966
2967
1
napi_status napi_reject_deferred(napi_env env,
2968
                                 napi_deferred deferred,
2969
                                 napi_value resolution) {
2970
1
  return v8impl::ConcludeDeferred(env, deferred, resolution, false);
2971
}
2972
2973
7
napi_status napi_is_promise(napi_env env,
2974
                            napi_value value,
2975
                            bool* is_promise) {
2976
7
  CHECK_ENV(env);
2977
7
  CHECK_ARG(env, value);
2978
7
  CHECK_ARG(env, is_promise);
2979
2980
14
  *is_promise = v8impl::V8LocalValueFromJsValue(value)->IsPromise();
2981
2982
7
  return napi_clear_last_error(env);
2983
}
2984
2985
1
napi_status napi_create_date(napi_env env,
2986
                             double time,
2987
                             napi_value* result) {
2988


3
  NAPI_PREAMBLE(env);
2989
1
  CHECK_ARG(env, result);
2990
2991
1
  v8::MaybeLocal<v8::Value> maybe_date = v8::Date::New(env->context(), time);
2992
1
  CHECK_MAYBE_EMPTY(env, maybe_date, napi_generic_failure);
2993
2994
2
  *result = v8impl::JsValueFromV8LocalValue(maybe_date.ToLocalChecked());
2995
2996
1
  return GET_RETURN_STATUS(env);
2997
}
2998
2999
7
napi_status napi_is_date(napi_env env,
3000
                         napi_value value,
3001
                         bool* is_date) {
3002
7
  CHECK_ENV(env);
3003
7
  CHECK_ARG(env, value);
3004
7
  CHECK_ARG(env, is_date);
3005
3006
14
  *is_date = v8impl::V8LocalValueFromJsValue(value)->IsDate();
3007
3008
7
  return napi_clear_last_error(env);
3009
}
3010
3011
1
napi_status napi_get_date_value(napi_env env,
3012
                                napi_value value,
3013
                                double* result) {
3014


3
  NAPI_PREAMBLE(env);
3015
1
  CHECK_ARG(env, value);
3016
1
  CHECK_ARG(env, result);
3017
3018
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
3019
1
  RETURN_STATUS_IF_FALSE(env, val->IsDate(), napi_date_expected);
3020
3021
1
  v8::Local<v8::Date> date = val.As<v8::Date>();
3022
2
  *result = date->ValueOf();
3023
3024
1
  return GET_RETURN_STATUS(env);
3025
}
3026
3027
2
napi_status napi_run_script(napi_env env,
3028
                            napi_value script,
3029
                            napi_value* result) {
3030


6
  NAPI_PREAMBLE(env);
3031
2
  CHECK_ARG(env, script);
3032
2
  CHECK_ARG(env, result);
3033
3034
2
  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
3035
3036
4
  if (!v8_script->IsString()) {
3037
1
    return napi_set_last_error(env, napi_string_expected);
3038
  }
3039
3040
1
  v8::Local<v8::Context> context = env->context();
3041
3042
  auto maybe_script = v8::Script::Compile(context,
3043
1
      v8::Local<v8::String>::Cast(v8_script));
3044
1
  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
3045
3046
  auto script_result =
3047
2
      maybe_script.ToLocalChecked()->Run(context);
3048
1
  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
3049
3050
2
  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
3051
1
  return GET_RETURN_STATUS(env);
3052
}
3053
3054
3
napi_status napi_add_finalizer(napi_env env,
3055
                               napi_value js_object,
3056
                               void* native_object,
3057
                               napi_finalize finalize_cb,
3058
                               void* finalize_hint,
3059
                               napi_ref* result) {
3060
  return v8impl::Wrap<v8impl::anonymous>(env,
3061
                                         js_object,
3062
                                         native_object,
3063
                                         finalize_cb,
3064
                                         finalize_hint,
3065
3
                                         result);
3066
}
3067
3068
1
napi_status napi_adjust_external_memory(napi_env env,
3069
                                        int64_t change_in_bytes,
3070
                                        int64_t* adjusted_value) {
3071
1
  CHECK_ENV(env);
3072
1
  CHECK_ARG(env, adjusted_value);
3073
3074
1
  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
3075
      change_in_bytes);
3076
3077
1
  return napi_clear_last_error(env);
3078
}
3079
3080
7
napi_status napi_set_instance_data(napi_env env,
3081
                                   void* data,
3082
                                   napi_finalize finalize_cb,
3083
                                   void* finalize_hint) {
3084
7
  CHECK_ENV(env);
3085
3086
7
  v8impl::RefBase* old_data = static_cast<v8impl::RefBase*>(env->instance_data);
3087
7
  if (old_data != nullptr) {
3088
    // Our contract so far has been to not finalize any old data there may be.
3089
    // So we simply delete it.
3090
    v8impl::RefBase::Delete(old_data);
3091
  }
3092
3093
7
  env->instance_data = v8impl::RefBase::New(env,
3094
                                            0,
3095
                                            true,
3096
                                            finalize_cb,
3097
                                            data,
3098
                                            finalize_hint);
3099
3100
7
  return napi_clear_last_error(env);
3101
}
3102
3103
22
napi_status napi_get_instance_data(napi_env env,
3104
                                   void** data) {
3105
22
  CHECK_ENV(env);
3106
22
  CHECK_ARG(env, data);
3107
3108
22
  v8impl::RefBase* idata = static_cast<v8impl::RefBase*>(env->instance_data);
3109
3110
22
  *data = (idata == nullptr ? nullptr : idata->Data());
3111
3112
22
  return napi_clear_last_error(env);
3113
}
3114
3115
12
napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) {
3116
12
  CHECK_ENV(env);
3117
12
  CHECK_ARG(env, arraybuffer);
3118
3119
12
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3120
12
  RETURN_STATUS_IF_FALSE(
3121
      env, value->IsArrayBuffer(), napi_arraybuffer_expected);
3122
3123
12
  v8::Local<v8::ArrayBuffer> it = value.As<v8::ArrayBuffer>();
3124
12
  RETURN_STATUS_IF_FALSE(
3125
      env, it->IsDetachable(), napi_detachable_arraybuffer_expected);
3126
3127
12
  it->Detach();
3128
3129
12
  return napi_clear_last_error(env);
3130
}
3131
3132
26
napi_status napi_is_detached_arraybuffer(napi_env env,
3133
                                         napi_value arraybuffer,
3134
                                         bool* result) {
3135
26
  CHECK_ENV(env);
3136
26
  CHECK_ARG(env, arraybuffer);
3137
26
  CHECK_ARG(env, result);
3138
3139
26
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3140
3141

104
  *result = value->IsArrayBuffer() &&
3142
104
            value.As<v8::ArrayBuffer>()->GetBackingStore()->Data() == nullptr;
3143
3144
26
  return napi_clear_last_error(env);
3145

14097
}