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: 1243 1266 98.2 %
Date: 2019-09-23 22:30:09 Branches: 894 1498 59.7 %

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

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

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


10
  NAPI_PREAMBLE(env);
167
5
  CHECK_ARG(env, result);
168
169
5
  v8::Local<v8::Context> context = env->isolate->GetCurrentContext();
170
  v8impl::Persistent<v8::Value>* deferred_ref =
171
5
      NodePersistentFromJsDeferred(deferred);
172
  v8::Local<v8::Value> v8_deferred =
173
10
      v8::Local<v8::Value>::New(env->isolate, *deferred_ref);
174
175
5
  auto v8_resolver = v8::Local<v8::Promise::Resolver>::Cast(v8_deferred);
176
177
  v8::Maybe<bool> success = is_resolved ?
178
8
      v8_resolver->Resolve(context, v8impl::V8LocalValueFromJsValue(result)) :
179
10
      v8_resolver->Reject(context, v8impl::V8LocalValueFromJsValue(result));
180
181
10
  delete deferred_ref;
182
183
10
  RETURN_STATUS_IF_FALSE(env, success.FromMaybe(false), napi_generic_failure);
184
185
5
  return GET_RETURN_STATUS(env);
186
}
187
188
// Wrapper around v8impl::Persistent that implements reference counting.
189
5114
class Reference : private Finalizer {
190
 private:
191
2945
  Reference(napi_env env,
192
            v8::Local<v8::Value> value,
193
            uint32_t initial_refcount,
194
            bool delete_self,
195
            napi_finalize finalize_callback,
196
            void* finalize_data,
197
            void* finalize_hint)
198
       : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
199
        _persistent(env->isolate, value),
200
        _refcount(initial_refcount),
201
5890
        _delete_self(delete_self) {
202
2945
    if (initial_refcount == 0) {
203
      _persistent.SetWeak(
204
2406
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
205
    }
206
2945
  }
207
208
 public:
209
27
  void* Data() {
210
27
    return _finalize_data;
211
  }
212
213
2945
  static Reference* New(napi_env env,
214
                        v8::Local<v8::Value> value,
215
                        uint32_t initial_refcount,
216
                        bool delete_self,
217
                        napi_finalize finalize_callback = nullptr,
218
                        void* finalize_data = nullptr,
219
                        void* finalize_hint = nullptr) {
220
    return new Reference(env,
221
      value,
222
      initial_refcount,
223
      delete_self,
224
      finalize_callback,
225
      finalize_data,
226
2945
      finalize_hint);
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
3559
  static void Delete(Reference* reference) {
245

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

4565
        (reference->_delete_self) ||
247
        (reference->_finalize_ran)) {
248
2557
      delete reference;
249
    } else {
250
      // defer until finalizer runs as
251
      // it may alread be queued
252
1002
      reference->_delete_self = true;
253
    }
254
3559
  }
255
256
1
  uint32_t Ref() {
257
1
    if (++_refcount == 1) {
258
      _persistent.ClearWeak();
259
    }
260
261
1
    return _refcount;
262
  }
263
264
2
  uint32_t Unref() {
265
2
    if (_refcount == 0) {
266
        return 0;
267
    }
268
2
    if (--_refcount == 0) {
269
      _persistent.SetWeak(
270
1
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
271
    }
272
273
2
    return _refcount;
274
  }
275
276
3561
  uint32_t RefCount() {
277
3561
    return _refcount;
278
  }
279
280
1553
  v8::Local<v8::Value> Get() {
281
3106
    if (_persistent.IsEmpty()) {
282
1001
      return v8::Local<v8::Value>();
283
    } else {
284
1104
      return v8::Local<v8::Value>::New(_env->isolate, _persistent);
285
    }
286
  }
287
288
 private:
289
  // The N-API finalizer callback may make calls into the engine. V8's heap is
290
  // not in a consistent state during the weak callback, and therefore it does
291
  // not support calls back into it. However, it provides a mechanism for adding
292
  // a finalizer which may make calls back into the engine by allowing us to
293
  // attach such a second-pass finalizer from the first pass finalizer. Thus,
294
  // we do that here to ensure that the N-API finalizer callback is free to call
295
  // into the engine.
296
2022
  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
297
2022
    Reference* reference = data.GetParameter();
298
299
    // The reference must be reset during the first pass.
300
2022
    reference->_persistent.Reset();
301
302
2022
    data.SetSecondPassCallback(SecondPassCallback);
303
2022
  }
304
305
2022
  static void SecondPassCallback(const v8::WeakCallbackInfo<Reference>& data) {
306
2022
    Reference* reference = data.GetParameter();
307
308
2022
    if (reference->_finalize_callback != nullptr) {
309
1019
      reference->_env->CallIntoModuleThrow([&](napi_env env) {
310
        reference->_finalize_callback(
311
            env,
312
            reference->_finalize_data,
313
1019
            reference->_finalize_hint);
314
2038
      });
315
    }
316
317
    // this is safe because if a request to delete the reference
318
    // is made in the finalize_callback it will defer deletion
319
    // to this block and set _delete_self to true
320
2022
    if (reference->_delete_self) {
321
2018
      Delete(reference);
322
    } else {
323
4
      reference->_finalize_ran = true;
324
    }
325
2022
  }
326
327
  v8impl::Persistent<v8::Value> _persistent;
328
  uint32_t _refcount;
329
  bool _delete_self;
330
};
331
332
enum UnwrapAction {
333
  KeepWrap,
334
  RemoveWrap
335
};
336
337
29
inline static napi_status Unwrap(napi_env env,
338
                                 napi_value js_object,
339
                                 void** result,
340
                                 UnwrapAction action) {
341


58
  NAPI_PREAMBLE(env);
342
29
  CHECK_ARG(env, js_object);
343
29
  if (action == KeepWrap) {
344
26
    CHECK_ARG(env, result);
345
  }
346
347
29
  v8::Isolate* isolate = env->isolate;
348
29
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
349
350
29
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
351
29
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
352
29
  v8::Local<v8::Object> obj = value.As<v8::Object>();
353
354
58
  auto val = obj->GetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
355
58
      .ToLocalChecked();
356
29
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
357
  Reference* reference =
358
54
      static_cast<v8impl::Reference*>(val.As<v8::External>()->Value());
359
360
27
  if (result) {
361
27
    *result = reference->Data();
362
  }
363
364
27
  if (action == RemoveWrap) {
365
6
    CHECK(obj->DeletePrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
366
        .FromJust());
367
2
    Reference::Delete(reference);
368
  }
369
370
27
  return GET_RETURN_STATUS(env);
371
}
372
373
//=== Function napi_callback wrapper =================================
374
375
// Use this data structure to associate callback data with each N-API function
376
// exposed to JavaScript. The structure is stored in a v8::External which gets
377
// passed into our callback wrapper. This reduces the performance impact of
378
// calling through N-API.
379
// Ref: benchmark/misc/function_call
380
// Discussion (incl. perf. data): https://github.com/nodejs/node/pull/21072
381
struct CallbackBundle {
382
  napi_env       env;      // Necessary to invoke C++ NAPI callback
383
  void*          cb_data;  // The user provided callback data
384
  napi_callback  function_or_getter;
385
  napi_callback  setter;
386
};
387
388
// Base class extended by classes that wrap V8 function and property callback
389
// info.
390
class CallbackWrapper {
391
 public:
392
4535
  CallbackWrapper(napi_value this_arg, size_t args_length, void* data)
393
4535
      : _this(this_arg), _args_length(args_length), _data(data) {}
394
395
  virtual napi_value GetNewTarget() = 0;
396
  virtual void Args(napi_value* buffer, size_t bufferlength) = 0;
397
  virtual void SetReturnValue(napi_value value) = 0;
398
399
39
  napi_value This() { return _this; }
400
401
4415
  size_t ArgsLength() { return _args_length; }
402
403
6
  void* Data() { return _data; }
404
405
 protected:
406
  const napi_value _this;
407
  const size_t _args_length;
408
  void* _data;
409
};
410
411
template <typename Info, napi_callback CallbackBundle::*FunctionField>
412
class CallbackWrapperBase : public CallbackWrapper {
413
 public:
414
4535
  CallbackWrapperBase(const Info& cbinfo, const size_t args_length)
415
      : CallbackWrapper(JsValueFromV8LocalValue(cbinfo.This()),
416
                        args_length,
417
                        nullptr),
418
4535
        _cbinfo(cbinfo) {
419
9070
    _bundle = reinterpret_cast<CallbackBundle*>(
420
        v8::Local<v8::External>::Cast(cbinfo.Data())->Value());
421
4535
    _data = _bundle->cb_data;
422
4535
  }
423
424
  napi_value GetNewTarget() override { return nullptr; }
425
426
 protected:
427
4535
  void InvokeCallback() {
428
    napi_callback_info cbinfo_wrapper = reinterpret_cast<napi_callback_info>(
429
4535
        static_cast<CallbackWrapper*>(this));
430
431
    // All other pointers we need are stored in `_bundle`
432
4535
    napi_env env = _bundle->env;
433
4535
    napi_callback cb = _bundle->*FunctionField;
434
435
    napi_value result;
436
9070
    env->CallIntoModuleThrow([&](napi_env env) {
437
4535
      result = cb(env, cbinfo_wrapper);
438
4535
    });
439
440
4535
    if (result != nullptr) {
441
2719
      this->SetReturnValue(result);
442
    }
443
4535
  }
444
445
  const Info& _cbinfo;
446
  CallbackBundle* _bundle;
447
};
448
449
class FunctionCallbackWrapper
450
    : public CallbackWrapperBase<v8::FunctionCallbackInfo<v8::Value>,
451
                                 &CallbackBundle::function_or_getter> {
452
 public:
453
4535
  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
454
4535
    FunctionCallbackWrapper cbwrapper(info);
455
4535
    cbwrapper.InvokeCallback();
456
4535
  }
457
458
4535
  explicit FunctionCallbackWrapper(
459
      const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
460
4535
      : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
461
462
8
  napi_value GetNewTarget() override {
463
16
    if (_cbinfo.IsConstructCall()) {
464
14
      return v8impl::JsValueFromV8LocalValue(_cbinfo.NewTarget());
465
    } else {
466
1
      return nullptr;
467
    }
468
  }
469
470
  /*virtual*/
471
4403
  void Args(napi_value* buffer, size_t buffer_length) override {
472
4403
    size_t i = 0;
473
4403
    size_t min = std::min(buffer_length, _args_length);
474
475
11368
    for (; i < min; i += 1) {
476
13930
      buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
477
    }
478
479
4403
    if (i < buffer_length) {
480
      napi_value undefined =
481
75
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
482
127
      for (; i < buffer_length; i += 1) {
483
102
        buffer[i] = undefined;
484
      }
485
    }
486
4403
  }
487
488
  /*virtual*/
489
2719
  void SetReturnValue(napi_value value) override {
490
2719
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
491
8157
    _cbinfo.GetReturnValue().Set(val);
492
2719
  }
493
};
494
495
class GetterCallbackWrapper
496
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<v8::Value>,
497
                                 &CallbackBundle::function_or_getter> {
498
 public:
499
  static void Invoke(v8::Local<v8::Name> property,
500
                     const v8::PropertyCallbackInfo<v8::Value>& info) {
501
    GetterCallbackWrapper cbwrapper(info);
502
    cbwrapper.InvokeCallback();
503
  }
504
505
  explicit GetterCallbackWrapper(
506
      const v8::PropertyCallbackInfo<v8::Value>& cbinfo)
507
      : CallbackWrapperBase(cbinfo, 0) {}
508
509
  /*virtual*/
510
  void Args(napi_value* buffer, size_t buffer_length) override {
511
    if (buffer_length > 0) {
512
      napi_value undefined =
513
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
514
      for (size_t i = 0; i < buffer_length; i += 1) {
515
        buffer[i] = undefined;
516
      }
517
    }
518
  }
519
520
  /*virtual*/
521
  void SetReturnValue(napi_value value) override {
522
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
523
    _cbinfo.GetReturnValue().Set(val);
524
  }
525
};
526
527
class SetterCallbackWrapper
528
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<void>,
529
                                 &CallbackBundle::setter> {
530
 public:
531
  static void Invoke(v8::Local<v8::Name> property,
532
                     v8::Local<v8::Value> value,
533
                     const v8::PropertyCallbackInfo<void>& info) {
534
    SetterCallbackWrapper cbwrapper(info, value);
535
    cbwrapper.InvokeCallback();
536
  }
537
538
  SetterCallbackWrapper(const v8::PropertyCallbackInfo<void>& cbinfo,
539
                        const v8::Local<v8::Value>& value)
540
      : CallbackWrapperBase(cbinfo, 1), _value(value) {}
541
542
  /*virtual*/
543
  void Args(napi_value* buffer, size_t buffer_length) override {
544
    if (buffer_length > 0) {
545
      buffer[0] = v8impl::JsValueFromV8LocalValue(_value);
546
547
      if (buffer_length > 1) {
548
        napi_value undefined = v8impl::JsValueFromV8LocalValue(
549
            v8::Undefined(_cbinfo.GetIsolate()));
550
        for (size_t i = 1; i < buffer_length; i += 1) {
551
          buffer[i] = undefined;
552
        }
553
      }
554
    }
555
  }
556
557
  /*virtual*/
558
  void SetReturnValue(napi_value value) override {
559
    // Ignore any value returned from a setter callback.
560
  }
561
562
 private:
563
  const v8::Local<v8::Value>& _value;
564
};
565
566
1
static void DeleteCallbackBundle(napi_env env, void* data, void* hint) {
567
1
  CallbackBundle* bundle = static_cast<CallbackBundle*>(data);
568
1
  delete bundle;
569
1
}
570
571
// Creates an object to be made available to the static function callback
572
// wrapper, used to retrieve the native callback function and data pointer.
573
static
574
375
v8::Local<v8::Value> CreateFunctionCallbackData(napi_env env,
575
                                                napi_callback cb,
576
                                                void* data) {
577
375
  CallbackBundle* bundle = new CallbackBundle();
578
375
  bundle->function_or_getter = cb;
579
375
  bundle->cb_data = data;
580
375
  bundle->env = env;
581
375
  v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
582
375
  Reference::New(env, cbdata, 0, true, DeleteCallbackBundle, bundle, nullptr);
583
584
375
  return cbdata;
585
}
586
587
enum WrapType {
588
  retrievable,
589
  anonymous
590
};
591
592
template <WrapType wrap_type>
593
1025
inline napi_status Wrap(napi_env env,
594
                        napi_value js_object,
595
                        void* native_object,
596
                        napi_finalize finalize_cb,
597
                        void* finalize_hint,
598
                        napi_ref* result) {
599




2050
  NAPI_PREAMBLE(env);
600

1025
  CHECK_ARG(env, js_object);
601
602
1025
  v8::Local<v8::Context> context = env->context();
603
604
1025
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
605

1025
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
606
1025
  v8::Local<v8::Object> obj = value.As<v8::Object>();
607
608
  if (wrap_type == retrievable) {
609
    // If we've already wrapped this object, we error out.
610
3057
    RETURN_STATUS_IF_FALSE(env,
611
        !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
612
            .FromJust(),
613
        napi_invalid_arg);
614
  } else if (wrap_type == anonymous) {
615
    // If no finalize callback is provided, we error out.
616
6
    CHECK_ARG(env, finalize_cb);
617
  }
618
619
1024
  v8impl::Reference* reference = nullptr;
620

1024
  if (result != nullptr) {
621
    // The returned reference should be deleted via napi_delete_reference()
622
    // ONLY in response to the finalize callback invocation. (If it is deleted
623
    // before then, then the finalize callback will never be invoked.)
624
    // Therefore a finalize callback is required when returning a reference.
625

8
    CHECK_ARG(env, finalize_cb);
626
8
    reference = v8impl::Reference::New(
627
24
        env, obj, 0, false, finalize_cb, native_object, finalize_hint);
628
8
    *result = reinterpret_cast<napi_ref>(reference);
629
  } else {
630
    // Create a self-deleting reference.
631
1016
    reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb,
632

3048
        native_object, finalize_cb == nullptr ? nullptr : finalize_hint);
633
  }
634
635
  if (wrap_type == retrievable) {
636
4072
    CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper),
637
          v8::External::New(env->isolate, reference)).FromJust());
