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: 1248 1271 98.2 %
Date: 2019-08-17 22:35:23 Branches: 895 1500 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
5118
class Reference : private Finalizer {
190
 private:
191
2570
  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
5140
        _delete_self(delete_self) {
202
2570
    if (initial_refcount == 0) {
203
      _persistent.SetWeak(
204
2031
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
205
    }
206
2570
  }
207
208
 public:
209
27
  void* Data() {
210
27
    return _finalize_data;
211
  }
212
213
2570
  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
2570
      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
3564
  static void Delete(Reference* reference) {
245

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

4573
        (reference->_delete_self) ||
247
        (reference->_finalize_ran)) {
248
2559
      delete reference;
249
    } else {
250
      // defer until finalizer runs as
251
      // it may alread be queued
252
1005
      reference->_delete_self = true;
253
    }
254
3564
  }
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
3566
  uint32_t RefCount() {
277
3566
    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
2024
  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
297
2024
    Reference* reference = data.GetParameter();
298
299
    // The reference must be reset during the first pass.
300
2024
    reference->_persistent.Reset();
301
302
2024
    data.SetSecondPassCallback(SecondPassCallback);
303
2024
  }
304
305
2024
  static void SecondPassCallback(const v8::WeakCallbackInfo<Reference>& data) {
306
2024
    Reference* reference = data.GetParameter();
307
308
2024
    if (reference->_finalize_callback != nullptr) {
309
1021
      reference->_env->CallIntoModuleThrow([&](napi_env env) {
310
        reference->_finalize_callback(
311
            env,
312
            reference->_finalize_data,
313
1021
            reference->_finalize_hint);
314
2042
      });
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
2024
    if (reference->_delete_self) {
321
2020
      Delete(reference);
322
    } else {
323
4
      reference->_finalize_ran = true;
324
    }
325
2024
  }
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
752
struct CallbackBundle {
382
  // Bind the lifecycle of `this` C++ object to a JavaScript object.
383
  // We never delete a CallbackBundle C++ object directly.
384
375
  void BindLifecycleTo(v8::Isolate* isolate, v8::Local<v8::Value> target) {
385
375
    handle.Reset(isolate, target);
386
375
    handle.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
387
375
  }
388
389
  napi_env       env;      // Necessary to invoke C++ NAPI callback
390
  void*          cb_data;  // The user provided callback data
391
  napi_callback  function_or_getter;
392
  napi_callback  setter;
393
  v8impl::Persistent<v8::Value> handle;  // Die with this JavaScript object
394
395
 private:
396
1
  static void WeakCallback(v8::WeakCallbackInfo<CallbackBundle> const& info) {
397
    // Use the "WeakCallback mechanism" to delete the C++ `bundle` object.
398
    // This will be called when the v8::External containing `this` pointer
399
    // is being GC-ed.
400
1
    CallbackBundle* bundle = info.GetParameter();
401
1
    delete bundle;
402
1
  }
403
};
404
405
// Base class extended by classes that wrap V8 function and property callback
406
// info.
407
class CallbackWrapper {
408
 public:
409
4535
  CallbackWrapper(napi_value this_arg, size_t args_length, void* data)
410
4535
      : _this(this_arg), _args_length(args_length), _data(data) {}
411
412
  virtual napi_value GetNewTarget() = 0;
413
  virtual void Args(napi_value* buffer, size_t bufferlength) = 0;
414
  virtual void SetReturnValue(napi_value value) = 0;
415
416
39
  napi_value This() { return _this; }
417
418
4415
  size_t ArgsLength() { return _args_length; }
419
420
6
  void* Data() { return _data; }
421
422
 protected:
423
  const napi_value _this;
424
  const size_t _args_length;
425
  void* _data;
426
};
427
428
template <typename Info, napi_callback CallbackBundle::*FunctionField>
429
class CallbackWrapperBase : public CallbackWrapper {
430
 public:
431
4535
  CallbackWrapperBase(const Info& cbinfo, const size_t args_length)
432
      : CallbackWrapper(JsValueFromV8LocalValue(cbinfo.This()),
433
                        args_length,
434
                        nullptr),
435
4535
        _cbinfo(cbinfo) {
436
9070
    _bundle = reinterpret_cast<CallbackBundle*>(
437
        v8::Local<v8::External>::Cast(cbinfo.Data())->Value());
438
4535
    _data = _bundle->cb_data;
439
4535
  }
440
441
  napi_value GetNewTarget() override { return nullptr; }
442
443
 protected:
444
4535
  void InvokeCallback() {
445
    napi_callback_info cbinfo_wrapper = reinterpret_cast<napi_callback_info>(
446
4535
        static_cast<CallbackWrapper*>(this));
447
448
    // All other pointers we need are stored in `_bundle`
449
4535
    napi_env env = _bundle->env;
450
4535
    napi_callback cb = _bundle->*FunctionField;
451
452
    napi_value result;
453
9070
    env->CallIntoModuleThrow([&](napi_env env) {
454
4535
      result = cb(env, cbinfo_wrapper);
455
4535
    });
456
457
4535
    if (result != nullptr) {
458
2719
      this->SetReturnValue(result);
459
    }
460
4535
  }
461
462
  const Info& _cbinfo;
463
  CallbackBundle* _bundle;
464
};
465
466
class FunctionCallbackWrapper
467
    : public CallbackWrapperBase<v8::FunctionCallbackInfo<v8::Value>,
468
                                 &CallbackBundle::function_or_getter> {
469
 public:
470
4535
  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
471
4535
    FunctionCallbackWrapper cbwrapper(info);
472
4535
    cbwrapper.InvokeCallback();
473
4535
  }
474
475
4535
  explicit FunctionCallbackWrapper(
476
      const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
477
4535
      : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
478
479
8
  napi_value GetNewTarget() override {
480
16
    if (_cbinfo.IsConstructCall()) {
481
14
      return v8impl::JsValueFromV8LocalValue(_cbinfo.NewTarget());
482
    } else {
483
1
      return nullptr;
484
    }
485
  }
486
487
  /*virtual*/
488
4403
  void Args(napi_value* buffer, size_t buffer_length) override {
489
4403
    size_t i = 0;
490
4403
    size_t min = std::min(buffer_length, _args_length);
491
492
11368
    for (; i < min; i += 1) {
493
13930
      buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
494
    }
495
496
4403
    if (i < buffer_length) {
497
      napi_value undefined =
498
75
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
499
127
      for (; i < buffer_length; i += 1) {
500
102
        buffer[i] = undefined;
501
      }
502
    }
503
4403
  }
504
505
  /*virtual*/
506
2719
  void SetReturnValue(napi_value value) override {
507
2719
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
508
8157
    _cbinfo.GetReturnValue().Set(val);
509
2719
  }
510
};
511
512
class GetterCallbackWrapper
513
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<v8::Value>,
514
                                 &CallbackBundle::function_or_getter> {
515
 public:
516
  static void Invoke(v8::Local<v8::Name> property,
517
                     const v8::PropertyCallbackInfo<v8::Value>& info) {
518
    GetterCallbackWrapper cbwrapper(info);
519
    cbwrapper.InvokeCallback();
520
  }
521
522
  explicit GetterCallbackWrapper(
523
      const v8::PropertyCallbackInfo<v8::Value>& cbinfo)
524
      : CallbackWrapperBase(cbinfo, 0) {}
525
526
  /*virtual*/
527
  void Args(napi_value* buffer, size_t buffer_length) override {
528
    if (buffer_length > 0) {
529
      napi_value undefined =
530
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
531
      for (size_t i = 0; i < buffer_length; i += 1) {
532
        buffer[i] = undefined;
533
      }
534
    }
535
  }
536
537
  /*virtual*/
538
  void SetReturnValue(napi_value value) override {
539
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
540
    _cbinfo.GetReturnValue().Set(val);
541
  }
542
};
543
544
class SetterCallbackWrapper
545
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<void>,
546
                                 &CallbackBundle::setter> {
547
 public:
548
  static void Invoke(v8::Local<v8::Name> property,
549
                     v8::Local<v8::Value> value,
550
                     const v8::PropertyCallbackInfo<void>& info) {
551
    SetterCallbackWrapper cbwrapper(info, value);
552
    cbwrapper.InvokeCallback();
553
  }
554
555
  SetterCallbackWrapper(const v8::PropertyCallbackInfo<void>& cbinfo,
556
                        const v8::Local<v8::Value>& value)
557
      : CallbackWrapperBase(cbinfo, 1), _value(value) {}
558
559
  /*virtual*/
560
  void Args(napi_value* buffer, size_t buffer_length) override {
561
    if (buffer_length > 0) {
562
      buffer[0] = v8impl::JsValueFromV8LocalValue(_value);
563
564
      if (buffer_length > 1) {
565
        napi_value undefined = v8impl::JsValueFromV8LocalValue(
566
            v8::Undefined(_cbinfo.GetIsolate()));
567
        for (size_t i = 1; i < buffer_length; i += 1) {
568
          buffer[i] = undefined;
569
        }
570
      }
571
    }
572
  }
573
574
  /*virtual*/
575
  void SetReturnValue(napi_value value) override {
576
    // Ignore any value returned from a setter callback.
577
  }
578
579
 private:
580
  const v8::Local<v8::Value>& _value;
581
};
582
583
// Creates an object to be made available to the static function callback
584
// wrapper, used to retrieve the native callback function and data pointer.
585
static
586
375
v8::Local<v8::Value> CreateFunctionCallbackData(napi_env env,
587
                                                napi_callback cb,
588
                                                void* data) {
589
375
  CallbackBundle* bundle = new CallbackBundle();
590
375
  bundle->function_or_getter = cb;
591
375
  bundle->cb_data = data;
592
375
  bundle->env = env;
593
375
  v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
594
375
  bundle->BindLifecycleTo(env->isolate, cbdata);
595
596
375
  return cbdata;
597
}
598
599
enum WrapType {
600
  retrievable,
601
  anonymous
602
};
603
604
template <WrapType wrap_type>
605
1025
inline napi_status Wrap(napi_env env,
606
                        napi_value js_object,
607
                        void* native_object,
608
                        napi_finalize finalize_cb,
609
                        void* finalize_hint,
610
                        napi_ref* result) {
611




2050
  NAPI_PREAMBLE(env);
612

1025
  CHECK_ARG(env, js_object);
613
614
1025
  v8::Local<v8::Context> context = env->context();
615
616
1025
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
617

1025
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
618
1025
  v8::Local<v8::Object> obj = value.As<v8::Object>();
619
620
  if (wrap_type == retrievable) {
621
    // If we've already wrapped this object, we error out.
622
3057
    RETURN_STATUS_IF_FALSE(env,
623
        !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
624
            .FromJust(),
625
        napi_invalid_arg);
626
  } else if (wrap_type == anonymous) {
627
    // If no finalize callback is provided, we error out.
628
6
    CHECK_ARG(env, finalize_cb);
629
  }
630
631
1024
  v8impl::Reference* reference = nullptr;
632

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

8
    CHECK_ARG(env, finalize_cb);
638
8
    reference = v8impl::Reference::New(
639
24
        env, obj, 0, false, finalize_cb, native_object, finalize_hint);
640
8
    *result = reinterpret_cast<napi_ref>(reference);
641
  } else {
642
    // Create a self-deleting reference.
643
1016
    reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb,
644

3048
        native_object, finalize_cb == nullptr ? nullptr : finalize_hint);
645
  }
646
647
  if (wrap_type == retrievable) {
648
4072
    CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper),
649
          v8::External::New(env->isolate, reference)).FromJust());