638
  }
639
640

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


87
  NAPI_PREAMBLE(env);
702
43
  CHECK_ARG(env, result);
703
42
  CHECK_ARG(env, cb);
704
705
41
  v8::Isolate* isolate = env->isolate;
706
  v8::Local<v8::Function> return_value;
707
41
  v8::EscapableHandleScope scope(isolate);
708
  v8::Local<v8::Value> cbdata =
709
41
      v8impl::CreateFunctionCallbackData(env, cb, callback_data);
710
711
41
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
712
713
41
  v8::Local<v8::Context> context = env->context();
714
  v8::MaybeLocal<v8::Function> maybe_function =
715
      v8::Function::New(context,
716
                        v8impl::FunctionCallbackWrapper::Invoke,
717
41
                        cbdata);
718
41
  CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
719
720
41
  return_value = scope.Escape(maybe_function.ToLocalChecked());
721
722
41
  if (utf8name != nullptr) {
723
    v8::Local<v8::String> name_string;
724


96
    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
725
32
    return_value->SetName(name_string);
726
  }
727
728
82
  *result = v8impl::JsValueFromV8LocalValue(return_value);
729
730
84
  return GET_RETURN_STATUS(env);
731
}
732
733
13
napi_status napi_define_class(napi_env env,
734
                              const char* utf8name,
735
                              size_t length,
736
                              napi_callback constructor,
737
                              void* callback_data,
738
                              size_t property_count,
739
                              const napi_property_descriptor* properties,
740
                              napi_value* result) {
741


25
  NAPI_PREAMBLE(env);
742
12
  CHECK_ARG(env, result);
743
11
  CHECK_ARG(env, constructor);
744
745
10
  if (property_count > 0) {
746
7
    CHECK_ARG(env, properties);
747
  }
748
749
9
  v8::Isolate* isolate = env->isolate;
750
751
9
  v8::EscapableHandleScope scope(isolate);
752
  v8::Local<v8::Value> cbdata =
753
9
      v8impl::CreateFunctionCallbackData(env, constructor, callback_data);
754
755
9
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
756
757
  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(
758
9
      isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
759
760
  v8::Local<v8::String> name_string;
761


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

21
    if (p->getter != nullptr || p->setter != nullptr) {
790
      v8::Local<v8::FunctionTemplate> getter_tpl;
791
      v8::Local<v8::FunctionTemplate> setter_tpl;
792
10
      if (p->getter != nullptr) {
793
        v8::Local<v8::Value> getter_data =
794
10
            v8impl::CreateFunctionCallbackData(env, p->getter, p->data);
795
796
        getter_tpl = v8::FunctionTemplate::New(
797
10
            isolate, v8impl::FunctionCallbackWrapper::Invoke, getter_data);
798
      }
799
10
      if (p->setter != nullptr) {
800
        v8::Local<v8::Value> setter_data =
801
5
            v8impl::CreateFunctionCallbackData(env, p->setter, p->data);
802
803
        setter_tpl = v8::FunctionTemplate::New(
804
5
            isolate, v8impl::FunctionCallbackWrapper::Invoke, setter_data);
805
      }
806
807
30
      tpl->PrototypeTemplate()->SetAccessorProperty(
808
        property_name,
809
        getter_tpl,
810
        setter_tpl,
811
        attributes,
812
20
        v8::AccessControl::DEFAULT);
813
11
    } else if (p->method != nullptr) {
814
      v8::Local<v8::Value> cbdata =
815
5
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
816
817
5
      RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
818
819
      v8::Local<v8::FunctionTemplate> t =
820
        v8::FunctionTemplate::New(isolate,
821
          v8impl::FunctionCallbackWrapper::Invoke,
822
          cbdata,
823
5
          v8::Signature::New(isolate, tpl));
824
825
10
      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
826
    } else {
827
6
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
828
12
      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
829
    }
830
  }
831
832
8
  v8::Local<v8::Context> context = env->context();
833
  *result = v8impl::JsValueFromV8LocalValue(
834
24
      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
835
836
8
  if (static_property_count > 0) {
837
3
    std::vector<napi_property_descriptor> static_descriptors;
838
3
    static_descriptors.reserve(static_property_count);
839
840
26
    for (size_t i = 0; i < property_count; i++) {
841
23
      const napi_property_descriptor* p = properties + i;
842
23
      if ((p->attributes & napi_static) != 0) {
843
7
        static_descriptors.push_back(*p);
844
      }
845
    }
846
847
    napi_status status =
848
        napi_define_properties(env,
849
                               *result,
850
                               static_descriptors.size(),
851
3
                               static_descriptors.data());
852

3
    if (status != napi_ok) return status;
853
  }
854
855
20
  return GET_RETURN_STATUS(env);
856
}
857
858
5
napi_status napi_get_property_names(napi_env env,
859
                                    napi_value object,
860
                                    napi_value* result) {
861


10
  NAPI_PREAMBLE(env);
862
5
  CHECK_ARG(env, result);
863
864
5
  v8::Local<v8::Context> context = env->context();
865
  v8::Local<v8::Object> obj;
866

20
  CHECK_TO_OBJECT(env, context, obj, object);
867
868
  v8::MaybeLocal<v8::Array> maybe_propertynames = obj->GetPropertyNames(
869
    context,
870
    v8::KeyCollectionMode::kIncludePrototypes,
871
    static_cast<v8::PropertyFilter>(
872
        v8::PropertyFilter::ONLY_ENUMERABLE |
873
        v8::PropertyFilter::SKIP_SYMBOLS),
874
    v8::IndexFilter::kIncludeIndices,
875
5
    v8::KeyConversionMode::kConvertToString);
876
877
5
  CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure);
878
879
  *result = v8impl::JsValueFromV8LocalValue(
880
10
      maybe_propertynames.ToLocalChecked());
881
5
  return GET_RETURN_STATUS(env);
882
}
883
884
19
napi_status napi_set_property(napi_env env,
885
                              napi_value object,
886
                              napi_value key,
887
                              napi_value value) {
888


37
  NAPI_PREAMBLE(env);
889
18
  CHECK_ARG(env, key);
890
17
  CHECK_ARG(env, value);
891
892
16
  v8::Local<v8::Context> context = env->context();
893
  v8::Local<v8::Object> obj;
894
895

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


23
  NAPI_PREAMBLE(env);
911
11
  CHECK_ARG(env, result);
912
10
  CHECK_ARG(env, key);
913
914
9
  v8::Local<v8::Context> context = env->context();
915
  v8::Local<v8::Object> obj;
916
917

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


55
  NAPI_PREAMBLE(env);
933
27
  CHECK_ARG(env, key);
934
26
  CHECK_ARG(env, result);
935
936
25
  v8::Local<v8::Context> context = env->context();
937
25
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
938
  v8::Local<v8::Object> obj;
939
940

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


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

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


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

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


140
  NAPI_PREAMBLE(env);
997
70
  CHECK_ARG(env, value);
998
999
70
  v8::Local<v8::Context> context = env->context();
1000
  v8::Local<v8::Object> obj;
1001
1002

280
  CHECK_TO_OBJECT(env, context, obj, object);
1003
1004
  v8::Local<v8::Name> key;
1005

210
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1006
1007
70
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1008
1009
70
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1010
1011
140
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1012
70
  return GET_RETURN_STATUS(env);
1013
}
1014
1015
5
napi_status napi_has_named_property(napi_env env,
1016
                                    napi_value object,
1017
                                    const char* utf8name,
1018
                                    bool* result) {
1019


10
  NAPI_PREAMBLE(env);
1020
5
  CHECK_ARG(env, result);
1021
1022
5
  v8::Local<v8::Context> context = env->context();
1023
  v8::Local<v8::Object> obj;
1024
1025

20
  CHECK_TO_OBJECT(env, context, obj, object);
1026
1027
  v8::Local<v8::Name> key;
1028

15
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1029
1030
5
  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1031
1032
5
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1033
1034
10
  *result = has_maybe.FromMaybe(false);
1035
5
  return GET_RETURN_STATUS(env);
1036
}
1037
1038
1
napi_status napi_get_named_property(napi_env env,
1039
                                    napi_value object,
1040
                                    const char* utf8name,
1041
                                    napi_value* result) {
1042


2
  NAPI_PREAMBLE(env);
1043
1
  CHECK_ARG(env, result);
1044
1045
1
  v8::Local<v8::Context> context = env->context();
1046
1047
  v8::Local<v8::Name> key;
1048

3
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1049
1050
  v8::Local<v8::Object> obj;
1051
1052

4
  CHECK_TO_OBJECT(env, context, obj, object);
1053
1054
1
  auto get_maybe = obj->Get(context, key);
1055
1056
1
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1057
1058
1
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1059
1
  *result = v8impl::JsValueFromV8LocalValue(val);
1060
1
  return GET_RETURN_STATUS(env);
1061
}
1062
1063
11
napi_status napi_set_element(napi_env env,
1064
                             napi_value object,
1065
                             uint32_t index,
1066
                             napi_value value) {
1067


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

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


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

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


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

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


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

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


120
  NAPI_PREAMBLE(env);
1147
60
  if (property_count > 0) {
1148
60
    CHECK_ARG(env, properties);
1149
  }
1150
1151
60
  v8::Local<v8::Context> context = env->context();
1152
1153
  v8::Local<v8::Object> obj;
1154

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

316
    if (p->getter != nullptr || p->setter != nullptr) {
1168
      v8::Local<v8::Value> local_getter;
1169
      v8::Local<v8::Value> local_setter;
1170
1171
9
      if (p->getter != nullptr) {
1172
        v8::Local<v8::Value> getter_data =
1173
9
            v8impl::CreateFunctionCallbackData(env, p->getter, p->data);
1174
9
        CHECK_MAYBE_EMPTY(env, getter_data, napi_generic_failure);
1175
1176
        v8::MaybeLocal<v8::Function> maybe_getter =
1177
            v8::Function::New(context,
1178
                              v8impl::FunctionCallbackWrapper::Invoke,
1179
9
                              getter_data);
1180
9
        CHECK_MAYBE_EMPTY(env, maybe_getter, napi_generic_failure);
1181
1182
9
        local_getter = maybe_getter.ToLocalChecked();
1183
      }
1184
9
      if (p->setter != nullptr) {
1185
        v8::Local<v8::Value> setter_data =
1186
2
            v8impl::CreateFunctionCallbackData(env, p->setter, p->data);
1187
2
        CHECK_MAYBE_EMPTY(env, setter_data, napi_generic_failure);
1188
1189
        v8::MaybeLocal<v8::Function> maybe_setter =
1190
            v8::Function::New(context,
1191
                              v8impl::FunctionCallbackWrapper::Invoke,
1192
2
                              setter_data);
1193
2
        CHECK_MAYBE_EMPTY(env, maybe_setter, napi_generic_failure);
1194
2
        local_setter = maybe_setter.ToLocalChecked();
1195
      }
1196
1197
9
      v8::PropertyDescriptor descriptor(local_getter, local_setter);
1198
9
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1199
9
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1200
1201
      auto define_maybe = obj->DefineProperty(context,
1202
                                              property_name,
1203
9
                                              descriptor);
1204
1205
18
      if (!define_maybe.FromMaybe(false)) {
1206
        return napi_set_last_error(env, napi_invalid_arg);
1207
9
      }
1208
307
    } else if (p->method != nullptr) {
1209
      v8::Local<v8::Value> cbdata =
1210
294
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
1211
1212
294
      CHECK_MAYBE_EMPTY(env, cbdata, napi_generic_failure);
1213
1214
      v8::MaybeLocal<v8::Function> maybe_fn =
1215
          v8::Function::New(context,
1216
                            v8impl::FunctionCallbackWrapper::Invoke,
1217
294
                            cbdata);
1218
1219
294
      CHECK_MAYBE_EMPTY(env, maybe_fn, napi_generic_failure);
1220
1221
      v8::PropertyDescriptor descriptor(maybe_fn.ToLocalChecked(),
1222
588
                                        (p->attributes & napi_writable) != 0);
1223
294
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1224
294
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1225
1226
      auto define_maybe = obj->DefineProperty(context,
1227
                                              property_name,
1228
294
                                              descriptor);
1229
1230
588
      if (!define_maybe.FromMaybe(false)) {
1231
        return napi_set_last_error(env, napi_generic_failure);
1232
294
      }
1233
    } else {
1234
13
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1235
1236
      v8::PropertyDescriptor descriptor(value,
1237
13
                                        (p->attributes & napi_writable) != 0);
1238
13
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1239
13
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1240
1241
      auto define_maybe =
1242
13
          obj->DefineProperty(context, property_name, descriptor);
1243
1244
26
      if (!define_maybe.FromMaybe(false)) {
1245
        return napi_set_last_error(env, napi_invalid_arg);
1246
13
      }
1247
    }
1248
  }