650
  }
651
652

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


87
  NAPI_PREAMBLE(env);
714
43
  CHECK_ARG(env, result);
715
42
  CHECK_ARG(env, cb);
716
717
41
  v8::Isolate* isolate = env->isolate;
718
  v8::Local<v8::Function> return_value;
719
41
  v8::EscapableHandleScope scope(isolate);
720
  v8::Local<v8::Value> cbdata =
721
41
      v8impl::CreateFunctionCallbackData(env, cb, callback_data);
722
723
41
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
724
725
41
  v8::Local<v8::Context> context = env->context();
726
  v8::MaybeLocal<v8::Function> maybe_function =
727
      v8::Function::New(context,
728
                        v8impl::FunctionCallbackWrapper::Invoke,
729
41
                        cbdata);
730
41
  CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
731
732
41
  return_value = scope.Escape(maybe_function.ToLocalChecked());
733
734
41
  if (utf8name != nullptr) {
735
    v8::Local<v8::String> name_string;
736


96
    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
737
32
    return_value->SetName(name_string);
738
  }
739
740
82
  *result = v8impl::JsValueFromV8LocalValue(return_value);
741
742
84
  return GET_RETURN_STATUS(env);
743
}
744
745
13
napi_status napi_define_class(napi_env env,
746
                              const char* utf8name,
747
                              size_t length,
748
                              napi_callback constructor,
749
                              void* callback_data,
750
                              size_t property_count,
751
                              const napi_property_descriptor* properties,
752
                              napi_value* result) {
753


25
  NAPI_PREAMBLE(env);
754
12
  CHECK_ARG(env, result);
755
11
  CHECK_ARG(env, constructor);
756
757
10
  if (property_count > 0) {
758
7
    CHECK_ARG(env, properties);
759
  }
760
761
9
  v8::Isolate* isolate = env->isolate;
762
763
9
  v8::EscapableHandleScope scope(isolate);
764
  v8::Local<v8::Value> cbdata =
765
9
      v8impl::CreateFunctionCallbackData(env, constructor, callback_data);
766
767
9
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
768
769
  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(
770
9
      isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
771
772
  v8::Local<v8::String> name_string;
773


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

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

3
    if (status != napi_ok) return status;
865
  }
866
867
20
  return GET_RETURN_STATUS(env);
868
}
869
870
5
napi_status napi_get_property_names(napi_env env,
871
                                    napi_value object,
872
                                    napi_value* result) {
873


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

20
  CHECK_TO_OBJECT(env, context, obj, object);
879
880
  v8::MaybeLocal<v8::Array> maybe_propertynames = obj->GetPropertyNames(
881
    context,
882
    v8::KeyCollectionMode::kIncludePrototypes,
883
    static_cast<v8::PropertyFilter>(
884
        v8::PropertyFilter::ONLY_ENUMERABLE |
885
        v8::PropertyFilter::SKIP_SYMBOLS),
886
    v8::IndexFilter::kIncludeIndices,
887
5
    v8::KeyConversionMode::kConvertToString);
888
889
5
  CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure);
890
891
  *result = v8impl::JsValueFromV8LocalValue(
892
10
      maybe_propertynames.ToLocalChecked());
893
5
  return GET_RETURN_STATUS(env);
894
}
895
896
19
napi_status napi_set_property(napi_env env,
897
                              napi_value object,
898
                              napi_value key,
899
                              napi_value value) {
900


37
  NAPI_PREAMBLE(env);
901
18
  CHECK_ARG(env, key);
902
17
  CHECK_ARG(env, value);
903
904
16
  v8::Local<v8::Context> context = env->context();
905
  v8::Local<v8::Object> obj;
906
907

62
  CHECK_TO_OBJECT(env, context, obj, object);
908
909
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
910
15
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
911
912
15
  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
913
914
30
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
915
15
  return GET_RETURN_STATUS(env);
916
}
917
918
12
napi_status napi_has_property(napi_env env,
919
                              napi_value object,
920
                              napi_value key,
921
                              bool* result) {
922


23
  NAPI_PREAMBLE(env);
923
11
  CHECK_ARG(env, result);
924
10
  CHECK_ARG(env, key);
925
926
9
  v8::Local<v8::Context> context = env->context();
927
  v8::Local<v8::Object> obj;
928
929

34
  CHECK_TO_OBJECT(env, context, obj, object);
930
931
8
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
932
8
  v8::Maybe<bool> has_maybe = obj->Has(context, k);
933
934
8
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
935
936
16
  *result = has_maybe.FromMaybe(false);
937
8
  return GET_RETURN_STATUS(env);
938
}
939
940
28
napi_status napi_get_property(napi_env env,
941
                              napi_value object,
942
                              napi_value key,
943
                              napi_value* result) {
944


55
  NAPI_PREAMBLE(env);
945
27
  CHECK_ARG(env, key);
946
26
  CHECK_ARG(env, result);
947
948
25
  v8::Local<v8::Context> context = env->context();
949
25
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
950
  v8::Local<v8::Object> obj;
951
952

98
  CHECK_TO_OBJECT(env, context, obj, object);
953
954
24
  auto get_maybe = obj->Get(context, k);
955
956
24
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
957
958
24
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
959
24
  *result = v8impl::JsValueFromV8LocalValue(val);
960
24
  return GET_RETURN_STATUS(env);
961
}
962
963
5
napi_status napi_delete_property(napi_env env,
964
                                 napi_value object,
965
                                 napi_value key,
966
                                 bool* result) {
967


10
  NAPI_PREAMBLE(env);
968
5
  CHECK_ARG(env, key);
969
970
5
  v8::Local<v8::Context> context = env->context();
971
5
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
972
  v8::Local<v8::Object> obj;
973
974

20
  CHECK_TO_OBJECT(env, context, obj, object);
975
5
  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
976
5
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
977
978
5
  if (result != nullptr)
979
10
    *result = delete_maybe.FromMaybe(false);
980
981
5
  return GET_RETURN_STATUS(env);
982
}
983
984
15
napi_status napi_has_own_property(napi_env env,
985
                                  napi_value object,
986
                                  napi_value key,
987
                                  bool* result) {
988


30
  NAPI_PREAMBLE(env);
989
15
  CHECK_ARG(env, key);
990
991
15
  v8::Local<v8::Context> context = env->context();
992
  v8::Local<v8::Object> obj;
993
994

60
  CHECK_TO_OBJECT(env, context, obj, object);
995
15
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
996
24
  RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected);