1249
1250
60
  return GET_RETURN_STATUS(env);
1251
}
1252
1253
11
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1254
11
  CHECK_ENV(env);
1255
11
  CHECK_ARG(env, value);
1256
11
  CHECK_ARG(env, result);
1257
1258
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1259
1260
22
  *result = val->IsArray();
1261
11
  return napi_clear_last_error(env);
1262
}
1263
1264
13
napi_status napi_get_array_length(napi_env env,
1265
                                  napi_value value,
1266
                                  uint32_t* result) {
1267


26
  NAPI_PREAMBLE(env);
1268
13
  CHECK_ARG(env, value);
1269
13
  CHECK_ARG(env, result);
1270
1271
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1272
13
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1273
1274
13
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1275
26
  *result = arr->Length();
1276
1277
13
  return GET_RETURN_STATUS(env);
1278
}
1279
1280
9
napi_status napi_strict_equals(napi_env env,
1281
                               napi_value lhs,
1282
                               napi_value rhs,
1283
                               bool* result) {
1284


18
  NAPI_PREAMBLE(env);
1285
9
  CHECK_ARG(env, lhs);
1286
9
  CHECK_ARG(env, rhs);
1287
9
  CHECK_ARG(env, result);
1288
1289
9
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1290
9
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1291
1292
18
  *result = a->StrictEquals(b);
1293
9
  return GET_RETURN_STATUS(env);
1294
}
1295
1296
4
napi_status napi_get_prototype(napi_env env,
1297
                               napi_value object,
1298
                               napi_value* result) {
1299


8
  NAPI_PREAMBLE(env);
1300
4
  CHECK_ARG(env, result);
1301
1302
4
  v8::Local<v8::Context> context = env->context();
1303
1304
  v8::Local<v8::Object> obj;
1305

16
  CHECK_TO_OBJECT(env, context, obj, object);
1306
1307
4
  v8::Local<v8::Value> val = obj->GetPrototype();
1308
4
  *result = v8impl::JsValueFromV8LocalValue(val);
1309
4
  return GET_RETURN_STATUS(env);
1310
}
1311
1312
18
napi_status napi_create_object(napi_env env, napi_value* result) {
1313
18
  CHECK_ENV(env);
1314
18
  CHECK_ARG(env, result);
1315
1316
  *result = v8impl::JsValueFromV8LocalValue(
1317
36
      v8::Object::New(env->isolate));
1318
1319
18
  return napi_clear_last_error(env);
1320
}
1321
1322
1
napi_status napi_create_array(napi_env env, napi_value* result) {
1323
1
  CHECK_ENV(env);
1324
1
  CHECK_ARG(env, result);
1325
1326
  *result = v8impl::JsValueFromV8LocalValue(
1327
2
      v8::Array::New(env->isolate));
1328
1329
1
  return napi_clear_last_error(env);
1330
}
1331
1332
4
napi_status napi_create_array_with_length(napi_env env,
1333
                                          size_t length,
1334
                                          napi_value* result) {
1335
4
  CHECK_ENV(env);
1336
4
  CHECK_ARG(env, result);
1337
1338
  *result = v8impl::JsValueFromV8LocalValue(
1339
8
      v8::Array::New(env->isolate, length));
1340
1341
4
  return napi_clear_last_error(env);
1342
}
1343
1344
12
napi_status napi_create_string_latin1(napi_env env,
1345
                                      const char* str,
1346
                                      size_t length,
1347
                                      napi_value* result) {
1348
12
  CHECK_ENV(env);
1349
12
  CHECK_ARG(env, result);
1350

12
  RETURN_STATUS_IF_FALSE(env,
1351
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1352
      napi_invalid_arg);
1353
1354
11
  auto isolate = env->isolate;
1355
  auto str_maybe =
1356
      v8::String::NewFromOneByte(isolate,
1357
                                 reinterpret_cast<const uint8_t*>(str),
1358
                                 v8::NewStringType::kNormal,
1359
11
                                 length);
1360
11
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1361
1362
22
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1363
11
  return napi_clear_last_error(env);
1364
}
1365
1366
605
napi_status napi_create_string_utf8(napi_env env,
1367
                                    const char* str,
1368
                                    size_t length,
1369
                                    napi_value* result) {
1370
605
  CHECK_ENV(env);
1371
605
  CHECK_ARG(env, result);
1372

605
  RETURN_STATUS_IF_FALSE(env,
1373
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1374
      napi_invalid_arg);
1375
1376
604
  auto isolate = env->isolate;
1377
  auto str_maybe =
1378
      v8::String::NewFromUtf8(isolate,
1379
                              str,
1380
                              v8::NewStringType::kNormal,
1381
604
                              static_cast<int>(length));
1382
604
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1383
1208
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1384
604
  return napi_clear_last_error(env);
1385
}
1386
1387
14
napi_status napi_create_string_utf16(napi_env env,
1388
                                     const char16_t* str,
1389
                                     size_t length,
1390
                                     napi_value* result) {
1391
14
  CHECK_ENV(env);
1392
14
  CHECK_ARG(env, result);
1393

14
  RETURN_STATUS_IF_FALSE(env,
1394
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1395
      napi_invalid_arg);
1396
1397
13
  auto isolate = env->isolate;
1398
  auto str_maybe =
1399
      v8::String::NewFromTwoByte(isolate,
1400
                                 reinterpret_cast<const uint16_t*>(str),
1401
                                 v8::NewStringType::kNormal,
1402
13
                                 length);
1403
13
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1404
1405
26
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1406
13
  return napi_clear_last_error(env);
1407
}
1408
1409
71
napi_status napi_create_double(napi_env env,
1410
                               double value,
1411
                               napi_value* result) {
1412
71
  CHECK_ENV(env);
1413
71
  CHECK_ARG(env, result);
1414
1415
  *result = v8impl::JsValueFromV8LocalValue(
1416
142
      v8::Number::New(env->isolate, value));
1417
1418
71
  return napi_clear_last_error(env);
1419
}
1420
1421
156
napi_status napi_create_int32(napi_env env,
1422
                              int32_t value,
1423
                              napi_value* result) {
1424
156
  CHECK_ENV(env);
1425
156
  CHECK_ARG(env, result);
1426
1427
  *result = v8impl::JsValueFromV8LocalValue(
1428
312
      v8::Integer::New(env->isolate, value));
1429
1430
156
  return napi_clear_last_error(env);
1431
}
1432
1433
551
napi_status napi_create_uint32(napi_env env,
1434
                               uint32_t value,
1435
                               napi_value* result) {
1436
551
  CHECK_ENV(env);
1437
551
  CHECK_ARG(env, result);
1438
1439
  *result = v8impl::JsValueFromV8LocalValue(
1440
1102
      v8::Integer::NewFromUnsigned(env->isolate, value));
1441
1442
551
  return napi_clear_last_error(env);
1443
}
1444
1445
24
napi_status napi_create_int64(napi_env env,
1446
                              int64_t value,
1447
                              napi_value* result) {
1448
24
  CHECK_ENV(env);
1449
24
  CHECK_ARG(env, result);
1450
1451
  *result = v8impl::JsValueFromV8LocalValue(
1452
48
      v8::Number::New(env->isolate, static_cast<double>(value)));
1453
1454
24
  return napi_clear_last_error(env);
1455
}
1456
1457
9
napi_status napi_create_bigint_int64(napi_env env,
1458
                                     int64_t value,
1459
                                     napi_value* result) {
1460
9
  CHECK_ENV(env);
1461
9
  CHECK_ARG(env, result);
1462
1463
  *result = v8impl::JsValueFromV8LocalValue(
1464
18
      v8::BigInt::New(env->isolate, value));
1465
1466
9
  return napi_clear_last_error(env);
1467
}
1468
1469
6
napi_status napi_create_bigint_uint64(napi_env env,
1470
                                      uint64_t value,
1471
                                      napi_value* result) {
1472
6
  CHECK_ENV(env);
1473
6
  CHECK_ARG(env, result);
1474
1475
  *result = v8impl::JsValueFromV8LocalValue(
1476
12
      v8::BigInt::NewFromUnsigned(env->isolate, value));
1477
1478
6
  return napi_clear_last_error(env);
1479
}
1480
1481
12
napi_status napi_create_bigint_words(napi_env env,
1482
                                     int sign_bit,
1483
                                     size_t word_count,
1484
                                     const uint64_t* words,
1485
                                     napi_value* result) {
1486


24
  NAPI_PREAMBLE(env);
1487
12
  CHECK_ARG(env, words);
1488
12
  CHECK_ARG(env, result);
1489
1490
12
  v8::Local<v8::Context> context = env->context();
1491
1492
12
  if (word_count > INT_MAX) {
1493
1
    napi_throw_range_error(env, nullptr, "Maximum BigInt size exceeded");
1494
1
    return napi_set_last_error(env, napi_pending_exception);
1495
  }
1496
1497
  v8::MaybeLocal<v8::BigInt> b = v8::BigInt::NewFromWords(
1498
11
      context, sign_bit, word_count, words);
1499
1500
11
  if (try_catch.HasCaught()) {
1501
    return napi_set_last_error(env, napi_pending_exception);
1502
  } else {
1503
11
    CHECK_MAYBE_EMPTY(env, b, napi_generic_failure);
1504
22
    *result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
1505
11
    return napi_clear_last_error(env);
1506
12
  }
1507
}
1508
1509
1259
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
1510
1259
  CHECK_ENV(env);