997
6
  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
998
6
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
999
12
  *result = has_maybe.FromMaybe(false);
1000
1001
6
  return GET_RETURN_STATUS(env);
1002
}
1003
1004
70
napi_status napi_set_named_property(napi_env env,
1005
                                    napi_value object,
1006
                                    const char* utf8name,
1007
                                    napi_value value) {
1008


140
  NAPI_PREAMBLE(env);
1009
70
  CHECK_ARG(env, value);
1010
1011
70
  v8::Local<v8::Context> context = env->context();
1012
  v8::Local<v8::Object> obj;
1013
1014

280
  CHECK_TO_OBJECT(env, context, obj, object);
1015
1016
  v8::Local<v8::Name> key;
1017

210
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1018
1019
70
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1020
1021
70
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1022
1023
140
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1024
70
  return GET_RETURN_STATUS(env);
1025
}
1026
1027
5
napi_status napi_has_named_property(napi_env env,
1028
                                    napi_value object,
1029
                                    const char* utf8name,
1030
                                    bool* result) {
1031


10
  NAPI_PREAMBLE(env);
1032
5
  CHECK_ARG(env, result);
1033
1034
5
  v8::Local<v8::Context> context = env->context();
1035
  v8::Local<v8::Object> obj;
1036
1037

20
  CHECK_TO_OBJECT(env, context, obj, object);
1038
1039
  v8::Local<v8::Name> key;
1040

15
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1041
1042
5
  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1043
1044
5
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1045
1046
10
  *result = has_maybe.FromMaybe(false);
1047
5
  return GET_RETURN_STATUS(env);
1048
}
1049
1050
1
napi_status napi_get_named_property(napi_env env,
1051
                                    napi_value object,
1052
                                    const char* utf8name,
1053
                                    napi_value* result) {
1054


2
  NAPI_PREAMBLE(env);
1055
1
  CHECK_ARG(env, result);
1056
1057
1
  v8::Local<v8::Context> context = env->context();
1058
1059
  v8::Local<v8::Name> key;
1060

3
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1061
1062
  v8::Local<v8::Object> obj;
1063
1064

4
  CHECK_TO_OBJECT(env, context, obj, object);
1065
1066
1
  auto get_maybe = obj->Get(context, key);
1067
1068
1
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1069
1070
1
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1071
1
  *result = v8impl::JsValueFromV8LocalValue(val);
1072
1
  return GET_RETURN_STATUS(env);
1073
}
1074
1075
11
napi_status napi_set_element(napi_env env,
1076
                             napi_value object,
1077
                             uint32_t index,
1078
                             napi_value value) {
1079


22
  NAPI_PREAMBLE(env);
1080
11
  CHECK_ARG(env, value);
1081
1082
11
  v8::Local<v8::Context> context = env->context();
1083
  v8::Local<v8::Object> obj;
1084
1085

44
  CHECK_TO_OBJECT(env, context, obj, object);
1086
1087
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1088
11
  auto set_maybe = obj->Set(context, index, val);
1089
1090
22
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1091
1092
11
  return GET_RETURN_STATUS(env);
1093
}
1094
1095
2
napi_status napi_has_element(napi_env env,
1096
                             napi_value object,
1097
                             uint32_t index,
1098
                             bool* result) {
1099


4
  NAPI_PREAMBLE(env);
1100
2
  CHECK_ARG(env, result);
1101
1102
2
  v8::Local<v8::Context> context = env->context();
1103
  v8::Local<v8::Object> obj;
1104
1105

8
  CHECK_TO_OBJECT(env, context, obj, object);
1106
1107
2
  v8::Maybe<bool> has_maybe = obj->Has(context, index);
1108
1109
2
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1110
1111
4
  *result = has_maybe.FromMaybe(false);
1112
2
  return GET_RETURN_STATUS(env);
1113
}
1114
1115
27
napi_status napi_get_element(napi_env env,
1116
                             napi_value object,
1117
                             uint32_t index,
1118
                             napi_value* result) {
1119


54
  NAPI_PREAMBLE(env);
1120
27
  CHECK_ARG(env, result);
1121
1122
27
  v8::Local<v8::Context> context = env->context();
1123
  v8::Local<v8::Object> obj;
1124
1125

108
  CHECK_TO_OBJECT(env, context, obj, object);
1126
1127
27
  auto get_maybe = obj->Get(context, index);
1128
1129
27
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1130
1131
54
  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
1132
27
  return GET_RETURN_STATUS(env);
1133
}
1134
1135
1
napi_status napi_delete_element(napi_env env,
1136
                                napi_value object,
1137
                                uint32_t index,
1138
                                bool* result) {
1139


2
  NAPI_PREAMBLE(env);
1140
1141
1
  v8::Local<v8::Context> context = env->context();
1142
  v8::Local<v8::Object> obj;
1143
1144

4
  CHECK_TO_OBJECT(env, context, obj, object);
1145
1
  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
1146
1
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1147
1148
1
  if (result != nullptr)
1149
2
    *result = delete_maybe.FromMaybe(false);
1150
1151
1
  return GET_RETURN_STATUS(env);
1152
}
1153
1154
60
napi_status napi_define_properties(napi_env env,
1155
                                   napi_value object,
1156
                                   size_t property_count,
1157
                                   const napi_property_descriptor* properties) {
1158


120
  NAPI_PREAMBLE(env);
1159
60
  if (property_count > 0) {
1160
60
    CHECK_ARG(env, properties);
1161
  }
1162
1163
60
  v8::Local<v8::Context> context = env->context();
1164
1165
  v8::Local<v8::Object> obj;
1166

240
  CHECK_TO_OBJECT(env, context, obj, object);
1167
1168
752
  for (size_t i = 0; i < property_count; i++) {
1169
316
    const napi_property_descriptor* p = &properties[i];
1170
1171
    v8::Local<v8::Name> property_name;
1172
    napi_status status =
1173
316
        v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
1174
1175
316
    if (status != napi_ok) {
1176
      return napi_set_last_error(env, status);
1177
    }
1178
1179

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


26
  NAPI_PREAMBLE(env);
1280
13
  CHECK_ARG(env, value);
1281
13
  CHECK_ARG(env, result);
1282
1283
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1284
13
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1285
1286
13
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1287
26
  *result = arr->Length();
1288
1289
13
  return GET_RETURN_STATUS(env);
1290
}
1291
1292
9
napi_status napi_strict_equals(napi_env env,
1293
                               napi_value lhs,
1294
                               napi_value rhs,
1295
                               bool* result) {
1296


18
  NAPI_PREAMBLE(env);
1297
9
  CHECK_ARG(env, lhs);
1298
9
  CHECK_ARG(env, rhs);
1299
9
  CHECK_ARG(env, result);
1300
1301
9
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1302
9
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1303
1304
18
  *result = a->StrictEquals(b);
1305
9
  return GET_RETURN_STATUS(env);
1306
}
1307
1308
4
napi_status napi_get_prototype(napi_env env,
1309
                               napi_value object,
1310
                               napi_value* result) {
1311


8
  NAPI_PREAMBLE(env);
1312
4
  CHECK_ARG(env, result);
1313
1314
4
  v8::Local<v8::Context> context = env->context();
1315
1316
  v8::Local<v8::Object> obj;
1317

16
  CHECK_TO_OBJECT(env, context, obj, object);
1318
1319
4
  v8::Local<v8::Value> val = obj->GetPrototype();
1320
4
  *result = v8impl::JsValueFromV8LocalValue(val);
1321
4
  return GET_RETURN_STATUS(env);
1322
}
1323
1324
18
napi_status napi_create_object(napi_env env, napi_value* result) {
1325
18
  CHECK_ENV(env);
1326
18
  CHECK_ARG(env, result);
1327
1328
  *result = v8impl::JsValueFromV8LocalValue(
1329
36
      v8::Object::New(env->isolate));
1330
1331
18
  return napi_clear_last_error(env);
1332
}
1333
1334
1
napi_status napi_create_array(napi_env env, napi_value* result) {
1335
1
  CHECK_ENV(env);
1336
1
  CHECK_ARG(env, result);
1337
1338
  *result = v8impl::JsValueFromV8LocalValue(
1339
2
      v8::Array::New(env->isolate));
1340
1341
1
  return napi_clear_last_error(env);
1342
}
1343
1344
4
napi_status napi_create_array_with_length(napi_env env,
1345
                                          size_t length,
1346
                                          napi_value* result) {
1347
4
  CHECK_ENV(env);
1348
4
  CHECK_ARG(env, result);
1349
1350
  *result = v8impl::JsValueFromV8LocalValue(
1351
8
      v8::Array::New(env->isolate, length));
1352
1353
4
  return napi_clear_last_error(env);
1354
}
1355
1356
12
napi_status napi_create_string_latin1(napi_env env,
1357
                                      const char* str,
1358
                                      size_t length,
1359
                                      napi_value* result) {
1360
12
  CHECK_ENV(env);
1361
12
  CHECK_ARG(env, result);
1362

12
  RETURN_STATUS_IF_FALSE(env,
1363
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1364
      napi_invalid_arg);
1365
1366
11
  auto isolate = env->isolate;
1367
  auto str_maybe =
1368
      v8::String::NewFromOneByte(isolate,
1369
                                 reinterpret_cast<const uint8_t*>(str),
1370
                                 v8::NewStringType::kNormal,
1371
11
                                 length);
1372
11
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1373
1374
22
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1375
11
  return napi_clear_last_error(env);
1376
}
1377
1378
605
napi_status napi_create_string_utf8(napi_env env,
1379
                                    const char* str,
1380
                                    size_t length,
1381
                                    napi_value* result) {
1382
605
  CHECK_ENV(env);
1383
605
  CHECK_ARG(env, result);
1384

605
  RETURN_STATUS_IF_FALSE(env,
1385
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1386
      napi_invalid_arg);
1387
1388
604
  auto isolate = env->isolate;
1389
  auto str_maybe =
1390
      v8::String::NewFromUtf8(isolate,
1391
                              str,
1392
                              v8::NewStringType::kNormal,
1393
604
                              static_cast<int>(length));
1394
604
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1395
1208
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1396
604
  return napi_clear_last_error(env);
1397
}
1398
1399
14
napi_status napi_create_string_utf16(napi_env env,
1400
                                     const char16_t* str,
1401
                                     size_t length,
1402
                                     napi_value* result) {
1403
14
  CHECK_ENV(env);
1404
14
  CHECK_ARG(env, result);
1405

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


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

196
  if ((code != nullptr) || (code_cstring != nullptr)) {
1562
115
    v8::Local<v8::Context> context = env->context();
1563
115
    v8::Local<v8::Object> err_object = error.As<v8::Object>();
1564
1565
115
    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1566
115
    if (code != nullptr) {
1567
4
      code_value = v8impl::V8LocalValueFromJsValue(code);
1568
8
      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1569
    } else {
1570

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


1326
  NAPI_PREAMBLE(env);
1763
661
  CHECK_ARG(env, recv);
1764
661
  if (argc > 0) {
1765
604
    CHECK_ARG(env, argv);
1766
  }
1767
1768
661
  v8::Local<v8::Context> context = env->context();
1769
1770
661
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1771
1772
  v8::Local<v8::Function> v8func;
1773

1983
  CHECK_TO_FUNCTION(env, v8func, func);
1774
1775
  auto maybe = v8func->Call(context, v8recv, argc,
1776
1322
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1777
1778
661
  if (try_catch.HasCaught()) {
1779
6
    return napi_set_last_error(env, napi_pending_exception);
1780
  } else {
1781
655
    if (result != nullptr) {
1782
11
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1783
11
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1784
    }
1785
655
    return napi_clear_last_error(env);
1786
661
  }
1787
}
1788
1789
14
napi_status napi_get_global(napi_env env, napi_value* result) {
1790
14
  CHECK_ENV(env);
1791
14
  CHECK_ARG(env, result);
1792
1793
42
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1794
1795
14
  return napi_clear_last_error(env);
1796
}
1797
1798
11
napi_status napi_throw(napi_env env, napi_value error) {
1799


22
  NAPI_PREAMBLE(env);
1800
11
  CHECK_ARG(env, error);
1801
1802
11
  v8::Isolate* isolate = env->isolate;
1803
1804
11
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1805
  // any VM calls after this point and before returning
1806
  // to the javascript invoker will fail
1807
11
  return napi_clear_last_error(env);
1808
}
1809
1810
78
napi_status napi_throw_error(napi_env env,
1811
                             const char* code,
1812
                             const char* msg) {
1813


156
  NAPI_PREAMBLE(env);
1814
1815
75
  v8::Isolate* isolate = env->isolate;
1816
  v8::Local<v8::String> str;
1817

225
  CHECK_NEW_FROM_UTF8(env, str, msg);
1818
1819
75
  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1820
75
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1821
75
  if (status != napi_ok) return status;
1822
1823
75
  isolate->ThrowException(error_obj);
1824
  // any VM calls after this point and before returning
1825
  // to the javascript invoker will fail
1826
75
  return napi_clear_last_error(env);
1827
}
1828
1829
90
napi_status napi_throw_type_error(napi_env env,
1830
                                  const char* code,
1831
                                  const char* msg) {
1832


180
  NAPI_PREAMBLE(env);
1833
1834
90
  v8::Isolate* isolate = env->isolate;
1835
  v8::Local<v8::String> str;
1836

270
  CHECK_NEW_FROM_UTF8(env, str, msg);
1837
1838
90
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1839
90
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1840
90
  if (status != napi_ok) return status;
1841
1842
90
  isolate->ThrowException(error_obj);
1843
  // any VM calls after this point and before returning
1844
  // to the javascript invoker will fail
1845
90
  return napi_clear_last_error(env);
1846
}
1847
1848
23
napi_status napi_throw_range_error(napi_env env,
1849
                                   const char* code,
1850
                                   const char* msg) {
1851


46
  NAPI_PREAMBLE(env);
1852
1853
23
  v8::Isolate* isolate = env->isolate;
1854
  v8::Local<v8::String> str;
1855

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

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


28
  NAPI_PREAMBLE(env);
2181
14
  CHECK_ARG(env, value);
2182
14
  CHECK_ARG(env, result);
2183
2184
14
  v8::Isolate* isolate = env->isolate;
2185
  v8::Local<v8::Boolean> b =
2186
28
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2187
28
  *result = v8impl::JsValueFromV8LocalValue(b);
2188
14
  return GET_RETURN_STATUS(env);
2189
}
2190
2191
#define GEN_COERCE_FUNCTION(UpperCaseName, MixedCaseName, LowerCaseName)      \
2192
  napi_status napi_coerce_to_##LowerCaseName(napi_env env,                    \
2193
                                             napi_value value,                \
2194
                                             napi_value* result) {            \
2195
    NAPI_PREAMBLE(env);                                                       \
2196
    CHECK_ARG(env, value);                                                    \
2197
    CHECK_ARG(env, result);                                                   \
2198
                                                                              \
2199
    v8::Local<v8::Context> context = env->context();                          \
2200
    v8::Local<v8::MixedCaseName> str;                                         \
2201
                                                                              \
2202
    CHECK_TO_##UpperCaseName(env, context, str, value);                       \
2203
                                                                              \
2204
    *result = v8impl::JsValueFromV8LocalValue(str);                           \
2205
    return GET_RETURN_STATUS(env);                                            \
2206
  }
2207
2208




103
GEN_COERCE_FUNCTION(NUMBER, Number, number)
2209




105
GEN_COERCE_FUNCTION(OBJECT, Object, object)
2210




96
GEN_COERCE_FUNCTION(STRING, String, string)
2211
2212
#undef GEN_COERCE_FUNCTION
2213
2214
1019
napi_status napi_wrap(napi_env env,
2215
                      napi_value js_object,
2216
                      void* native_object,
2217
                      napi_finalize finalize_cb,
2218
                      void* finalize_hint,
2219
                      napi_ref* result) {
2220
  return v8impl::Wrap<v8impl::retrievable>(env,
2221
                                           js_object,
2222
                                           native_object,
2223
                                           finalize_cb,
2224
                                           finalize_hint,
2225
1019
                                           result);
2226
}
2227
2228
26
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2229
26
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2230
}
2231
2232
3
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2233
3
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2234
}
2235
2236
6
napi_status napi_create_external(napi_env env,
2237
                                 void* data,
2238
                                 napi_finalize finalize_cb,
2239
                                 void* finalize_hint,
2240
                                 napi_value* result) {
2241


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

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


14
  NAPI_PREAMBLE(env);
2463
7
  CHECK_ARG(env, constructor);
2464
7
  if (argc > 0) {
2465
7
    CHECK_ARG(env, argv);
2466
  }
2467
7
  CHECK_ARG(env, result);
2468
2469
7
  v8::Local<v8::Context> context = env->context();
2470
2471
  v8::Local<v8::Function> ctor;
2472

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


4556
  NAPI_PREAMBLE(env);
2488
2278
  CHECK_ARG(env, object);
2489
2278
  CHECK_ARG(env, result);
2490
2491
2278
  *result = false;
2492
2493
  v8::Local<v8::Object> ctor;
2494
2278
  v8::Local<v8::Context> context = env->context();
2495
2496

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


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


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


66
  NAPI_PREAMBLE(env);
2647
33
  CHECK_ARG(env, arraybuffer);
2648
33
  CHECK_ARG(env, result);
2649
2650
33
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2651
33
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2652
2653
33
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2654
  v8::Local<v8::TypedArray> typedArray;
2655
2656



33
  switch (type) {
2657
    case napi_int8_array:
2658
8
      CREATE_TYPED_ARRAY(
2659
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2660
2
      break;
2661
    case napi_uint8_array:
2662
8
      CREATE_TYPED_ARRAY(
2663
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2664
2
      break;
2665
    case napi_uint8_clamped_array:
2666
5
      CREATE_TYPED_ARRAY(
2667
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2668
1
      break;
2669
    case napi_int16_array:
2670

6
      CREATE_TYPED_ARRAY(
2671
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2672
1
      break;
2673
    case napi_uint16_array:
2674

6
      CREATE_TYPED_ARRAY(
2675
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2676
1
      break;
2677
    case napi_int32_array:
2678

6
      CREATE_TYPED_ARRAY(
2679
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2680
1
      break;
2681
    case napi_uint32_array:
2682

6
      CREATE_TYPED_ARRAY(
2683
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2684
1
      break;
2685
    case napi_float32_array:
2686

6
      CREATE_TYPED_ARRAY(
2687
          env, Float32Array, 4, buffer, byte_offset, length, typedArray);
2688
1
      break;
2689
    case napi_float64_array:
2690

9
      CREATE_TYPED_ARRAY(
2691
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2692
2
      break;
2693
    case napi_bigint64_array:
2694

6
      CREATE_TYPED_ARRAY(
2695
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2696
1
      break;
2697
    case napi_biguint64_array:
2698

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


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


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


2
  NAPI_PREAMBLE(env);
2899
1
  CHECK_ARG(env, result);
2900
2901
1
  v8::MaybeLocal<v8::Value> maybe_date = v8::Date::New(env->context(), time);
2902
1
  CHECK_MAYBE_EMPTY(env, maybe_date, napi_generic_failure);
2903
2904
2
  *result = v8impl::JsValueFromV8LocalValue(maybe_date.ToLocalChecked());
2905
2906
1
  return GET_RETURN_STATUS(env);
2907
}
2908
2909
7
napi_status napi_is_date(napi_env env,
2910
                         napi_value value,
2911
                         bool* is_date) {
2912
7
  CHECK_ENV(env);
2913
7
  CHECK_ARG(env, value);
2914
7
  CHECK_ARG(env, is_date);
2915
2916
14
  *is_date = v8impl::V8LocalValueFromJsValue(value)->IsDate();
2917
2918
7
  return napi_clear_last_error(env);
2919
}
2920
2921
1
napi_status napi_get_date_value(napi_env env,
2922
                                napi_value value,
2923
                                double* result) {
2924


2
  NAPI_PREAMBLE(env);
2925
1
  CHECK_ARG(env, value);
2926
1
  CHECK_ARG(env, result);
2927
2928
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2929
1
  RETURN_STATUS_IF_FALSE(env, val->IsDate(), napi_date_expected);
2930
2931
1
  v8::Local<v8::Date> date = val.As<v8::Date>();
2932
2
  *result = date->ValueOf();
2933
2934
1
  return GET_RETURN_STATUS(env);
2935
}
2936
2937
2
napi_status napi_run_script(napi_env env,
2938
                            napi_value script,
2939
                            napi_value* result) {
2940


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