1511
1259
  CHECK_ARG(env, result);
1512
1513
1259
  v8::Isolate* isolate = env->isolate;
1514
1515
1259
  if (value) {
1516
1432
    *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
1517
  } else {
1518
1086
    *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
1519
  }
1520
1521
1259
  return napi_clear_last_error(env);
1522
}
1523
1524
13
napi_status napi_create_symbol(napi_env env,
1525
                               napi_value description,
1526
                               napi_value* result) {
1527
13
  CHECK_ENV(env);
1528
13
  CHECK_ARG(env, result);
1529
1530
13
  v8::Isolate* isolate = env->isolate;
1531
1532
13
  if (description == nullptr) {
1533
6
    *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
1534
  } else {
1535
11
    v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
1536
22
    RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
1537
1538
    *result = v8impl::JsValueFromV8LocalValue(
1539
33
      v8::Symbol::New(isolate, desc.As<v8::String>()));
1540
  }
1541
1542
13
  return napi_clear_last_error(env);
1543
}
1544
1545
196
static inline napi_status set_error_code(napi_env env,
1546
                                         v8::Local<v8::Value> error,
1547
                                         napi_value code,
1548
                                         const char* code_cstring) {
1549

196
  if ((code != nullptr) || (code_cstring != nullptr)) {
1550
115
    v8::Local<v8::Context> context = env->context();
1551
115
    v8::Local<v8::Object> err_object = error.As<v8::Object>();
1552
1553
115
    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1554
115
    if (code != nullptr) {
1555
4
      code_value = v8impl::V8LocalValueFromJsValue(code);
1556
8
      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1557
    } else {
1558

333
      CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
1559
    }
1560
1561
    v8::Local<v8::Name> code_key;
1562
345
    CHECK_NEW_FROM_UTF8(env, code_key, "code");
1563
1564
115
    v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
1565
230
    RETURN_STATUS_IF_FALSE(env,
1566
                           set_maybe.FromMaybe(false),
1567
                           napi_generic_failure);
1568
  }
1569
196
  return napi_ok;
1570
}
1571
1572
4
napi_status napi_create_error(napi_env env,
1573
                              napi_value code,
1574
                              napi_value msg,
1575
                              napi_value* result) {
1576
4
  CHECK_ENV(env);
1577
4
  CHECK_ARG(env, msg);
1578
4
  CHECK_ARG(env, result);
1579
1580
4
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1581
8
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1582
1583
  v8::Local<v8::Value> error_obj =
1584
4
      v8::Exception::Error(message_value.As<v8::String>());
1585
4
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1586
4
  if (status != napi_ok) return status;
1587
1588
4
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1589
1590
4
  return napi_clear_last_error(env);
1591
}
1592
1593
2
napi_status napi_create_type_error(napi_env env,
1594
                                   napi_value code,
1595
                                   napi_value msg,
1596
                                   napi_value* result) {
1597
2
  CHECK_ENV(env);
1598
2
  CHECK_ARG(env, msg);
1599
2
  CHECK_ARG(env, result);
1600
1601
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1602
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1603
1604
  v8::Local<v8::Value> error_obj =
1605
2
      v8::Exception::TypeError(message_value.As<v8::String>());
1606
2
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1607
2
  if (status != napi_ok) return status;
1608
1609
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1610
1611
2
  return napi_clear_last_error(env);
1612
}
1613
1614
2
napi_status napi_create_range_error(napi_env env,
1615
                                    napi_value code,
1616
                                    napi_value msg,
1617
                                    napi_value* result) {
1618
2
  CHECK_ENV(env);
1619
2
  CHECK_ARG(env, msg);
1620
2
  CHECK_ARG(env, result);
1621
1622
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1623
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1624
1625
  v8::Local<v8::Value> error_obj =
1626
2
      v8::Exception::RangeError(message_value.As<v8::String>());
1627
2
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1628
2
  if (status != napi_ok) return status;
1629
1630
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1631
1632
2
  return napi_clear_last_error(env);
1633
}
1634
1635
437
napi_status napi_typeof(napi_env env,
1636
                        napi_value value,
1637
                        napi_valuetype* result) {
1638
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1639
  // JS exceptions.
1640
437
  CHECK_ENV(env);
1641
437
  CHECK_ARG(env, value);
1642
437
  CHECK_ARG(env, result);
1643
1644
437
  v8::Local<v8::Value> v = v8impl::V8LocalValueFromJsValue(value);
1645
1646
437
  if (v->IsNumber()) {
1647
141
    *result = napi_number;
1648
296
  } else if (v->IsBigInt()) {
1649
26
    *result = napi_bigint;
1650
540
  } else if (v->IsString()) {
1651
84
    *result = napi_string;
1652
186
  } else if (v->IsFunction()) {
1653
    // This test has to come before IsObject because IsFunction
1654
    // implies IsObject
1655
35
    *result = napi_function;
1656
151
  } else if (v->IsExternal()) {
1657
    // This test has to come before IsObject because IsExternal
1658
    // implies IsObject
1659
2
    *result = napi_external;
1660
149
  } else if (v->IsObject()) {
1661
136
    *result = napi_object;
1662
13
  } else if (v->IsBoolean()) {
1663
1
    *result = napi_boolean;
1664
24
  } else if (v->IsUndefined()) {
1665
2
    *result = napi_undefined;
1666
10
  } else if (v->IsSymbol()) {
1667
9
    *result = napi_symbol;
1668
2
  } else if (v->IsNull()) {
1669
1
    *result = napi_null;
1670
  } else {
1671
    // Should not get here unless V8 has added some new kind of value.
1672
    return napi_set_last_error(env, napi_invalid_arg);
1673
  }
1674
1675
437
  return napi_clear_last_error(env);
1676
}
1677
1678
141
napi_status napi_get_undefined(napi_env env, napi_value* result) {
1679
141
  CHECK_ENV(env);
1680
141
  CHECK_ARG(env, result);
1681
1682
  *result = v8impl::JsValueFromV8LocalValue(
1683
282
      v8::Undefined(env->isolate));
1684
1685
141
  return napi_clear_last_error(env);
1686
}
1687
1688
5
napi_status napi_get_null(napi_env env, napi_value* result) {
1689
5
  CHECK_ENV(env);
1690
5
  CHECK_ARG(env, result);
1691
1692
  *result = v8impl::JsValueFromV8LocalValue(
1693
10
        v8::Null(env->isolate));
1694
1695
5
  return napi_clear_last_error(env);
1696
}
1697
1698
// Gets all callback info in a single call. (Ugly, but faster.)
1699
4434
napi_status napi_get_cb_info(
1700
    napi_env env,               // [in] NAPI environment handle
1701
    napi_callback_info cbinfo,  // [in] Opaque callback-info handle
1702
    size_t* argc,      // [in-out] Specifies the size of the provided argv array
1703
                       // and receives the actual count of args.
1704
    napi_value* argv,  // [out] Array of values
1705
    napi_value* this_arg,  // [out] Receives the JS 'this' arg for the call
1706
    void** data) {         // [out] Receives the data pointer for the callback.
1707
4434
  CHECK_ENV(env);
1708
4434
  CHECK_ARG(env, cbinfo);
1709
1710
  v8impl::CallbackWrapper* info =
1711
4434
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1712
1713
4434
  if (argv != nullptr) {
1714
4403
    CHECK_ARG(env, argc);
1715
4403
    info->Args(argv, *argc);
1716
  }
1717
4434
  if (argc != nullptr) {
1718
4415
    *argc = info->ArgsLength();
1719
  }
1720
4434
  if (this_arg != nullptr) {
1721
39
    *this_arg = info->This();
1722
  }
1723
4434
  if (data != nullptr) {
1724
6
    *data = info->Data();
1725
  }
1726
1727
4434
  return napi_clear_last_error(env);
1728
}
1729
1730
8
napi_status napi_get_new_target(napi_env env,
1731
                                napi_callback_info cbinfo,
1732
                                napi_value* result) {
1733
8
  CHECK_ENV(env);
1734
8
  CHECK_ARG(env, cbinfo);
1735
8
  CHECK_ARG(env, result);
1736
1737
  v8impl::CallbackWrapper* info =
1738
8
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1739
1740
8
  *result = info->GetNewTarget();
1741
8
  return napi_clear_last_error(env);
1742
}
1743
1744
663
napi_status napi_call_function(napi_env env,
1745
                               napi_value recv,
1746
                               napi_value func,
1747
                               size_t argc,
1748
                               const napi_value* argv,
1749
                               napi_value* result) {
1750


1326
  NAPI_PREAMBLE(env);
1751
661
  CHECK_ARG(env, recv);
1752
661
  if (argc > 0) {
1753
604
    CHECK_ARG(env, argv);
1754
  }
1755
1756
661
  v8::Local<v8::Context> context = env->context();
1757
1758
661
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1759
1760
  v8::Local<v8::Function> v8func;
1761

1983
  CHECK_TO_FUNCTION(env, v8func, func);
1762
1763
  auto maybe = v8func->Call(context, v8recv, argc,
1764
1322
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1765
1766
661
  if (try_catch.HasCaught()) {
1767
6
    return napi_set_last_error(env, napi_pending_exception);
1768
  } else {
1769
655
    if (result != nullptr) {
1770
11
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1771
11
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1772
    }
1773
655
    return napi_clear_last_error(env);
1774
661
  }
1775
}
1776
1777
14
napi_status napi_get_global(napi_env env, napi_value* result) {
1778
14
  CHECK_ENV(env);
1779
14
  CHECK_ARG(env, result);
1780
1781
42
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1782
1783
14
  return napi_clear_last_error(env);
1784
}
1785
1786
11
napi_status napi_throw(napi_env env, napi_value error) {
1787


22
  NAPI_PREAMBLE(env);
1788
11
  CHECK_ARG(env, error);
1789
1790
11
  v8::Isolate* isolate = env->isolate;
1791
1792
11
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1793
  // any VM calls after this point and before returning
1794
  // to the javascript invoker will fail
1795
11
  return napi_clear_last_error(env);
1796
}
1797
1798
78
napi_status napi_throw_error(napi_env env,
1799
                             const char* code,
1800
                             const char* msg) {
1801


156
  NAPI_PREAMBLE(env);
1802
1803
75
  v8::Isolate* isolate = env->isolate;
1804
  v8::Local<v8::String> str;
1805

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


180
  NAPI_PREAMBLE(env);
1821
1822
90
  v8::Isolate* isolate = env->isolate;
1823
  v8::Local<v8::String> str;
1824

270
  CHECK_NEW_FROM_UTF8(env, str, msg);
1825
1826
90
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1827
90
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1828
90
  if (status != napi_ok) return status;
1829
1830
90
  isolate->ThrowException(error_obj);
1831
  // any VM calls after this point and before returning
1832
  // to the javascript invoker will fail
1833
90
  return napi_clear_last_error(env);
1834
}
1835
1836
23
napi_status napi_throw_range_error(napi_env env,
1837
                                   const char* code,
1838
                                   const char* msg) {
1839


46
  NAPI_PREAMBLE(env);
1840
1841
23
  v8::Isolate* isolate = env->isolate;
1842
  v8::Local<v8::String> str;
1843

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

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


28
  NAPI_PREAMBLE(env);
2169
14
  CHECK_ARG(env, value);
2170
14
  CHECK_ARG(env, result);
2171
2172
14
  v8::Isolate* isolate = env->isolate;
2173
  v8::Local<v8::Boolean> b =
2174
28
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2175
28
  *result = v8impl::JsValueFromV8LocalValue(b);
2176
14
  return GET_RETURN_STATUS(env);
2177
}
2178
2179
#define GEN_COERCE_FUNCTION(UpperCaseName, MixedCaseName, LowerCaseName)      \
2180
  napi_status napi_coerce_to_##LowerCaseName(napi_env env,                    \
2181
                                             napi_value value,                \
2182
                                             napi_value* result) {            \
2183
    NAPI_PREAMBLE(env);                                                       \
2184
    CHECK_ARG(env, value);                                                    \
2185
    CHECK_ARG(env, result);                                                   \
2186
                                                                              \
2187
    v8::Local<v8::Context> context = env->context();                          \
2188
    v8::Local<v8::MixedCaseName> str;                                         \
2189
                                                                              \
2190
    CHECK_TO_##UpperCaseName(env, context, str, value);                       \
2191
                                                                              \
2192
    *result = v8impl::JsValueFromV8LocalValue(str);                           \
2193
    return GET_RETURN_STATUS(env);                                            \
2194
  }
2195
2196




103
GEN_COERCE_FUNCTION(NUMBER, Number, number)
2197




105
GEN_COERCE_FUNCTION(OBJECT, Object, object)
2198




96
GEN_COERCE_FUNCTION(STRING, String, string)
2199
2200
#undef GEN_COERCE_FUNCTION
2201
2202
1019
napi_status napi_wrap(napi_env env,
2203
                      napi_value js_object,
2204
                      void* native_object,
2205
                      napi_finalize finalize_cb,
2206
                      void* finalize_hint,
2207
                      napi_ref* result) {
2208
  return v8impl::Wrap<v8impl::retrievable>(env,
2209
                                           js_object,
2210
                                           native_object,
2211
                                           finalize_cb,
2212
                                           finalize_hint,
2213
1019
                                           result);
2214
}
2215
2216
26
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2217
26
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2218
}
2219
2220
3
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2221
3
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2222
}
2223
2224
6
napi_status napi_create_external(napi_env env,
2225
                                 void* data,
2226
                                 napi_finalize finalize_cb,
2227
                                 void* finalize_hint,
2228
                                 napi_value* result) {
2229


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

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


14
  NAPI_PREAMBLE(env);
2451
7
  CHECK_ARG(env, constructor);
2452
7
  if (argc > 0) {
2453
7
    CHECK_ARG(env, argv);
2454
  }
2455
7
  CHECK_ARG(env, result);
2456
2457
7
  v8::Local<v8::Context> context = env->context();
2458
2459
  v8::Local<v8::Function> ctor;
2460

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


4556
  NAPI_PREAMBLE(env);
2476
2278
  CHECK_ARG(env, object);
2477
2278
  CHECK_ARG(env, result);
2478
2479
2278
  *result = false;
2480
2481
  v8::Local<v8::Object> ctor;
2482
2278
  v8::Local<v8::Context> context = env->context();
2483
2484

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


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


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


66
  NAPI_PREAMBLE(env);
2635
33
  CHECK_ARG(env, arraybuffer);
2636
33
  CHECK_ARG(env, result);
2637
2638
33
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2639
33
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2640
2641
33
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2642
  v8::Local<v8::TypedArray> typedArray;
2643
2644



33
  switch (type) {
2645
    case napi_int8_array:
2646
8
      CREATE_TYPED_ARRAY(
2647
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2648
2
      break;
2649
    case napi_uint8_array:
2650
8
      CREATE_TYPED_ARRAY(
2651
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2652
2
      break;
2653
    case napi_uint8_clamped_array:
2654
5
      CREATE_TYPED_ARRAY(
2655
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2656
1
      break;
2657
    case napi_int16_array:
2658

6
      CREATE_TYPED_ARRAY(
2659
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2660
1
      break;
2661
    case napi_uint16_array:
2662

6
      CREATE_TYPED_ARRAY(
2663
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2664
1
      break;
2665
    case napi_int32_array:
2666

6
      CREATE_TYPED_ARRAY(
2667
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2668
1
      break;
2669
    case napi_uint32_array:
2670

6
      CREATE_TYPED_ARRAY(
2671
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2672
1
      break;
2673
    case napi_float32_array:
2674

6
      CREATE_TYPED_ARRAY(
2675
          env, Float32Array, 4, buffer, byte_offset, length, typedArray);
2676
1
      break;
2677
    case napi_float64_array:
2678

9
      CREATE_TYPED_ARRAY(
2679
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2680
2
      break;
2681
    case napi_bigint64_array:
2682

6
      CREATE_TYPED_ARRAY(
2683
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2684
1
      break;
2685
    case napi_biguint64_array:
2686

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


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


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


2
  NAPI_PREAMBLE(env);
2887
1
  CHECK_ARG(env, result);
2888
2889
1
  v8::MaybeLocal<v8::Value> maybe_date = v8::Date::New(env->context(), time);
2890
1
  CHECK_MAYBE_EMPTY(env, maybe_date, napi_generic_failure);
2891
2892
2
  *result = v8impl::JsValueFromV8LocalValue(maybe_date.ToLocalChecked());
2893
2894
1
  return GET_RETURN_STATUS(env);
2895
}
2896
2897
7
napi_status napi_is_date(napi_env env,
2898
                         napi_value value,
2899
                         bool* is_date) {
2900
7
  CHECK_ENV(env);
2901
7
  CHECK_ARG(env, value);
2902
7
  CHECK_ARG(env, is_date);
2903
2904
14
  *is_date = v8impl::V8LocalValueFromJsValue(value)->IsDate();
2905
2906
7
  return napi_clear_last_error(env);
2907
}
2908
2909
1
napi_status napi_get_date_value(napi_env env,
2910
                                napi_value value,
2911
                                double* result) {
2912


2
  NAPI_PREAMBLE(env);
2913
1
  CHECK_ARG(env, value);
2914
1
  CHECK_ARG(env, result);
2915
2916
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2917
1
  RETURN_STATUS_IF_FALSE(env, val->IsDate(), napi_date_expected);
2918
2919
1
  v8::Local<v8::Date> date = val.As<v8::Date>();
2920
2
  *result = date->ValueOf();
2921
2922
1
  return GET_RETURN_STATUS(env);
2923
}
2924
2925
2
napi_status napi_run_script(napi_env env,
2926
                            napi_value script,
2927
                            napi_value* result) {
2928


4
  NAPI_PREAMBLE(env);
2929
2
  CHECK_ARG(env, script);
2930
2
  CHECK_ARG(env, result);
2931
2932
2
  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
2933
2934
4
  if (!v8_script->IsString()) {
2935
1
    return napi_set_last_error(env, napi_string_expected);
2936
  }
2937
2938
1
  v8::Local<v8::Context> context = env->context();
2939
2940
  auto maybe_script = v8::Script::Compile(context,
2941
1
      v8::Local<v8::String>::Cast(v8_script));
2942
1
  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
2943
2944
  auto script_result =
2945
2
      maybe_script.ToLocalChecked()->Run(context);
2946
1
  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
2947
2948
2
  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
2949
1
  return GET_RETURN_STATUS(env);
2950
}
2951
2952
6
napi_status napi_add_finalizer(napi_env env,
2953
                               napi_value js_object,
2954
                               void* native_object,
2955
                               napi_finalize finalize_cb,
2956
                               void* finalize_hint,
2957
                               napi_ref* result) {
2958
  return v8impl::Wrap<v8impl::anonymous>(env,
2959
                                         js_object,
2960
                                         native_object,
2961
                                         finalize_cb,
2962
                                         finalize_hint,
2963
6
                                         result);
2964
}
2965
2966
1
napi_status napi_adjust_external_memory(napi_env env,
2967
                                        int64_t change_in_bytes,
2968
                                        int64_t* adjusted_value) {
2969
1
  CHECK_ENV(env);
2970
1
  CHECK_ARG(env, adjusted_value);
2971
2972
  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
2973
2
      change_in_bytes);
2974
2975
1
  return napi_clear_last_error(env);
2976
}
2977
2978
4
napi_status napi_set_instance_data(napi_env env,
2979
                                   void* data,
2980
                                   napi_finalize finalize_cb,
2981
                                   void* finalize_hint) {
2982
4
  CHECK_ENV(env);
2983
2984
4
  env->instance_data.data = data;
2985
4
  env->instance_data.finalize_cb = finalize_cb;
2986
4
  env->instance_data.hint = finalize_hint;
2987
2988
4
  return napi_clear_last_error(env);
2989
}
2990
2991
22
napi_status napi_get_instance_data(napi_env env,
2992
                                   void** data) {
2993
22
  CHECK_ENV(env);
2994
22
  CHECK_ARG(env, data);
2995
2996
22
  *data = env->instance_data.data;
2997
2998
22
  return napi_clear_last_error(env);
2999
}