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: 66 1396 4.7 %
Date: 2021-02-19 04:08:54 Branches: 33 1682 2.0 %

Line Branch Exec Source
1
#include <climits>  // INT_MAX
2
#include <cmath>
3
#include <algorithm>
4
#define NAPI_EXPERIMENTAL
5
#include "env-inl.h"
6
#include "js_native_api_v8.h"
7
#include "js_native_api.h"
8
#include "util-inl.h"
9
10
#define CHECK_MAYBE_NOTHING(env, maybe, status) \
11
  RETURN_STATUS_IF_FALSE((env), !((maybe).IsNothing()), (status))
12
13
#define CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe, status) \
14
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsNothing()), (status))
15
16
#define CHECK_TO_NUMBER(env, context, result, src) \
17
  CHECK_TO_TYPE((env), Number, (context), (result), (src), napi_number_expected)
18
19
// n-api defines NAPI_AUTO_LENGHTH as the indicator that a string
20
// is null terminated. For V8 the equivalent is -1. The assert
21
// validates that our cast of NAPI_AUTO_LENGTH results in -1 as
22
// needed by V8.
23
#define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len)                   \
24
  do {                                                                   \
25
    static_assert(static_cast<int>(NAPI_AUTO_LENGTH) == -1,              \
26
                  "Casting NAPI_AUTO_LENGTH to int must result in -1");  \
27
    RETURN_STATUS_IF_FALSE((env),                                        \
28
        (len == NAPI_AUTO_LENGTH) || len <= INT_MAX,                     \
29
        napi_invalid_arg);                                               \
30
    RETURN_STATUS_IF_FALSE((env),                                        \
31
        (str) != nullptr,                                                \
32
        napi_invalid_arg);                                               \
33
    auto str_maybe = v8::String::NewFromUtf8(                            \
34
        (env)->isolate, (str), v8::NewStringType::kInternalized,         \
35
        static_cast<int>(len));                                          \
36
    CHECK_MAYBE_EMPTY((env), str_maybe, napi_generic_failure);           \
37
    (result) = str_maybe.ToLocalChecked();                               \
38
  } while (0)
39
40
#define CHECK_NEW_FROM_UTF8(env, result, str) \
41
  CHECK_NEW_FROM_UTF8_LEN((env), (result), (str), NAPI_AUTO_LENGTH)
42
43
#define CREATE_TYPED_ARRAY(                                                    \
44
    env, type, size_of_element, buffer, byte_offset, length, out)              \
45
  do {                                                                         \
46
    if ((size_of_element) > 1) {                                               \
47
      THROW_RANGE_ERROR_IF_FALSE(                                              \
48
          (env), (byte_offset) % (size_of_element) == 0,                       \
49
          "ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT",                             \
50
          "start offset of "#type" should be a multiple of "#size_of_element); \
51
    }                                                                          \
52
    THROW_RANGE_ERROR_IF_FALSE((env), (length) * (size_of_element) +           \
53
        (byte_offset) <= buffer->ByteLength(),                                 \
54
        "ERR_NAPI_INVALID_TYPEDARRAY_LENGTH",                                  \
55
        "Invalid typed array length");                                         \
56
    (out) = v8::type::New((buffer), (byte_offset), (length));                  \
57
  } while (0)
58
59
namespace v8impl {
60
61
namespace {
62
63
inline static napi_status
64
V8NameFromPropertyDescriptor(napi_env env,
65
                             const napi_property_descriptor* p,
66
                             v8::Local<v8::Name>* result) {
67
  if (p->utf8name != nullptr) {
68
    CHECK_NEW_FROM_UTF8(env, *result, p->utf8name);
69
  } else {
70
    v8::Local<v8::Value> property_value =
71
      v8impl::V8LocalValueFromJsValue(p->name);
72
73
    RETURN_STATUS_IF_FALSE(env, property_value->IsName(), napi_name_expected);
74
    *result = property_value.As<v8::Name>();
75
  }
76
77
  return napi_ok;
78
}
79
80
// convert from n-api property attributes to v8::PropertyAttribute
81
inline static v8::PropertyAttribute V8PropertyAttributesFromDescriptor(
82
    const napi_property_descriptor* descriptor) {
83
  unsigned int attribute_flags = v8::PropertyAttribute::None;
84
85
  // The napi_writable attribute is ignored for accessor descriptors, but
86
  // V8 would throw `TypeError`s on assignment with nonexistence of a setter.
87
  if ((descriptor->getter == nullptr && descriptor->setter == nullptr) &&
88
    (descriptor->attributes & napi_writable) == 0) {
89
    attribute_flags |= v8::PropertyAttribute::ReadOnly;
90
  }
91
92
  if ((descriptor->attributes & napi_enumerable) == 0) {
93
    attribute_flags |= v8::PropertyAttribute::DontEnum;
94
  }
95
  if ((descriptor->attributes & napi_configurable) == 0) {
96
    attribute_flags |= v8::PropertyAttribute::DontDelete;
97
  }
98
99
  return static_cast<v8::PropertyAttribute>(attribute_flags);
100
}
101
102
inline static napi_deferred
103
JsDeferredFromNodePersistent(v8impl::Persistent<v8::Value>* local) {
104
  return reinterpret_cast<napi_deferred>(local);
105
}
106
107
inline static v8impl::Persistent<v8::Value>*
108
NodePersistentFromJsDeferred(napi_deferred local) {
109
  return reinterpret_cast<v8impl::Persistent<v8::Value>*>(local);
110
}
111
112
class HandleScopeWrapper {
113
 public:
114
  explicit HandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {}
115
116
 private:
117
  v8::HandleScope scope;
118
};
119
120
// In node v0.10 version of v8, there is no EscapableHandleScope and the
121
// node v0.10 port use HandleScope::Close(Local<T> v) to mimic the behavior
122
// of a EscapableHandleScope::Escape(Local<T> v), but it is not the same
123
// semantics. This is an example of where the api abstraction fail to work
124
// across different versions.
125
class EscapableHandleScopeWrapper {
126
 public:
127
  explicit EscapableHandleScopeWrapper(v8::Isolate* isolate)
128
      : scope(isolate), escape_called_(false) {}
129
  bool escape_called() const {
130
    return escape_called_;
131
  }
132
  template <typename T>
133
  v8::Local<T> Escape(v8::Local<T> handle) {
134
    escape_called_ = true;
135
    return scope.Escape(handle);
136
  }
137
138
 private:
139
  v8::EscapableHandleScope scope;
140
  bool escape_called_;
141
};
142
143
inline static napi_handle_scope
144
JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s) {
145
  return reinterpret_cast<napi_handle_scope>(s);
146
}
147
148
inline static HandleScopeWrapper*
149
V8HandleScopeFromJsHandleScope(napi_handle_scope s) {
150
  return reinterpret_cast<HandleScopeWrapper*>(s);
151
}
152
153
inline static napi_escapable_handle_scope
154
JsEscapableHandleScopeFromV8EscapableHandleScope(
155
    EscapableHandleScopeWrapper* s) {
156
  return reinterpret_cast<napi_escapable_handle_scope>(s);
157
}
158
159
inline static EscapableHandleScopeWrapper*
160
V8EscapableHandleScopeFromJsEscapableHandleScope(
161
    napi_escapable_handle_scope s) {
162
  return reinterpret_cast<EscapableHandleScopeWrapper*>(s);
163
}
164
165
inline static napi_status ConcludeDeferred(napi_env env,
166
                                           napi_deferred deferred,
167
                                           napi_value result,
168
                                           bool is_resolved) {
169
  NAPI_PREAMBLE(env);
170
  CHECK_ARG(env, result);
171
172
  v8::Local<v8::Context> context = env->context();
173
  v8impl::Persistent<v8::Value>* deferred_ref =
174
      NodePersistentFromJsDeferred(deferred);
175
  v8::Local<v8::Value> v8_deferred =
176
      v8::Local<v8::Value>::New(env->isolate, *deferred_ref);
177
178
  auto v8_resolver = v8::Local<v8::Promise::Resolver>::Cast(v8_deferred);
179
180
  v8::Maybe<bool> success = is_resolved ?
181
      v8_resolver->Resolve(context, v8impl::V8LocalValueFromJsValue(result)) :
182
      v8_resolver->Reject(context, v8impl::V8LocalValueFromJsValue(result));
183
184
  delete deferred_ref;
185
186
  RETURN_STATUS_IF_FALSE(env, success.FromMaybe(false), napi_generic_failure);
187
188
  return GET_RETURN_STATUS(env);
189
}
190
191
// Wrapper around v8impl::Persistent that implements reference counting.
192
class RefBase : protected Finalizer, RefTracker {
193
 protected:
194
2
  RefBase(napi_env env,
195
          uint32_t initial_refcount,
196
          bool delete_self,
197
          napi_finalize finalize_callback,
198
          void* finalize_data,
199
          void* finalize_hint)
200
2
       : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
201
        _refcount(initial_refcount),
202
2
        _delete_self(delete_self) {
203
2
    Link(finalize_callback == nullptr
204
        ? &env->reflist
205
2
        : &env->finalizing_reflist);
206
2
  }
207
208
 public:
209
1
  static RefBase* New(napi_env env,
210
                      uint32_t initial_refcount,
211
                      bool delete_self,
212
                      napi_finalize finalize_callback,
213
                      void* finalize_data,
214
                      void* finalize_hint) {
215
    return new RefBase(env,
216
                       initial_refcount,
217
                       delete_self,
218
                       finalize_callback,
219
                       finalize_data,
220
1
                       finalize_hint);
221
  }
222
223
3
  virtual ~RefBase() { Unlink(); }
224
225
  inline void* Data() {
226
    return _finalize_data;
227
  }
228
229
  // Delete is called in 2 ways. Either from the finalizer or
230
  // from one of Unwrap or napi_delete_reference.
231
  //
232
  // When it is called from Unwrap or napi_delete_reference we only
233
  // want to do the delete if the finalizer has already run or
234
  // cannot have been queued to run (ie the reference count is > 0),
235
  // otherwise we may crash when the finalizer does run.
236
  // If the finalizer may have been queued and has not already run
237
  // delay the delete until the finalizer runs by not doing the delete
238
  // and setting _delete_self to true so that the finalizer will
239
  // delete it when it runs.
240
  //
241
  // The second way this is called is from
242
  // the finalizer and _delete_self is set. In this case we
243
  // know we need to do the deletion so just do it.
244
2
  static inline void Delete(RefBase* reference) {
245

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

2
        (reference->_delete_self) ||
247
        (reference->_finalize_ran)) {
248
2
      delete reference;
249
    } else {
250
      // defer until finalizer runs as
251
      // it may alread be queued
252
      reference->_delete_self = true;
253
    }
254
2
  }
255
256
  inline uint32_t Ref() {
257
    return ++_refcount;
258
  }
259
260
  inline uint32_t Unref() {
261
    if (_refcount == 0) {
262
        return 0;
263
    }
264
    return --_refcount;
265
  }
266
267
3
  inline uint32_t RefCount() {
268
3
    return _refcount;
269
  }
270
271
 protected:
272
2
  inline void Finalize(bool is_env_teardown = false) override {
273
2
    if (_finalize_callback != nullptr) {
274
1
      _env->CallFinalizer(_finalize_callback, _finalize_data, _finalize_hint);
275
    }
276
277
    // this is safe because if a request to delete the reference
278
    // is made in the finalize_callback it will defer deletion
279
    // to this block and set _delete_self to true
280

2
    if (_delete_self || is_env_teardown) {
281
2
      Delete(this);
282
    } else {
283
      _finalize_ran = true;
284
    }
285
2
  }
286
287
 private:
288
  uint32_t _refcount;
289
  bool _delete_self;
290
};
291
292
3
class Reference : public RefBase {
293
 protected:
294
  template <typename... Args>
295
1
  Reference(napi_env env,
296
            v8::Local<v8::Value> value,
297
            Args&&... args)
298
5
      : RefBase(env, std::forward<Args>(args)...),
299
5
            _persistent(env->isolate, value) {
300
1
    if (RefCount() == 0) {
301
1
      _persistent.SetWeak(
302
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
303
    }
304
1
  }
305
306
 public:
307
1
  static inline Reference* New(napi_env env,
308
                             v8::Local<v8::Value> value,
309
                             uint32_t initial_refcount,
310
                             bool delete_self,
311
                             napi_finalize finalize_callback = nullptr,
312
                             void* finalize_data = nullptr,
313
                             void* finalize_hint = nullptr) {
314
    return new Reference(env,
315
                         value,
316
                         initial_refcount,
317
                         delete_self,
318
                         finalize_callback,
319
                         finalize_data,
320
1
                         finalize_hint);
321
  }
322
323
  inline uint32_t Ref() {
324
    uint32_t refcount = RefBase::Ref();
325
    if (refcount == 1) {
326
      _persistent.ClearWeak();
327
    }
328
    return refcount;
329
  }
330
331
  inline uint32_t Unref() {
332
    uint32_t old_refcount = RefCount();
333
    uint32_t refcount = RefBase::Unref();
334
    if (old_refcount == 1 && refcount == 0) {
335
      _persistent.SetWeak(
336
          this, FinalizeCallback, v8::WeakCallbackType::kParameter);
337
    }
338
    return refcount;
339
  }
340
341
  inline v8::Local<v8::Value> Get() {
342
    if (_persistent.IsEmpty()) {
343
      return v8::Local<v8::Value>();
344
    } else {
345
      return v8::Local<v8::Value>::New(_env->isolate, _persistent);
346
    }
347
  }
348
349
 private:
350
  // The N-API finalizer callback may make calls into the engine. V8's heap is
351
  // not in a consistent state during the weak callback, and therefore it does
352
  // not support calls back into it. However, it provides a mechanism for adding
353
  // a finalizer which may make calls back into the engine by allowing us to
354
  // attach such a second-pass finalizer from the first pass finalizer. Thus,
355
  // we do that here to ensure that the N-API finalizer callback is free to call
356
  // into the engine.
357
  static void FinalizeCallback(const v8::WeakCallbackInfo<Reference>& data) {
358
    Reference* reference = data.GetParameter();
359
360
    // The reference must be reset during the first pass.
361
    reference->_persistent.Reset();
362
363
    data.SetSecondPassCallback(SecondPassCallback);
364
  }
365
366
  static void SecondPassCallback(const v8::WeakCallbackInfo<Reference>& data) {
367
    data.GetParameter()->Finalize();
368
  }
369
370
  v8impl::Persistent<v8::Value> _persistent;
371
};
372
373
enum UnwrapAction {
374
  KeepWrap,
375
  RemoveWrap
376
};
377
378
inline static napi_status Unwrap(napi_env env,
379
                                 napi_value js_object,
380
                                 void** result,
381
                                 UnwrapAction action) {
382
  NAPI_PREAMBLE(env);
383
  CHECK_ARG(env, js_object);
384
  if (action == KeepWrap) {
385
    CHECK_ARG(env, result);
386
  }
387
388
  v8::Local<v8::Context> context = env->context();
389
390
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
391
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
392
  v8::Local<v8::Object> obj = value.As<v8::Object>();
393
394
  auto val = obj->GetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
395
      .ToLocalChecked();
396
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
397
  Reference* reference =
398
      static_cast<v8impl::Reference*>(val.As<v8::External>()->Value());
399
400
  if (result) {
401
    *result = reference->Data();
402
  }
403
404
  if (action == RemoveWrap) {
405
    CHECK(obj->DeletePrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
406
        .FromJust());
407
    Reference::Delete(reference);
408
  }
409
410
  return GET_RETURN_STATUS(env);
411
}
412
413
//=== Function napi_callback wrapper =================================
414
415
// Use this data structure to associate callback data with each N-API function
416
// exposed to JavaScript. The structure is stored in a v8::External which gets
417
// passed into our callback wrapper. This reduces the performance impact of
418
// calling through N-API.
419
// Ref: benchmark/misc/function_call
420
// Discussion (incl. perf. data): https://github.com/nodejs/node/pull/21072
421
class CallbackBundle {
422
 public:
423
  // Creates an object to be made available to the static function callback
424
  // wrapper, used to retrieve the native callback function and data pointer.
425
  static inline v8::Local<v8::Value>
426
  New(napi_env env, napi_callback cb, void* data) {
427
    CallbackBundle* bundle = new CallbackBundle();
428
    bundle->cb = cb;
429
    bundle->cb_data = data;
430
    bundle->env = env;
431
432
    v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
433
    Reference::New(env, cbdata, 0, true, Delete, bundle, nullptr);
434
    return cbdata;
435
  }
436
  napi_env       env;      // Necessary to invoke C++ NAPI callback
437
  void*          cb_data;  // The user provided callback data
438
  napi_callback  cb;
439
 private:
440
  static void Delete(napi_env env, void* data, void* hint) {
441
    CallbackBundle* bundle = static_cast<CallbackBundle*>(data);
442
    delete bundle;
443
  }
444
};
445
446
// Base class extended by classes that wrap V8 function and property callback
447
// info.
448
class CallbackWrapper {
449
 public:
450
  inline CallbackWrapper(napi_value this_arg, size_t args_length, void* data)
451
      : _this(this_arg), _args_length(args_length), _data(data) {}
452
453
  virtual napi_value GetNewTarget() = 0;
454
  virtual void Args(napi_value* buffer, size_t bufferlength) = 0;
455
  virtual void SetReturnValue(napi_value value) = 0;
456
457
  napi_value This() { return _this; }
458
459
  size_t ArgsLength() { return _args_length; }
460
461
  void* Data() { return _data; }
462
463
 protected:
464
  const napi_value _this;
465
  const size_t _args_length;
466
  void* _data;
467
};
468
469
class CallbackWrapperBase : public CallbackWrapper {
470
 public:
471
  inline CallbackWrapperBase(const v8::FunctionCallbackInfo<v8::Value>& cbinfo,
472
                             const size_t args_length)
473
      : CallbackWrapper(JsValueFromV8LocalValue(cbinfo.This()),
474
                        args_length,
475
                        nullptr),
476
        _cbinfo(cbinfo) {
477
    _bundle = reinterpret_cast<CallbackBundle*>(
478
        v8::Local<v8::External>::Cast(cbinfo.Data())->Value());
479
    _data = _bundle->cb_data;
480
  }
481
482
 protected:
483
  inline void InvokeCallback() {
484
    napi_callback_info cbinfo_wrapper = reinterpret_cast<napi_callback_info>(
485
        static_cast<CallbackWrapper*>(this));
486
487
    // All other pointers we need are stored in `_bundle`
488
    napi_env env = _bundle->env;
489
    napi_callback cb = _bundle->cb;
490
491
    napi_value result;
492
    env->CallIntoModule([&](napi_env env) {
493
      result = cb(env, cbinfo_wrapper);
494
    });
495
496
    if (result != nullptr) {
497
      this->SetReturnValue(result);
498
    }
499
  }
500
501
  const v8::FunctionCallbackInfo<v8::Value>& _cbinfo;
502
  CallbackBundle* _bundle;
503
};
504
505
class FunctionCallbackWrapper
506
    : public CallbackWrapperBase {
507
 public:
508
  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
509
    FunctionCallbackWrapper cbwrapper(info);
510
    cbwrapper.InvokeCallback();
511
  }
512
513
  static inline napi_status NewFunction(napi_env env,
514
                                        napi_callback cb,
515
                                        void* cb_data,
516
                                        v8::Local<v8::Function>* result) {
517
    v8::Local<v8::Value> cbdata = v8impl::CallbackBundle::New(env, cb, cb_data);
518
    RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
519
520
    v8::MaybeLocal<v8::Function> maybe_function =
521
        v8::Function::New(env->context(), Invoke, cbdata);
522
    CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
523
524
    *result = maybe_function.ToLocalChecked();
525
    return napi_clear_last_error(env);
526
  }
527
528
  static inline napi_status NewTemplate(napi_env env,
529
                    napi_callback cb,
530
                    void* cb_data,
531
                    v8::Local<v8::FunctionTemplate>* result,
532
                    v8::Local<v8::Signature> sig = v8::Local<v8::Signature>()) {
533
    v8::Local<v8::Value> cbdata = v8impl::CallbackBundle::New(env, cb, cb_data);
534
    RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
535
536
    *result = v8::FunctionTemplate::New(env->isolate, Invoke, cbdata, sig);
537
    return napi_clear_last_error(env);
538
  }
539
540
  explicit FunctionCallbackWrapper(
541
      const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
542
      : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
543
544
  napi_value GetNewTarget() override {
545
    if (_cbinfo.IsConstructCall()) {
546
      return v8impl::JsValueFromV8LocalValue(_cbinfo.NewTarget());
547
    } else {
548
      return nullptr;
549
    }
550
  }
551
552
  /*virtual*/
553
  void Args(napi_value* buffer, size_t buffer_length) override {
554
    size_t i = 0;
555
    size_t min = std::min(buffer_length, _args_length);
556
557
    for (; i < min; i += 1) {
558
      buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
559
    }
560
561
    if (i < buffer_length) {
562
      napi_value undefined =
563
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
564
      for (; i < buffer_length; i += 1) {
565
        buffer[i] = undefined;
566
      }
567
    }
568
  }
569
570
  /*virtual*/
571
  void SetReturnValue(napi_value value) override {
572
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
573
    _cbinfo.GetReturnValue().Set(val);
574
  }
575
};
576
577
enum WrapType {
578
  retrievable,
579
  anonymous
580
};
581
582
template <WrapType wrap_type>
583
inline napi_status Wrap(napi_env env,
584
                        napi_value js_object,
585
                        void* native_object,
586
                        napi_finalize finalize_cb,
587
                        void* finalize_hint,
588
                        napi_ref* result) {
589
  NAPI_PREAMBLE(env);
590
  CHECK_ARG(env, js_object);
591
592
  v8::Local<v8::Context> context = env->context();
593
594
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
595
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
596
  v8::Local<v8::Object> obj = value.As<v8::Object>();
597
598
  if (wrap_type == retrievable) {
599
    // If we've already wrapped this object, we error out.
600
    RETURN_STATUS_IF_FALSE(env,
601
        !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
602
            .FromJust(),
603
        napi_invalid_arg);
604
  } else if (wrap_type == anonymous) {
605
    // If no finalize callback is provided, we error out.
606
    CHECK_ARG(env, finalize_cb);
607
  }
608
609
  v8impl::Reference* reference = nullptr;
610
  if (result != nullptr) {
611
    // The returned reference should be deleted via napi_delete_reference()
612
    // ONLY in response to the finalize callback invocation. (If it is deleted
613
    // before then, then the finalize callback will never be invoked.)
614
    // Therefore a finalize callback is required when returning a reference.
615
    CHECK_ARG(env, finalize_cb);
616
    reference = v8impl::Reference::New(
617
        env, obj, 0, false, finalize_cb, native_object, finalize_hint);
618
    *result = reinterpret_cast<napi_ref>(reference);
619
  } else {
620
    // Create a self-deleting reference.
621
    reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb,
622
        native_object, finalize_cb == nullptr ? nullptr : finalize_hint);
623
  }
624
625
  if (wrap_type == retrievable) {
626
    CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper),
627
          v8::External::New(env->isolate, reference)).FromJust());
628
  }
629
630
  return GET_RETURN_STATUS(env);
631
}
632
633
}  // end of anonymous namespace
634
635
}  // end of namespace v8impl
636
637
// Warning: Keep in-sync with napi_status enum
638
static
639
const char* error_messages[] = {nullptr,
640
                                "Invalid argument",
641
                                "An object was expected",
642
                                "A string was expected",
643
                                "A string or symbol was expected",
644
                                "A function was expected",
645
                                "A number was expected",
646
                                "A boolean was expected",
647
                                "An array was expected",
648
                                "Unknown failure",
649
                                "An exception is pending",
650
                                "The async work item was cancelled",
651
                                "napi_escape_handle already called on scope",
652
                                "Invalid handle scope usage",
653
                                "Invalid callback scope usage",
654
                                "Thread-safe function queue is full",
655
                                "Thread-safe function handle is closing",
656
                                "A bigint was expected",
657
                                "A date was expected",
658
                                "An arraybuffer was expected",
659
                                "A detachable arraybuffer was expected",
660
                                "Main thread would deadlock",
661
};
662
663
napi_status napi_get_last_error_info(napi_env env,
664
                                     const napi_extended_error_info** result) {
665
  CHECK_ENV(env);
666
  CHECK_ARG(env, result);
667
668
  // The value of the constant below must be updated to reference the last
669
  // message in the `napi_status` enum each time a new error message is added.
670
  // We don't have a napi_status_last as this would result in an ABI
671
  // change each time a message was added.
672
  const int last_status = napi_would_deadlock;
673
674
  static_assert(
675
      NAPI_ARRAYSIZE(error_messages) == last_status + 1,
676
      "Count of error messages must match count of error values");
677
  CHECK_LE(env->last_error.error_code, last_status);
678
679
  // Wait until someone requests the last error information to fetch the error
680
  // message string
681
  env->last_error.error_message =
682
      error_messages[env->last_error.error_code];
683
684
  *result = &(env->last_error);
685
  return napi_ok;
686
}
687
688
napi_status napi_create_function(napi_env env,
689
                                 const char* utf8name,
690
                                 size_t length,
691
                                 napi_callback cb,
692
                                 void* callback_data,
693
                                 napi_value* result) {
694
  NAPI_PREAMBLE(env);
695
  CHECK_ARG(env, result);
696
  CHECK_ARG(env, cb);
697
698
  v8::Local<v8::Function> return_value;
699
  v8::EscapableHandleScope scope(env->isolate);
700
  v8::Local<v8::Function> fn;
701
  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
702
      env, cb, callback_data, &fn));
703
  return_value = scope.Escape(fn);
704
705
  if (utf8name != nullptr) {
706
    v8::Local<v8::String> name_string;
707
    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
708
    return_value->SetName(name_string);
709
  }
710
711
  *result = v8impl::JsValueFromV8LocalValue(return_value);
712
713
  return GET_RETURN_STATUS(env);
714
}
715
716
napi_status napi_define_class(napi_env env,
717
                              const char* utf8name,
718
                              size_t length,
719
                              napi_callback constructor,
720
                              void* callback_data,
721
                              size_t property_count,
722
                              const napi_property_descriptor* properties,
723
                              napi_value* result) {
724
  NAPI_PREAMBLE(env);
725
  CHECK_ARG(env, result);
726
  CHECK_ARG(env, constructor);
727
728
  if (property_count > 0) {
729
    CHECK_ARG(env, properties);
730
  }
731
732
  v8::Isolate* isolate = env->isolate;
733
734
  v8::EscapableHandleScope scope(isolate);
735
  v8::Local<v8::FunctionTemplate> tpl;
736
  STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
737
      env, constructor, callback_data, &tpl));
738
739
  v8::Local<v8::String> name_string;
740
  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
741
  tpl->SetClassName(name_string);
742
743
  size_t static_property_count = 0;
744
  for (size_t i = 0; i < property_count; i++) {
745
    const napi_property_descriptor* p = properties + i;
746
747
    if ((p->attributes & napi_static) != 0) {
748
      // Static properties are handled separately below.
749
      static_property_count++;
750
      continue;
751
    }
752
753
    v8::Local<v8::Name> property_name;
754
    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
755
756
    v8::PropertyAttribute attributes =
757
        v8impl::V8PropertyAttributesFromDescriptor(p);
758
759
    // This code is similar to that in napi_define_properties(); the
760
    // difference is it applies to a template instead of an object,
761
    // and preferred PropertyAttribute for lack of PropertyDescriptor
762
    // support on ObjectTemplate.
763
    if (p->getter != nullptr || p->setter != nullptr) {
764
      v8::Local<v8::FunctionTemplate> getter_tpl;
765
      v8::Local<v8::FunctionTemplate> setter_tpl;
766
      if (p->getter != nullptr) {
767
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
768
            env, p->getter, p->data, &getter_tpl));
769
      }
770
      if (p->setter != nullptr) {
771
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
772
            env, p->setter, p->data, &setter_tpl));
773
      }
774
775
      tpl->PrototypeTemplate()->SetAccessorProperty(
776
        property_name,
777
        getter_tpl,
778
        setter_tpl,
779
        attributes,
780
        v8::AccessControl::DEFAULT);
781
    } else if (p->method != nullptr) {
782
      v8::Local<v8::FunctionTemplate> t;
783
      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewTemplate(
784
          env, p->method, p->data, &t, v8::Signature::New(isolate, tpl)));
785
786
      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
787
    } else {
788
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
789
      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
790
    }
791
  }
792
793
  v8::Local<v8::Context> context = env->context();
794
  *result = v8impl::JsValueFromV8LocalValue(
795
      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
796
797
  if (static_property_count > 0) {
798
    std::vector<napi_property_descriptor> static_descriptors;
799
    static_descriptors.reserve(static_property_count);
800
801
    for (size_t i = 0; i < property_count; i++) {
802
      const napi_property_descriptor* p = properties + i;
803
      if ((p->attributes & napi_static) != 0) {
804
        static_descriptors.push_back(*p);
805
      }
806
    }
807
808
    STATUS_CALL(napi_define_properties(env,
809
                                       *result,
810
                                       static_descriptors.size(),
811
                                       static_descriptors.data()));
812
  }
813
814
  return GET_RETURN_STATUS(env);
815
}
816
817
napi_status napi_get_property_names(napi_env env,
818
                                    napi_value object,
819
                                    napi_value* result) {
820
  return napi_get_all_property_names(
821
      env,
822
      object,
823
      napi_key_include_prototypes,
824
      static_cast<napi_key_filter>(napi_key_enumerable |
825
                                   napi_key_skip_symbols),
826
      napi_key_numbers_to_strings,
827
      result);
828
}
829
830
napi_status napi_get_all_property_names(napi_env env,
831
                                        napi_value object,
832
                                        napi_key_collection_mode key_mode,
833
                                        napi_key_filter key_filter,
834
                                        napi_key_conversion key_conversion,
835
                                        napi_value* result) {
836
  NAPI_PREAMBLE(env);
837
  CHECK_ARG(env, result);
838
839
  v8::Local<v8::Context> context = env->context();
840
  v8::Local<v8::Object> obj;
841
  CHECK_TO_OBJECT(env, context, obj, object);
842
843
  v8::PropertyFilter filter = v8::PropertyFilter::ALL_PROPERTIES;
844
  if (key_filter & napi_key_writable) {
845
    filter =
846
        static_cast<v8::PropertyFilter>(filter |
847
                                        v8::PropertyFilter::ONLY_WRITABLE);
848
  }
849
  if (key_filter & napi_key_enumerable) {
850
    filter =
851
        static_cast<v8::PropertyFilter>(filter |
852
                                        v8::PropertyFilter::ONLY_ENUMERABLE);
853
  }
854
  if (key_filter & napi_key_configurable) {
855
    filter =
856
        static_cast<v8::PropertyFilter>(filter |
857
                                        v8::PropertyFilter::ONLY_WRITABLE);
858
  }
859
  if (key_filter & napi_key_skip_strings) {
860
    filter =
861
        static_cast<v8::PropertyFilter>(filter |
862
                                        v8::PropertyFilter::SKIP_STRINGS);
863
  }
864
  if (key_filter & napi_key_skip_symbols) {
865
    filter =
866
        static_cast<v8::PropertyFilter>(filter |
867
                                        v8::PropertyFilter::SKIP_SYMBOLS);
868
  }
869
  v8::KeyCollectionMode collection_mode;
870
  v8::KeyConversionMode conversion_mode;
871
872
  switch (key_mode) {
873
    case napi_key_include_prototypes:
874
      collection_mode = v8::KeyCollectionMode::kIncludePrototypes;
875
      break;
876
    case napi_key_own_only:
877
      collection_mode = v8::KeyCollectionMode::kOwnOnly;
878
      break;
879
    default:
880
      return napi_set_last_error(env, napi_invalid_arg);
881
  }
882
883
  switch (key_conversion) {
884
    case napi_key_keep_numbers:
885
      conversion_mode = v8::KeyConversionMode::kKeepNumbers;
886
      break;
887
    case napi_key_numbers_to_strings:
888
      conversion_mode = v8::KeyConversionMode::kConvertToString;
889
      break;
890
    default:
891
      return napi_set_last_error(env, napi_invalid_arg);
892
  }
893
894
  v8::MaybeLocal<v8::Array> maybe_all_propertynames =
895
      obj->GetPropertyNames(context,
896
                            collection_mode,
897
                            filter,
898
                            v8::IndexFilter::kIncludeIndices,
899
                            conversion_mode);
900
901
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(
902
      env, maybe_all_propertynames, napi_generic_failure);
903
904
  *result =
905
      v8impl::JsValueFromV8LocalValue(maybe_all_propertynames.ToLocalChecked());
906
  return GET_RETURN_STATUS(env);
907
}
908
909
2
napi_status napi_set_property(napi_env env,
910
                              napi_value object,
911
                              napi_value key,
912
                              napi_value value) {
913


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

8
  CHECK_TO_OBJECT(env, context, obj, object);
921
922
2
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
923
2
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
924
925
2
  v8::Maybe<bool> set_maybe = obj->Set(context, k, val);
926
927
4
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
928
2
  return GET_RETURN_STATUS(env);
929
}
930
931
napi_status napi_has_property(napi_env env,
932
                              napi_value object,
933
                              napi_value key,
934
                              bool* result) {
935
  NAPI_PREAMBLE(env);
936
  CHECK_ARG(env, result);
937
  CHECK_ARG(env, key);
938
939
  v8::Local<v8::Context> context = env->context();
940
  v8::Local<v8::Object> obj;
941
942
  CHECK_TO_OBJECT(env, context, obj, object);
943
944
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
945
  v8::Maybe<bool> has_maybe = obj->Has(context, k);
946
947
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
948
949
  *result = has_maybe.FromMaybe(false);
950
  return GET_RETURN_STATUS(env);
951
}
952
953
napi_status napi_get_property(napi_env env,
954
                              napi_value object,
955
                              napi_value key,
956
                              napi_value* result) {
957
  NAPI_PREAMBLE(env);
958
  CHECK_ARG(env, key);
959
  CHECK_ARG(env, result);
960
961
  v8::Local<v8::Context> context = env->context();
962
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
963
  v8::Local<v8::Object> obj;
964
965
  CHECK_TO_OBJECT(env, context, obj, object);
966
967
  auto get_maybe = obj->Get(context, k);
968
969
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
970
971
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
972
  *result = v8impl::JsValueFromV8LocalValue(val);
973
  return GET_RETURN_STATUS(env);
974
}
975
976
napi_status napi_delete_property(napi_env env,
977
                                 napi_value object,
978
                                 napi_value key,
979
                                 bool* result) {
980
  NAPI_PREAMBLE(env);
981
  CHECK_ARG(env, key);
982
983
  v8::Local<v8::Context> context = env->context();
984
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
985
  v8::Local<v8::Object> obj;
986
987
  CHECK_TO_OBJECT(env, context, obj, object);
988
  v8::Maybe<bool> delete_maybe = obj->Delete(context, k);
989
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
990
991
  if (result != nullptr)
992
    *result = delete_maybe.FromMaybe(false);
993
994
  return GET_RETURN_STATUS(env);
995
}
996
997
napi_status napi_has_own_property(napi_env env,
998
                                  napi_value object,
999
                                  napi_value key,
1000
                                  bool* result) {
1001
  NAPI_PREAMBLE(env);
1002
  CHECK_ARG(env, key);
1003
  CHECK_ARG(env, result);
1004
1005
  v8::Local<v8::Context> context = env->context();
1006
  v8::Local<v8::Object> obj;
1007
1008
  CHECK_TO_OBJECT(env, context, obj, object);
1009
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
1010
  RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected);
1011
  v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>());
1012
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1013
  *result = has_maybe.FromMaybe(false);
1014
1015
  return GET_RETURN_STATUS(env);
1016
}
1017
1018
napi_status napi_set_named_property(napi_env env,
1019
                                    napi_value object,
1020
                                    const char* utf8name,
1021
                                    napi_value value) {
1022
  NAPI_PREAMBLE(env);
1023
  CHECK_ARG(env, value);
1024
1025
  v8::Local<v8::Context> context = env->context();
1026
  v8::Local<v8::Object> obj;
1027
1028
  CHECK_TO_OBJECT(env, context, obj, object);
1029
1030
  v8::Local<v8::Name> key;
1031
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1032
1033
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1034
1035
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1036
1037
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1038
  return GET_RETURN_STATUS(env);
1039
}
1040
1041
napi_status napi_has_named_property(napi_env env,
1042
                                    napi_value object,
1043
                                    const char* utf8name,
1044
                                    bool* result) {
1045
  NAPI_PREAMBLE(env);
1046
  CHECK_ARG(env, result);
1047
1048
  v8::Local<v8::Context> context = env->context();
1049
  v8::Local<v8::Object> obj;
1050
1051
  CHECK_TO_OBJECT(env, context, obj, object);
1052
1053
  v8::Local<v8::Name> key;
1054
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1055
1056
  v8::Maybe<bool> has_maybe = obj->Has(context, key);
1057
1058
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1059
1060
  *result = has_maybe.FromMaybe(false);
1061
  return GET_RETURN_STATUS(env);
1062
}
1063
1064
napi_status napi_get_named_property(napi_env env,
1065
                                    napi_value object,
1066
                                    const char* utf8name,
1067
                                    napi_value* result) {
1068
  NAPI_PREAMBLE(env);
1069
  CHECK_ARG(env, result);
1070
1071
  v8::Local<v8::Context> context = env->context();
1072
1073
  v8::Local<v8::Name> key;
1074
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1075
1076
  v8::Local<v8::Object> obj;
1077
1078
  CHECK_TO_OBJECT(env, context, obj, object);
1079
1080
  auto get_maybe = obj->Get(context, key);
1081
1082
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1083
1084
  v8::Local<v8::Value> val = get_maybe.ToLocalChecked();
1085
  *result = v8impl::JsValueFromV8LocalValue(val);
1086
  return GET_RETURN_STATUS(env);
1087
}
1088
1089
napi_status napi_set_element(napi_env env,
1090
                             napi_value object,
1091
                             uint32_t index,
1092
                             napi_value value) {
1093
  NAPI_PREAMBLE(env);
1094
  CHECK_ARG(env, value);
1095
1096
  v8::Local<v8::Context> context = env->context();
1097
  v8::Local<v8::Object> obj;
1098
1099
  CHECK_TO_OBJECT(env, context, obj, object);
1100
1101
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1102
  auto set_maybe = obj->Set(context, index, val);
1103
1104
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1105
1106
  return GET_RETURN_STATUS(env);
1107
}
1108
1109
napi_status napi_has_element(napi_env env,
1110
                             napi_value object,
1111
                             uint32_t index,
1112
                             bool* result) {
1113
  NAPI_PREAMBLE(env);
1114
  CHECK_ARG(env, result);
1115
1116
  v8::Local<v8::Context> context = env->context();
1117
  v8::Local<v8::Object> obj;
1118
1119
  CHECK_TO_OBJECT(env, context, obj, object);
1120
1121
  v8::Maybe<bool> has_maybe = obj->Has(context, index);
1122
1123
  CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure);
1124
1125
  *result = has_maybe.FromMaybe(false);
1126
  return GET_RETURN_STATUS(env);
1127
}
1128
1129
napi_status napi_get_element(napi_env env,
1130
                             napi_value object,
1131
                             uint32_t index,
1132
                             napi_value* result) {
1133
  NAPI_PREAMBLE(env);
1134
  CHECK_ARG(env, result);
1135
1136
  v8::Local<v8::Context> context = env->context();
1137
  v8::Local<v8::Object> obj;
1138
1139
  CHECK_TO_OBJECT(env, context, obj, object);
1140
1141
  auto get_maybe = obj->Get(context, index);
1142
1143
  CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure);
1144
1145
  *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked());
1146
  return GET_RETURN_STATUS(env);
1147
}
1148
1149
napi_status napi_delete_element(napi_env env,
1150
                                napi_value object,
1151
                                uint32_t index,
1152
                                bool* result) {
1153
  NAPI_PREAMBLE(env);
1154
1155
  v8::Local<v8::Context> context = env->context();
1156
  v8::Local<v8::Object> obj;
1157
1158
  CHECK_TO_OBJECT(env, context, obj, object);
1159
  v8::Maybe<bool> delete_maybe = obj->Delete(context, index);
1160
  CHECK_MAYBE_NOTHING(env, delete_maybe, napi_generic_failure);
1161
1162
  if (result != nullptr)
1163
    *result = delete_maybe.FromMaybe(false);
1164
1165
  return GET_RETURN_STATUS(env);
1166
}
1167
1168
napi_status napi_define_properties(napi_env env,
1169
                                   napi_value object,
1170
                                   size_t property_count,
1171
                                   const napi_property_descriptor* properties) {
1172
  NAPI_PREAMBLE(env);
1173
  if (property_count > 0) {
1174
    CHECK_ARG(env, properties);
1175
  }
1176
1177
  v8::Local<v8::Context> context = env->context();
1178
1179
  v8::Local<v8::Object> obj;
1180
  CHECK_TO_OBJECT(env, context, obj, object);
1181
1182
  for (size_t i = 0; i < property_count; i++) {
1183
    const napi_property_descriptor* p = &properties[i];
1184
1185
    v8::Local<v8::Name> property_name;
1186
    STATUS_CALL(v8impl::V8NameFromPropertyDescriptor(env, p, &property_name));
1187
1188
    if (p->getter != nullptr || p->setter != nullptr) {
1189
      v8::Local<v8::Function> local_getter;
1190
      v8::Local<v8::Function> local_setter;
1191
1192
      if (p->getter != nullptr) {
1193
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1194
            env, p->getter, p->data, &local_getter));
1195
      }
1196
      if (p->setter != nullptr) {
1197
        STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1198
            env, p->setter, p->data, &local_setter));
1199
      }
1200
1201
      v8::PropertyDescriptor descriptor(local_getter, local_setter);
1202
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1203
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1204
1205
      auto define_maybe = obj->DefineProperty(context,
1206
                                              property_name,
1207
                                              descriptor);
1208
1209
      if (!define_maybe.FromMaybe(false)) {
1210
        return napi_set_last_error(env, napi_invalid_arg);
1211
      }
1212
    } else if (p->method != nullptr) {
1213
      v8::Local<v8::Function> method;
1214
      STATUS_CALL(v8impl::FunctionCallbackWrapper::NewFunction(
1215
          env, p->method, p->data, &method));
1216
      v8::PropertyDescriptor descriptor(method,
1217
                                        (p->attributes & napi_writable) != 0);
1218
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1219
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1220
1221
      auto define_maybe = obj->DefineProperty(context,
1222
                                              property_name,
1223
                                              descriptor);
1224
1225
      if (!define_maybe.FromMaybe(false)) {
1226
        return napi_set_last_error(env, napi_generic_failure);
1227
      }
1228
    } else {
1229
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1230
1231
      v8::PropertyDescriptor descriptor(value,
1232
                                        (p->attributes & napi_writable) != 0);
1233
      descriptor.set_enumerable((p->attributes & napi_enumerable) != 0);
1234
      descriptor.set_configurable((p->attributes & napi_configurable) != 0);
1235
1236
      auto define_maybe =
1237
          obj->DefineProperty(context, property_name, descriptor);
1238
1239
      if (!define_maybe.FromMaybe(false)) {
1240
        return napi_set_last_error(env, napi_invalid_arg);
1241
      }
1242
    }
1243
  }
1244
1245
  return GET_RETURN_STATUS(env);
1246
}
1247
1248
napi_status napi_object_freeze(napi_env env,
1249
                               napi_value object) {
1250
  NAPI_PREAMBLE(env);
1251
1252
  v8::Local<v8::Context> context = env->context();
1253
  v8::Local<v8::Object> obj;
1254
1255
  CHECK_TO_OBJECT(env, context, obj, object);
1256
1257
  v8::Maybe<bool> set_frozen =
1258
    obj->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen);
1259
1260
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
1261
    set_frozen.FromMaybe(false), napi_generic_failure);
1262
1263
  return GET_RETURN_STATUS(env);
1264
}
1265
1266
napi_status napi_object_seal(napi_env env,
1267
                             napi_value object) {
1268
  NAPI_PREAMBLE(env);
1269
1270
  v8::Local<v8::Context> context = env->context();
1271
  v8::Local<v8::Object> obj;
1272
1273
  CHECK_TO_OBJECT(env, context, obj, object);
1274
1275
  v8::Maybe<bool> set_sealed =
1276
    obj->SetIntegrityLevel(context, v8::IntegrityLevel::kSealed);
1277
1278
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
1279
    set_sealed.FromMaybe(false), napi_generic_failure);
1280
1281
  return GET_RETURN_STATUS(env);
1282
}
1283
1284
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1285
  CHECK_ENV(env);
1286
  CHECK_ARG(env, value);
1287
  CHECK_ARG(env, result);
1288
1289
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1290
1291
  *result = val->IsArray();
1292
  return napi_clear_last_error(env);
1293
}
1294
1295
napi_status napi_get_array_length(napi_env env,
1296
                                  napi_value value,
1297
                                  uint32_t* result) {
1298
  NAPI_PREAMBLE(env);
1299
  CHECK_ARG(env, value);
1300
  CHECK_ARG(env, result);
1301
1302
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1303
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1304
1305
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1306
  *result = arr->Length();
1307
1308
  return GET_RETURN_STATUS(env);
1309
}
1310
1311
napi_status napi_strict_equals(napi_env env,
1312
                               napi_value lhs,
1313
                               napi_value rhs,
1314
                               bool* result) {
1315
  NAPI_PREAMBLE(env);
1316
  CHECK_ARG(env, lhs);
1317
  CHECK_ARG(env, rhs);
1318
  CHECK_ARG(env, result);
1319
1320
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1321
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1322
1323
  *result = a->StrictEquals(b);
1324
  return GET_RETURN_STATUS(env);
1325
}
1326
1327
napi_status napi_get_prototype(napi_env env,
1328
                               napi_value object,
1329
                               napi_value* result) {
1330
  NAPI_PREAMBLE(env);
1331
  CHECK_ARG(env, result);
1332
1333
  v8::Local<v8::Context> context = env->context();
1334
1335
  v8::Local<v8::Object> obj;
1336
  CHECK_TO_OBJECT(env, context, obj, object);
1337
1338
  v8::Local<v8::Value> val = obj->GetPrototype();
1339
  *result = v8impl::JsValueFromV8LocalValue(val);
1340
  return GET_RETURN_STATUS(env);
1341
}
1342
1343
napi_status napi_create_object(napi_env env, napi_value* result) {
1344
  CHECK_ENV(env);
1345
  CHECK_ARG(env, result);
1346
1347
  *result = v8impl::JsValueFromV8LocalValue(
1348
      v8::Object::New(env->isolate));
1349
1350
  return napi_clear_last_error(env);
1351
}
1352
1353
napi_status napi_create_array(napi_env env, napi_value* result) {
1354
  CHECK_ENV(env);
1355
  CHECK_ARG(env, result);
1356
1357
  *result = v8impl::JsValueFromV8LocalValue(
1358
      v8::Array::New(env->isolate));
1359
1360
  return napi_clear_last_error(env);
1361
}
1362
1363
napi_status napi_create_array_with_length(napi_env env,
1364
                                          size_t length,
1365
                                          napi_value* result) {
1366
  CHECK_ENV(env);
1367
  CHECK_ARG(env, result);
1368
1369
  *result = v8impl::JsValueFromV8LocalValue(
1370
      v8::Array::New(env->isolate, length));
1371
1372
  return napi_clear_last_error(env);
1373
}
1374
1375
napi_status napi_create_string_latin1(napi_env env,
1376
                                      const char* str,
1377
                                      size_t length,
1378
                                      napi_value* result) {
1379
  CHECK_ENV(env);
1380
  CHECK_ARG(env, result);
1381
  RETURN_STATUS_IF_FALSE(env,
1382
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1383
      napi_invalid_arg);
1384
1385
  auto isolate = env->isolate;
1386
  auto str_maybe =
1387
      v8::String::NewFromOneByte(isolate,
1388
                                 reinterpret_cast<const uint8_t*>(str),
1389
                                 v8::NewStringType::kNormal,
1390
                                 length);
1391
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1392
1393
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1394
  return napi_clear_last_error(env);
1395
}
1396
1397
3
napi_status napi_create_string_utf8(napi_env env,
1398
                                    const char* str,
1399
                                    size_t length,
1400
                                    napi_value* result) {
1401
3
  CHECK_ENV(env);
1402
3
  CHECK_ARG(env, result);
1403

3
  RETURN_STATUS_IF_FALSE(env,
1404
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1405
      napi_invalid_arg);
1406
1407
3
  auto isolate = env->isolate;
1408
  auto str_maybe =
1409
      v8::String::NewFromUtf8(isolate,
1410
                              str,
1411
                              v8::NewStringType::kNormal,
1412
3
                              static_cast<int>(length));
1413
3
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1414
6
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1415
3
  return napi_clear_last_error(env);
1416
}
1417
1418
napi_status napi_create_string_utf16(napi_env env,
1419
                                     const char16_t* str,
1420
                                     size_t length,
1421
                                     napi_value* result) {
1422
  CHECK_ENV(env);
1423
  CHECK_ARG(env, result);
1424
  RETURN_STATUS_IF_FALSE(env,
1425
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1426
      napi_invalid_arg);
1427
1428
  auto isolate = env->isolate;
1429
  auto str_maybe =
1430
      v8::String::NewFromTwoByte(isolate,
1431
                                 reinterpret_cast<const uint16_t*>(str),
1432
                                 v8::NewStringType::kNormal,
1433
                                 length);
1434
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1435
1436
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1437
  return napi_clear_last_error(env);
1438
}
1439
1440
napi_status napi_create_double(napi_env env,
1441
                               double value,
1442
                               napi_value* result) {
1443
  CHECK_ENV(env);
1444
  CHECK_ARG(env, result);
1445
1446
  *result = v8impl::JsValueFromV8LocalValue(
1447
      v8::Number::New(env->isolate, value));
1448
1449
  return napi_clear_last_error(env);
1450
}
1451
1452
napi_status napi_create_int32(napi_env env,
1453
                              int32_t value,
1454
                              napi_value* result) {
1455
  CHECK_ENV(env);
1456
  CHECK_ARG(env, result);
1457
1458
  *result = v8impl::JsValueFromV8LocalValue(
1459
      v8::Integer::New(env->isolate, value));
1460
1461
  return napi_clear_last_error(env);
1462
}
1463
1464
napi_status napi_create_uint32(napi_env env,
1465
                               uint32_t value,
1466
                               napi_value* result) {
1467
  CHECK_ENV(env);
1468
  CHECK_ARG(env, result);
1469
1470
  *result = v8impl::JsValueFromV8LocalValue(
1471
      v8::Integer::NewFromUnsigned(env->isolate, value));
1472
1473
  return napi_clear_last_error(env);
1474
}
1475
1476
napi_status napi_create_int64(napi_env env,
1477
                              int64_t value,
1478
                              napi_value* result) {
1479
  CHECK_ENV(env);
1480
  CHECK_ARG(env, result);
1481
1482
  *result = v8impl::JsValueFromV8LocalValue(
1483
      v8::Number::New(env->isolate, static_cast<double>(value)));
1484
1485
  return napi_clear_last_error(env);
1486
}
1487
1488
napi_status napi_create_bigint_int64(napi_env env,
1489
                                     int64_t value,
1490
                                     napi_value* result) {
1491
  CHECK_ENV(env);
1492
  CHECK_ARG(env, result);
1493
1494
  *result = v8impl::JsValueFromV8LocalValue(
1495
      v8::BigInt::New(env->isolate, value));
1496
1497
  return napi_clear_last_error(env);
1498
}
1499
1500
napi_status napi_create_bigint_uint64(napi_env env,
1501
                                      uint64_t value,
1502
                                      napi_value* result) {
1503
  CHECK_ENV(env);
1504
  CHECK_ARG(env, result);
1505
1506
  *result = v8impl::JsValueFromV8LocalValue(
1507
      v8::BigInt::NewFromUnsigned(env->isolate, value));
1508
1509
  return napi_clear_last_error(env);
1510
}
1511
1512
napi_status napi_create_bigint_words(napi_env env,
1513
                                     int sign_bit,
1514
                                     size_t word_count,
1515
                                     const uint64_t* words,
1516
                                     napi_value* result) {
1517
  NAPI_PREAMBLE(env);
1518
  CHECK_ARG(env, words);
1519
  CHECK_ARG(env, result);
1520
1521
  v8::Local<v8::Context> context = env->context();
1522
1523
  RETURN_STATUS_IF_FALSE(
1524
      env, word_count <= INT_MAX, napi_invalid_arg);
1525
1526
  v8::MaybeLocal<v8::BigInt> b = v8::BigInt::NewFromWords(
1527
      context, sign_bit, word_count, words);
1528
1529
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, b, napi_generic_failure);
1530
1531
  *result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
1532
  return GET_RETURN_STATUS(env);
1533
}
1534
1535
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
1536
  CHECK_ENV(env);
1537
  CHECK_ARG(env, result);
1538
1539
  v8::Isolate* isolate = env->isolate;
1540
1541
  if (value) {
1542
    *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
1543
  } else {
1544
    *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
1545
  }
1546
1547
  return napi_clear_last_error(env);
1548
}
1549
1550
napi_status napi_create_symbol(napi_env env,
1551
                               napi_value description,
1552
                               napi_value* result) {
1553
  CHECK_ENV(env);
1554
  CHECK_ARG(env, result);
1555
1556
  v8::Isolate* isolate = env->isolate;
1557
1558
  if (description == nullptr) {
1559
    *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
1560
  } else {
1561
    v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
1562
    RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
1563
1564
    *result = v8impl::JsValueFromV8LocalValue(
1565
      v8::Symbol::New(isolate, desc.As<v8::String>()));
1566
  }
1567
1568
  return napi_clear_last_error(env);
1569
}
1570
1571
static inline napi_status set_error_code(napi_env env,
1572
                                         v8::Local<v8::Value> error,
1573
                                         napi_value code,
1574
                                         const char* code_cstring) {
1575
  if ((code != nullptr) || (code_cstring != nullptr)) {
1576
    v8::Local<v8::Context> context = env->context();
1577
    v8::Local<v8::Object> err_object = error.As<v8::Object>();
1578
1579
    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1580
    if (code != nullptr) {
1581
      code_value = v8impl::V8LocalValueFromJsValue(code);
1582
      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1583
    } else {
1584
      CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
1585
    }
1586
1587
    v8::Local<v8::Name> code_key;
1588
    CHECK_NEW_FROM_UTF8(env, code_key, "code");
1589
1590
    v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
1591
    RETURN_STATUS_IF_FALSE(env,
1592
                           set_maybe.FromMaybe(false),
1593
                           napi_generic_failure);
1594
  }
1595
  return napi_ok;
1596
}
1597
1598
napi_status napi_create_error(napi_env env,
1599
                              napi_value code,
1600
                              napi_value msg,
1601
                              napi_value* result) {
1602
  CHECK_ENV(env);
1603
  CHECK_ARG(env, msg);
1604
  CHECK_ARG(env, result);
1605
1606
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1607
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1608
1609
  v8::Local<v8::Value> error_obj =
1610
      v8::Exception::Error(message_value.As<v8::String>());
1611
  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
1612
1613
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1614
1615
  return napi_clear_last_error(env);
1616
}
1617
1618
napi_status napi_create_type_error(napi_env env,
1619
                                   napi_value code,
1620
                                   napi_value msg,
1621
                                   napi_value* result) {
1622
  CHECK_ENV(env);
1623
  CHECK_ARG(env, msg);
1624
  CHECK_ARG(env, result);
1625
1626
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1627
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1628
1629
  v8::Local<v8::Value> error_obj =
1630
      v8::Exception::TypeError(message_value.As<v8::String>());
1631
  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
1632
1633
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1634
1635
  return napi_clear_last_error(env);
1636
}
1637
1638
napi_status napi_create_range_error(napi_env env,
1639
                                    napi_value code,
1640
                                    napi_value msg,
1641
                                    napi_value* result) {
1642
  CHECK_ENV(env);
1643
  CHECK_ARG(env, msg);
1644
  CHECK_ARG(env, result);
1645
1646
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1647
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1648
1649
  v8::Local<v8::Value> error_obj =
1650
      v8::Exception::RangeError(message_value.As<v8::String>());
1651
  STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
1652
1653
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1654
1655
  return napi_clear_last_error(env);
1656
}
1657
1658
napi_status napi_typeof(napi_env env,
1659
                        napi_value value,
1660
                        napi_valuetype* result) {
1661
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1662
  // JS exceptions.
1663
  CHECK_ENV(env);
1664
  CHECK_ARG(env, value);
1665
  CHECK_ARG(env, result);
1666
1667
  v8::Local<v8::Value> v = v8impl::V8LocalValueFromJsValue(value);
1668
1669
  if (v->IsNumber()) {
1670
    *result = napi_number;
1671
  } else if (v->IsBigInt()) {
1672
    *result = napi_bigint;
1673
  } else if (v->IsString()) {
1674
    *result = napi_string;
1675
  } else if (v->IsFunction()) {
1676
    // This test has to come before IsObject because IsFunction
1677
    // implies IsObject
1678
    *result = napi_function;
1679
  } else if (v->IsExternal()) {
1680
    // This test has to come before IsObject because IsExternal
1681
    // implies IsObject
1682
    *result = napi_external;
1683
  } else if (v->IsObject()) {
1684
    *result = napi_object;
1685
  } else if (v->IsBoolean()) {
1686
    *result = napi_boolean;
1687
  } else if (v->IsUndefined()) {
1688
    *result = napi_undefined;
1689
  } else if (v->IsSymbol()) {
1690
    *result = napi_symbol;
1691
  } else if (v->IsNull()) {
1692
    *result = napi_null;
1693
  } else {
1694
    // Should not get here unless V8 has added some new kind of value.
1695
    return napi_set_last_error(env, napi_invalid_arg);
1696
  }
1697
1698
  return napi_clear_last_error(env);
1699
}
1700
1701
napi_status napi_get_undefined(napi_env env, napi_value* result) {
1702
  CHECK_ENV(env);
1703
  CHECK_ARG(env, result);
1704
1705
  *result = v8impl::JsValueFromV8LocalValue(
1706
      v8::Undefined(env->isolate));
1707
1708
  return napi_clear_last_error(env);
1709
}
1710
1711
napi_status napi_get_null(napi_env env, napi_value* result) {
1712
  CHECK_ENV(env);
1713
  CHECK_ARG(env, result);
1714
1715
  *result = v8impl::JsValueFromV8LocalValue(
1716
        v8::Null(env->isolate));
1717
1718
  return napi_clear_last_error(env);
1719
}
1720
1721
// Gets all callback info in a single call. (Ugly, but faster.)
1722
napi_status napi_get_cb_info(
1723
    napi_env env,               // [in] NAPI environment handle
1724
    napi_callback_info cbinfo,  // [in] Opaque callback-info handle
1725
    size_t* argc,      // [in-out] Specifies the size of the provided argv array
1726
                       // and receives the actual count of args.
1727
    napi_value* argv,  // [out] Array of values
1728
    napi_value* this_arg,  // [out] Receives the JS 'this' arg for the call
1729
    void** data) {         // [out] Receives the data pointer for the callback.
1730
  CHECK_ENV(env);
1731
  CHECK_ARG(env, cbinfo);
1732
1733
  v8impl::CallbackWrapper* info =
1734
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1735
1736
  if (argv != nullptr) {
1737
    CHECK_ARG(env, argc);
1738
    info->Args(argv, *argc);
1739
  }
1740
  if (argc != nullptr) {
1741
    *argc = info->ArgsLength();
1742
  }
1743
  if (this_arg != nullptr) {
1744
    *this_arg = info->This();
1745
  }
1746
  if (data != nullptr) {
1747
    *data = info->Data();
1748
  }
1749
1750
  return napi_clear_last_error(env);
1751
}
1752
1753
napi_status napi_get_new_target(napi_env env,
1754
                                napi_callback_info cbinfo,
1755
                                napi_value* result) {
1756
  CHECK_ENV(env);
1757
  CHECK_ARG(env, cbinfo);
1758
  CHECK_ARG(env, result);
1759
1760
  v8impl::CallbackWrapper* info =
1761
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1762
1763
  *result = info->GetNewTarget();
1764
  return napi_clear_last_error(env);
1765
}
1766
1767
napi_status napi_call_function(napi_env env,
1768
                               napi_value recv,
1769
                               napi_value func,
1770
                               size_t argc,
1771
                               const napi_value* argv,
1772
                               napi_value* result) {
1773
  NAPI_PREAMBLE(env);
1774
  CHECK_ARG(env, recv);
1775
  if (argc > 0) {
1776
    CHECK_ARG(env, argv);
1777
  }
1778
1779
  v8::Local<v8::Context> context = env->context();
1780
1781
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1782
1783
  v8::Local<v8::Function> v8func;
1784
  CHECK_TO_FUNCTION(env, v8func, func);
1785
1786
  auto maybe = v8func->Call(context, v8recv, argc,
1787
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1788
1789
  if (try_catch.HasCaught()) {
1790
    return napi_set_last_error(env, napi_pending_exception);
1791
  } else {
1792
    if (result != nullptr) {
1793
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1794
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1795
    }
1796
    return napi_clear_last_error(env);
1797
  }
1798
}
1799
1800
napi_status napi_get_global(napi_env env, napi_value* result) {
1801
  CHECK_ENV(env);
1802
  CHECK_ARG(env, result);
1803
1804
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1805
1806
  return napi_clear_last_error(env);
1807
}
1808
1809
napi_status napi_throw(napi_env env, napi_value error) {
1810
  NAPI_PREAMBLE(env);
1811
  CHECK_ARG(env, error);
1812
1813
  v8::Isolate* isolate = env->isolate;
1814
1815
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1816
  // any VM calls after this point and before returning
1817
  // to the javascript invoker will fail
1818
  return napi_clear_last_error(env);
1819
}
1820
1821
napi_status napi_throw_error(napi_env env,
1822
                             const char* code,
1823
                             const char* msg) {
1824
  NAPI_PREAMBLE(env);
1825
1826
  v8::Isolate* isolate = env->isolate;
1827
  v8::Local<v8::String> str;
1828
  CHECK_NEW_FROM_UTF8(env, str, msg);
1829
1830
  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1831
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1832
1833
  isolate->ThrowException(error_obj);
1834
  // any VM calls after this point and before returning
1835
  // to the javascript invoker will fail
1836
  return napi_clear_last_error(env);
1837
}
1838
1839
napi_status napi_throw_type_error(napi_env env,
1840
                                  const char* code,
1841
                                  const char* msg) {
1842
  NAPI_PREAMBLE(env);
1843
1844
  v8::Isolate* isolate = env->isolate;
1845
  v8::Local<v8::String> str;
1846
  CHECK_NEW_FROM_UTF8(env, str, msg);
1847
1848
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1849
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1850
1851
  isolate->ThrowException(error_obj);
1852
  // any VM calls after this point and before returning
1853
  // to the javascript invoker will fail
1854
  return napi_clear_last_error(env);
1855
}
1856
1857
napi_status napi_throw_range_error(napi_env env,
1858
                                   const char* code,
1859
                                   const char* msg) {
1860
  NAPI_PREAMBLE(env);
1861
1862
  v8::Isolate* isolate = env->isolate;
1863
  v8::Local<v8::String> str;
1864
  CHECK_NEW_FROM_UTF8(env, str, msg);
1865
1866
  v8::Local<v8::Value> error_obj = v8::Exception::RangeError(str);
1867
  STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1868
1869
  isolate->ThrowException(error_obj);
1870
  // any VM calls after this point and before returning
1871
  // to the javascript invoker will fail
1872
  return napi_clear_last_error(env);
1873
}
1874
1875
napi_status napi_is_error(napi_env env, napi_value value, bool* result) {
1876
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot
1877
  // throw JS exceptions.
1878
  CHECK_ENV(env);
1879
  CHECK_ARG(env, value);
1880
  CHECK_ARG(env, result);
1881
1882
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1883
  *result = val->IsNativeError();
1884
1885
  return napi_clear_last_error(env);
1886
}
1887
1888
napi_status napi_get_value_double(napi_env env,
1889
                                  napi_value value,
1890
                                  double* result) {
1891
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1892
  // JS exceptions.
1893
  CHECK_ENV(env);
1894
  CHECK_ARG(env, value);
1895
  CHECK_ARG(env, result);
1896
1897
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1898
  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1899
1900
  *result = val.As<v8::Number>()->Value();
1901
1902
  return napi_clear_last_error(env);
1903
}
1904
1905
napi_status napi_get_value_int32(napi_env env,
1906
                                 napi_value value,
1907
                                 int32_t* result) {
1908
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1909
  // JS exceptions.
1910
  CHECK_ENV(env);
1911
  CHECK_ARG(env, value);
1912
  CHECK_ARG(env, result);
1913
1914
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1915
1916
  if (val->IsInt32()) {
1917
    *result = val.As<v8::Int32>()->Value();
1918
  } else {
1919
    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1920
1921
    // Empty context: https://github.com/nodejs/node/issues/14379
1922
    v8::Local<v8::Context> context;
1923
    *result = val->Int32Value(context).FromJust();
1924
  }
1925
1926
  return napi_clear_last_error(env);
1927
}
1928
1929
napi_status napi_get_value_uint32(napi_env env,
1930
                                  napi_value value,
1931
                                  uint32_t* result) {
1932
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1933
  // JS exceptions.
1934
  CHECK_ENV(env);
1935
  CHECK_ARG(env, value);
1936
  CHECK_ARG(env, result);
1937
1938
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1939
1940
  if (val->IsUint32()) {
1941
    *result = val.As<v8::Uint32>()->Value();
1942
  } else {
1943
    RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1944
1945
    // Empty context: https://github.com/nodejs/node/issues/14379
1946
    v8::Local<v8::Context> context;
1947
    *result = val->Uint32Value(context).FromJust();
1948
  }
1949
1950
  return napi_clear_last_error(env);
1951
}
1952
1953
napi_status napi_get_value_int64(napi_env env,
1954
                                 napi_value value,
1955
                                 int64_t* result) {
1956
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1957
  // JS exceptions.
1958
  CHECK_ENV(env);
1959
  CHECK_ARG(env, value);
1960
  CHECK_ARG(env, result);
1961
1962
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1963
1964
  // This is still a fast path very likely to be taken.
1965
  if (val->IsInt32()) {
1966
    *result = val.As<v8::Int32>()->Value();
1967
    return napi_clear_last_error(env);
1968
  }
1969
1970
  RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
1971
1972
  // v8::Value::IntegerValue() converts NaN, +Inf, and -Inf to INT64_MIN,
1973
  // inconsistent with v8::Value::Int32Value() which converts those values to 0.
1974
  // Special-case all non-finite values to match that behavior.
1975
  double doubleValue = val.As<v8::Number>()->Value();
1976
  if (std::isfinite(doubleValue)) {
1977
    // Empty context: https://github.com/nodejs/node/issues/14379
1978
    v8::Local<v8::Context> context;
1979
    *result = val->IntegerValue(context).FromJust();
1980
  } else {
1981
    *result = 0;
1982
  }
1983
1984
  return napi_clear_last_error(env);
1985
}
1986
1987
napi_status napi_get_value_bigint_int64(napi_env env,
1988
                                        napi_value value,
1989
                                        int64_t* result,
1990
                                        bool* lossless) {
1991
  CHECK_ENV(env);
1992
  CHECK_ARG(env, value);
1993
  CHECK_ARG(env, result);
1994
  CHECK_ARG(env, lossless);
1995
1996
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1997
1998
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
1999
2000
  *result = val.As<v8::BigInt>()->Int64Value(lossless);
2001
2002
  return napi_clear_last_error(env);
2003
}
2004
2005
napi_status napi_get_value_bigint_uint64(napi_env env,
2006
                                         napi_value value,
2007
                                         uint64_t* result,
2008
                                         bool* lossless) {
2009
  CHECK_ENV(env);
2010
  CHECK_ARG(env, value);
2011
  CHECK_ARG(env, result);
2012
  CHECK_ARG(env, lossless);
2013
2014
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2015
2016
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
2017
2018
  *result = val.As<v8::BigInt>()->Uint64Value(lossless);
2019
2020
  return napi_clear_last_error(env);
2021
}
2022
2023
napi_status napi_get_value_bigint_words(napi_env env,
2024
                                        napi_value value,
2025
                                        int* sign_bit,
2026
                                        size_t* word_count,
2027
                                        uint64_t* words) {
2028
  CHECK_ENV(env);
2029
  CHECK_ARG(env, value);
2030
  CHECK_ARG(env, word_count);
2031
2032
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2033
2034
  RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
2035
2036
  v8::Local<v8::BigInt> big = val.As<v8::BigInt>();
2037
2038
  int word_count_int = *word_count;
2039
2040
  if (sign_bit == nullptr && words == nullptr) {
2041
    word_count_int = big->WordCount();
2042
  } else {
2043
    CHECK_ARG(env, sign_bit);
2044
    CHECK_ARG(env, words);
2045
    big->ToWordsArray(sign_bit, &word_count_int, words);
2046
  }
2047
2048
  *word_count = word_count_int;
2049
2050
  return napi_clear_last_error(env);
2051
}
2052
2053
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) {
2054
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2055
  // JS exceptions.
2056
  CHECK_ENV(env);
2057
  CHECK_ARG(env, value);
2058
  CHECK_ARG(env, result);
2059
2060
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2061
  RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected);
2062
2063
  *result = val.As<v8::Boolean>()->Value();
2064
2065
  return napi_clear_last_error(env);
2066
}
2067
2068
// Copies a JavaScript string into a LATIN-1 string buffer. The result is the
2069
// number of bytes (excluding the null terminator) copied into buf.
2070
// A sufficient buffer size should be greater than the length of string,
2071
// reserving space for null terminator.
2072
// If bufsize is insufficient, the string will be truncated and null terminated.
2073
// If buf is NULL, this method returns the length of the string (in bytes)
2074
// via the result parameter.
2075
// The result argument is optional unless buf is NULL.
2076
napi_status napi_get_value_string_latin1(napi_env env,
2077
                                         napi_value value,
2078
                                         char* buf,
2079
                                         size_t bufsize,
2080
                                         size_t* result) {
2081
  CHECK_ENV(env);
2082
  CHECK_ARG(env, value);
2083
2084
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2085
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2086
2087
  if (!buf) {
2088
    CHECK_ARG(env, result);
2089
    *result = val.As<v8::String>()->Length();
2090
  } else if (bufsize != 0) {
2091
    int copied =
2092
        val.As<v8::String>()->WriteOneByte(env->isolate,
2093
                                           reinterpret_cast<uint8_t*>(buf),
2094
                                           0,
2095
                                           bufsize - 1,
2096
                                           v8::String::NO_NULL_TERMINATION);
2097
2098
    buf[copied] = '\0';
2099
    if (result != nullptr) {
2100
      *result = copied;
2101
    }
2102
  } else if (result != nullptr) {
2103
    *result = 0;
2104
  }
2105
2106
  return napi_clear_last_error(env);
2107
}
2108
2109
// Copies a JavaScript string into a UTF-8 string buffer. The result is the
2110
// number of bytes (excluding the null terminator) copied into buf.
2111
// A sufficient buffer size should be greater than the length of string,
2112
// reserving space for null terminator.
2113
// If bufsize is insufficient, the string will be truncated and null terminated.
2114
// If buf is NULL, this method returns the length of the string (in bytes)
2115
// via the result parameter.
2116
// The result argument is optional unless buf is NULL.
2117
napi_status napi_get_value_string_utf8(napi_env env,
2118
                                       napi_value value,
2119
                                       char* buf,
2120
                                       size_t bufsize,
2121
                                       size_t* result) {
2122
  CHECK_ENV(env);
2123
  CHECK_ARG(env, value);
2124
2125
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2126
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2127
2128
  if (!buf) {
2129
    CHECK_ARG(env, result);
2130
    *result = val.As<v8::String>()->Utf8Length(env->isolate);
2131
  } else if (bufsize != 0) {
2132
    int copied = val.As<v8::String>()->WriteUtf8(
2133
        env->isolate,
2134
        buf,
2135
        bufsize - 1,
2136
        nullptr,
2137
        v8::String::REPLACE_INVALID_UTF8 | v8::String::NO_NULL_TERMINATION);
2138
2139
    buf[copied] = '\0';
2140
    if (result != nullptr) {
2141
      *result = copied;
2142
    }
2143
  } else if (result != nullptr) {
2144
    *result = 0;
2145
  }
2146
2147
  return napi_clear_last_error(env);
2148
}
2149
2150
// Copies a JavaScript string into a UTF-16 string buffer. The result is the
2151
// number of 2-byte code units (excluding the null terminator) copied into buf.
2152
// A sufficient buffer size should be greater than the length of string,
2153
// reserving space for null terminator.
2154
// If bufsize is insufficient, the string will be truncated and null terminated.
2155
// If buf is NULL, this method returns the length of the string (in 2-byte
2156
// code units) via the result parameter.
2157
// The result argument is optional unless buf is NULL.
2158
napi_status napi_get_value_string_utf16(napi_env env,
2159
                                        napi_value value,
2160
                                        char16_t* buf,
2161
                                        size_t bufsize,
2162
                                        size_t* result) {
2163
  CHECK_ENV(env);
2164
  CHECK_ARG(env, value);
2165
2166
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2167
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2168
2169
  if (!buf) {
2170
    CHECK_ARG(env, result);
2171
    // V8 assumes UTF-16 length is the same as the number of characters.
2172
    *result = val.As<v8::String>()->Length();
2173
  } else if (bufsize != 0) {
2174
    int copied = val.As<v8::String>()->Write(env->isolate,
2175
                                             reinterpret_cast<uint16_t*>(buf),
2176
                                             0,
2177
                                             bufsize - 1,
2178
                                             v8::String::NO_NULL_TERMINATION);
2179
2180
    buf[copied] = '\0';
2181
    if (result != nullptr) {
2182
      *result = copied;
2183
    }
2184
  } else if (result != nullptr) {
2185
    *result = 0;
2186
  }
2187
2188
  return napi_clear_last_error(env);
2189
}
2190
2191
napi_status napi_coerce_to_bool(napi_env env,
2192
                                napi_value value,
2193
                                napi_value* result) {
2194
  NAPI_PREAMBLE(env);
2195
  CHECK_ARG(env, value);
2196
  CHECK_ARG(env, result);
2197
2198
  v8::Isolate* isolate = env->isolate;
2199
  v8::Local<v8::Boolean> b =
2200
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2201
  *result = v8impl::JsValueFromV8LocalValue(b);
2202
  return GET_RETURN_STATUS(env);
2203
}
2204
2205
#define GEN_COERCE_FUNCTION(UpperCaseName, MixedCaseName, LowerCaseName)      \
2206
  napi_status napi_coerce_to_##LowerCaseName(napi_env env,                    \
2207
                                             napi_value value,                \
2208
                                             napi_value* result) {            \
2209
    NAPI_PREAMBLE(env);                                                       \
2210
    CHECK_ARG(env, value);                                                    \
2211
    CHECK_ARG(env, result);                                                   \
2212
                                                                              \
2213
    v8::Local<v8::Context> context = env->context();                          \
2214
    v8::Local<v8::MixedCaseName> str;                                         \
2215
                                                                              \
2216
    CHECK_TO_##UpperCaseName(env, context, str, value);                       \
2217
                                                                              \
2218
    *result = v8impl::JsValueFromV8LocalValue(str);                           \
2219
    return GET_RETURN_STATUS(env);                                            \
2220
  }
2221
2222
GEN_COERCE_FUNCTION(NUMBER, Number, number)
2223
GEN_COERCE_FUNCTION(OBJECT, Object, object)
2224
GEN_COERCE_FUNCTION(STRING, String, string)
2225
2226
#undef GEN_COERCE_FUNCTION
2227
2228
napi_status napi_wrap(napi_env env,
2229
                      napi_value js_object,
2230
                      void* native_object,
2231
                      napi_finalize finalize_cb,
2232
                      void* finalize_hint,
2233
                      napi_ref* result) {
2234
  return v8impl::Wrap<v8impl::retrievable>(env,
2235
                                           js_object,
2236
                                           native_object,
2237
                                           finalize_cb,
2238
                                           finalize_hint,
2239
                                           result);
2240
}
2241
2242
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2243
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2244
}
2245
2246
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2247
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2248
}
2249
2250
1
napi_status napi_create_external(napi_env env,
2251
                                 void* data,
2252
                                 napi_finalize finalize_cb,
2253
                                 void* finalize_hint,
2254
                                 napi_value* result) {
2255


3
  NAPI_PREAMBLE(env);
2256
1
  CHECK_ARG(env, result);
2257
2258
1
  v8::Isolate* isolate = env->isolate;
2259
2260
1
  v8::Local<v8::Value> external_value = v8::External::New(isolate, data);
2261
2262
  // The Reference object will delete itself after invoking the finalizer
2263
  // callback.
2264
  v8impl::Reference::New(env,
2265
      external_value,
2266
      0,
2267
      true,
2268
      finalize_cb,
2269
      data,
2270
1
      finalize_hint);
2271
2272
1
  *result = v8impl::JsValueFromV8LocalValue(external_value);
2273
2274
1
  return napi_clear_last_error(env);
2275
}
2276
2277
NAPI_EXTERN napi_status napi_type_tag_object(napi_env env,
2278
                                             napi_value object,
2279
                                             const napi_type_tag* type_tag) {
2280
  NAPI_PREAMBLE(env);
2281
  v8::Local<v8::Context> context = env->context();
2282
  v8::Local<v8::Object> obj;
2283
  CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, obj, object);
2284
  CHECK_ARG_WITH_PREAMBLE(env, type_tag);
2285
2286
  auto key = NAPI_PRIVATE_KEY(context, type_tag);
2287
  auto maybe_has = obj->HasPrivate(context, key);
2288
  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_has, napi_generic_failure);
2289
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
2290
                                       !maybe_has.FromJust(),
2291
                                       napi_invalid_arg);
2292
2293
  auto tag = v8::BigInt::NewFromWords(context,
2294
                                   0,
2295
                                   2,
2296
                                   reinterpret_cast<const uint64_t*>(type_tag));
2297
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, tag, napi_generic_failure);
2298
2299
  auto maybe_set = obj->SetPrivate(context, key, tag.ToLocalChecked());
2300
  CHECK_MAYBE_NOTHING_WITH_PREAMBLE(env, maybe_set, napi_generic_failure);
2301
  RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env,
2302
                                       maybe_set.FromJust(),
2303
                                       napi_generic_failure);
2304
2305
  return GET_RETURN_STATUS(env);
2306
}
2307
2308
NAPI_EXTERN napi_status
2309
napi_check_object_type_tag(napi_env env,
2310
                           napi_value object,
2311
                           const napi_type_tag* type_tag,
2312
                           bool* result) {
2313
  NAPI_PREAMBLE(env);
2314
  v8::Local<v8::Context> context = env->context();
2315
  v8::Local<v8::Object> obj;
2316
  CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, obj, object);
2317
  CHECK_ARG_WITH_PREAMBLE(env, type_tag);
2318
  CHECK_ARG_WITH_PREAMBLE(env, result);
2319
2320
  auto maybe_value = obj->GetPrivate(context,
2321
                                     NAPI_PRIVATE_KEY(context, type_tag));
2322
  CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe_value, napi_generic_failure);
2323
  v8::Local<v8::Value> val = maybe_value.ToLocalChecked();
2324
2325
  // We consider the type check to have failed unless we reach the line below
2326
  // where we set whether the type check succeeded or not based on the
2327
  // comparison of the two type tags.
2328
  *result = false;
2329
  if (val->IsBigInt()) {
2330
    int sign;
2331
    int size = 2;
2332
    napi_type_tag tag;
2333
    val.As<v8::BigInt>()->ToWordsArray(&sign,
2334
                                       &size,
2335
                                       reinterpret_cast<uint64_t*>(&tag));
2336
    if (size == 2 && sign == 0)
2337
      *result = (tag.lower == type_tag->lower && tag.upper == type_tag->upper);
2338
  }
2339
2340
  return GET_RETURN_STATUS(env);
2341
}
2342
2343
napi_status napi_get_value_external(napi_env env,
2344
                                    napi_value value,
2345
                                    void** result) {
2346
  CHECK_ENV(env);
2347
  CHECK_ARG(env, value);
2348
  CHECK_ARG(env, result);
2349
2350
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2351
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
2352
2353
  v8::Local<v8::External> external_value = val.As<v8::External>();
2354
  *result = external_value->Value();
2355
2356
  return napi_clear_last_error(env);
2357
}
2358
2359
// Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
2360
napi_status napi_create_reference(napi_env env,
2361
                                  napi_value value,
2362
                                  uint32_t initial_refcount,
2363
                                  napi_ref* result) {
2364
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2365
  // JS exceptions.
2366
  CHECK_ENV(env);
2367
  CHECK_ARG(env, value);
2368
  CHECK_ARG(env, result);
2369
2370
  v8::Local<v8::Value> v8_value = v8impl::V8LocalValueFromJsValue(value);
2371
2372
  if (!(v8_value->IsObject() || v8_value->IsFunction())) {
2373
    return napi_set_last_error(env, napi_object_expected);
2374
  }
2375
2376
  v8impl::Reference* reference =
2377
      v8impl::Reference::New(env, v8_value, initial_refcount, false);
2378
2379
  *result = reinterpret_cast<napi_ref>(reference);
2380
  return napi_clear_last_error(env);
2381
}
2382
2383
// Deletes a reference. The referenced value is released, and may be GC'd unless
2384
// there are other references to it.
2385
napi_status napi_delete_reference(napi_env env, napi_ref ref) {
2386
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2387
  // JS exceptions.
2388
  CHECK_ENV(env);
2389
  CHECK_ARG(env, ref);
2390
2391
  v8impl::Reference::Delete(reinterpret_cast<v8impl::Reference*>(ref));
2392
2393
  return napi_clear_last_error(env);
2394
}
2395
2396
// Increments the reference count, optionally returning the resulting count.
2397
// After this call the reference will be a strong reference because its
2398
// refcount is >0, and the referenced object is effectively "pinned".
2399
// Calling this when the refcount is 0 and the object is unavailable
2400
// results in an error.
2401
napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) {
2402
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2403
  // JS exceptions.
2404
  CHECK_ENV(env);
2405
  CHECK_ARG(env, ref);
2406
2407
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2408
  uint32_t count = reference->Ref();
2409
2410
  if (result != nullptr) {
2411
    *result = count;
2412
  }
2413
2414
  return napi_clear_last_error(env);
2415
}
2416
2417
// Decrements the reference count, optionally returning the resulting count. If
2418
// the result is 0 the reference is now weak and the object may be GC'd at any
2419
// time if there are no other references. Calling this when the refcount is
2420
// already 0 results in an error.
2421
napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) {
2422
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2423
  // JS exceptions.
2424
  CHECK_ENV(env);
2425
  CHECK_ARG(env, ref);
2426
2427
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2428
2429
  if (reference->RefCount() == 0) {
2430
    return napi_set_last_error(env, napi_generic_failure);
2431
  }
2432
2433
  uint32_t count = reference->Unref();
2434
2435
  if (result != nullptr) {
2436
    *result = count;
2437
  }
2438
2439
  return napi_clear_last_error(env);
2440
}
2441
2442
// Attempts to get a referenced value. If the reference is weak, the value might
2443
// no longer be available, in that case the call is still successful but the
2444
// result is NULL.
2445
napi_status napi_get_reference_value(napi_env env,
2446
                                     napi_ref ref,
2447
                                     napi_value* result) {
2448
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2449
  // JS exceptions.
2450
  CHECK_ENV(env);
2451
  CHECK_ARG(env, ref);
2452
  CHECK_ARG(env, result);
2453
2454
  v8impl::Reference* reference = reinterpret_cast<v8impl::Reference*>(ref);
2455
  *result = v8impl::JsValueFromV8LocalValue(reference->Get());
2456
2457
  return napi_clear_last_error(env);
2458
}
2459
2460
napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result) {
2461
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2462
  // JS exceptions.
2463
  CHECK_ENV(env);
2464
  CHECK_ARG(env, result);
2465
2466
  *result = v8impl::JsHandleScopeFromV8HandleScope(
2467
      new v8impl::HandleScopeWrapper(env->isolate));
2468
  env->open_handle_scopes++;
2469
  return napi_clear_last_error(env);
2470
}
2471
2472
napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) {
2473
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2474
  // JS exceptions.
2475
  CHECK_ENV(env);
2476
  CHECK_ARG(env, scope);
2477
  if (env->open_handle_scopes == 0) {
2478
    return napi_handle_scope_mismatch;
2479
  }
2480
2481
  env->open_handle_scopes--;
2482
  delete v8impl::V8HandleScopeFromJsHandleScope(scope);
2483
  return napi_clear_last_error(env);
2484
}
2485
2486
napi_status napi_open_escapable_handle_scope(
2487
    napi_env env,
2488
    napi_escapable_handle_scope* result) {
2489
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2490
  // JS exceptions.
2491
  CHECK_ENV(env);
2492
  CHECK_ARG(env, result);
2493
2494
  *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope(
2495
      new v8impl::EscapableHandleScopeWrapper(env->isolate));
2496
  env->open_handle_scopes++;
2497
  return napi_clear_last_error(env);
2498
}
2499
2500
napi_status napi_close_escapable_handle_scope(
2501
    napi_env env,
2502
    napi_escapable_handle_scope scope) {
2503
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2504
  // JS exceptions.
2505
  CHECK_ENV(env);
2506
  CHECK_ARG(env, scope);
2507
  if (env->open_handle_scopes == 0) {
2508
    return napi_handle_scope_mismatch;
2509
  }
2510
2511
  delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2512
  env->open_handle_scopes--;
2513
  return napi_clear_last_error(env);
2514
}
2515
2516
napi_status napi_escape_handle(napi_env env,
2517
                               napi_escapable_handle_scope scope,
2518
                               napi_value escapee,
2519
                               napi_value* result) {
2520
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2521
  // JS exceptions.
2522
  CHECK_ENV(env);
2523
  CHECK_ARG(env, scope);
2524
  CHECK_ARG(env, escapee);
2525
  CHECK_ARG(env, result);
2526
2527
  v8impl::EscapableHandleScopeWrapper* s =
2528
      v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
2529
  if (!s->escape_called()) {
2530
    *result = v8impl::JsValueFromV8LocalValue(
2531
        s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
2532
    return napi_clear_last_error(env);
2533
  }
2534
  return napi_set_last_error(env, napi_escape_called_twice);
2535
}
2536
2537
napi_status napi_new_instance(napi_env env,
2538
                              napi_value constructor,
2539
                              size_t argc,
2540
                              const napi_value* argv,
2541
                              napi_value* result) {
2542
  NAPI_PREAMBLE(env);
2543
  CHECK_ARG(env, constructor);
2544
  if (argc > 0) {
2545
    CHECK_ARG(env, argv);
2546
  }
2547
  CHECK_ARG(env, result);
2548
2549
  v8::Local<v8::Context> context = env->context();
2550
2551
  v8::Local<v8::Function> ctor;
2552
  CHECK_TO_FUNCTION(env, ctor, constructor);
2553
2554
  auto maybe = ctor->NewInstance(context, argc,
2555
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2556
2557
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2558
2559
  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2560
  return GET_RETURN_STATUS(env);
2561
}
2562
2563
napi_status napi_instanceof(napi_env env,
2564
                            napi_value object,
2565
                            napi_value constructor,
2566
                            bool* result) {
2567
  NAPI_PREAMBLE(env);
2568
  CHECK_ARG(env, object);
2569
  CHECK_ARG(env, result);
2570
2571
  *result = false;
2572
2573
  v8::Local<v8::Object> ctor;
2574
  v8::Local<v8::Context> context = env->context();
2575
2576
  CHECK_TO_OBJECT(env, context, ctor, constructor);
2577
2578
  if (!ctor->IsFunction()) {
2579
    napi_throw_type_error(env,
2580
                          "ERR_NAPI_CONS_FUNCTION",
2581
                          "Constructor must be a function");
2582
2583
    return napi_set_last_error(env, napi_function_expected);
2584
  }
2585
2586
  napi_status status = napi_generic_failure;
2587
2588
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(object);
2589
  auto maybe_result = val->InstanceOf(context, ctor);
2590
  CHECK_MAYBE_NOTHING(env, maybe_result, status);
2591
  *result = maybe_result.FromJust();
2592
  return GET_RETURN_STATUS(env);
2593
}
2594
2595
// Methods to support catching exceptions
2596
napi_status napi_is_exception_pending(napi_env env, bool* result) {
2597
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2598
  // pending exception.
2599
  CHECK_ENV(env);
2600
  CHECK_ARG(env, result);
2601
2602
  *result = !env->last_exception.IsEmpty();
2603
  return napi_clear_last_error(env);
2604
}
2605
2606
napi_status napi_get_and_clear_last_exception(napi_env env,
2607
                                              napi_value* result) {
2608
  // NAPI_PREAMBLE is not used here: this function must execute when there is a
2609
  // pending exception.
2610
  CHECK_ENV(env);
2611
  CHECK_ARG(env, result);
2612
2613
  if (env->last_exception.IsEmpty()) {
2614
    return napi_get_undefined(env, result);
2615
  } else {
2616
    *result = v8impl::JsValueFromV8LocalValue(
2617
      v8::Local<v8::Value>::New(env->isolate, env->last_exception));
2618
    env->last_exception.Reset();
2619
  }
2620
2621
  return napi_clear_last_error(env);
2622
}
2623
2624
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) {
2625
  CHECK_ENV(env);
2626
  CHECK_ARG(env, value);
2627
  CHECK_ARG(env, result);
2628
2629
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2630
  *result = val->IsArrayBuffer();
2631
2632
  return napi_clear_last_error(env);
2633
}
2634
2635
napi_status napi_create_arraybuffer(napi_env env,
2636
                                    size_t byte_length,
2637
                                    void** data,
2638
                                    napi_value* result) {
2639
  NAPI_PREAMBLE(env);
2640
  CHECK_ARG(env, result);
2641
2642
  v8::Isolate* isolate = env->isolate;
2643
  v8::Local<v8::ArrayBuffer> buffer =
2644
      v8::ArrayBuffer::New(isolate, byte_length);
2645
2646
  // Optionally return a pointer to the buffer's data, to avoid another call to
2647
  // retrieve it.
2648
  if (data != nullptr) {
2649
    *data = buffer->GetBackingStore()->Data();
2650
  }
2651
2652
  *result = v8impl::JsValueFromV8LocalValue(buffer);
2653
  return GET_RETURN_STATUS(env);
2654
}
2655
2656
napi_status napi_create_external_arraybuffer(napi_env env,
2657
                                             void* external_data,
2658
                                             size_t byte_length,
2659
                                             napi_finalize finalize_cb,
2660
                                             void* finalize_hint,
2661
                                             napi_value* result) {
2662
  // The API contract here is that the cleanup function runs on the JS thread,
2663
  // and is able to use napi_env. Implementing that properly is hard, so use the
2664
  // `Buffer` variant for easier implementation.
2665
  napi_value buffer;
2666
  STATUS_CALL(napi_create_external_buffer(
2667
      env,
2668
      byte_length,
2669
      external_data,
2670
      finalize_cb,
2671
      finalize_hint,
2672
      &buffer));
2673
  return napi_get_typedarray_info(
2674
      env,
2675
      buffer,
2676
      nullptr,
2677
      nullptr,
2678
      nullptr,
2679
      result,
2680
      nullptr);
2681
}
2682
2683
napi_status napi_get_arraybuffer_info(napi_env env,
2684
                                      napi_value arraybuffer,
2685
                                      void** data,
2686
                                      size_t* byte_length) {
2687
  CHECK_ENV(env);
2688
  CHECK_ARG(env, arraybuffer);
2689
2690
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2691
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2692
2693
  std::shared_ptr<v8::BackingStore> backing_store =
2694
      value.As<v8::ArrayBuffer>()->GetBackingStore();
2695
2696
  if (data != nullptr) {
2697
    *data = backing_store->Data();
2698
  }
2699
2700
  if (byte_length != nullptr) {
2701
    *byte_length = backing_store->ByteLength();
2702
  }
2703
2704
  return napi_clear_last_error(env);
2705
}
2706
2707
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) {
2708
  CHECK_ENV(env);
2709
  CHECK_ARG(env, value);
2710
  CHECK_ARG(env, result);
2711
2712
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2713
  *result = val->IsTypedArray();
2714
2715
  return napi_clear_last_error(env);
2716
}
2717
2718
napi_status napi_create_typedarray(napi_env env,
2719
                                   napi_typedarray_type type,
2720
                                   size_t length,
2721
                                   napi_value arraybuffer,
2722
                                   size_t byte_offset,
2723
                                   napi_value* result) {
2724
  NAPI_PREAMBLE(env);
2725
  CHECK_ARG(env, arraybuffer);
2726
  CHECK_ARG(env, result);
2727
2728
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2729
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2730
2731
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2732
  v8::Local<v8::TypedArray> typedArray;
2733
2734
  switch (type) {
2735
    case napi_int8_array:
2736
      CREATE_TYPED_ARRAY(
2737
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2738
      break;
2739
    case napi_uint8_array:
2740
      CREATE_TYPED_ARRAY(
2741
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2742
      break;
2743
    case napi_uint8_clamped_array:
2744
      CREATE_TYPED_ARRAY(
2745
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2746
      break;
2747
    case napi_int16_array:
2748
      CREATE_TYPED_ARRAY(
2749
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2750
      break;
2751
    case napi_uint16_array:
2752
      CREATE_TYPED_ARRAY(
2753
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2754
      break;
2755
    case napi_int32_array:
2756
      CREATE_TYPED_ARRAY(
2757
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2758
      break;
2759
    case napi_uint32_array:
2760
      CREATE_TYPED_ARRAY(
2761
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2762
      break;
2763
    case napi_float32_array:
2764
      CREATE_TYPED_ARRAY(
2765
          env, Float32Array, 4, buffer, byte_offset, length, typedArray);
2766
      break;
2767
    case napi_float64_array:
2768
      CREATE_TYPED_ARRAY(
2769
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2770
      break;
2771
    case napi_bigint64_array:
2772
      CREATE_TYPED_ARRAY(
2773
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2774
      break;
2775
    case napi_biguint64_array:
2776
      CREATE_TYPED_ARRAY(
2777
          env, BigUint64Array, 8, buffer, byte_offset, length, typedArray);
2778
      break;
2779
    default:
2780
      return napi_set_last_error(env, napi_invalid_arg);
2781
  }
2782
2783
  *result = v8impl::JsValueFromV8LocalValue(typedArray);
2784
  return GET_RETURN_STATUS(env);
2785
}
2786
2787
napi_status napi_get_typedarray_info(napi_env env,
2788
                                     napi_value typedarray,
2789
                                     napi_typedarray_type* type,
2790
                                     size_t* length,
2791
                                     void** data,
2792
                                     napi_value* arraybuffer,
2793
                                     size_t* byte_offset) {
2794
  CHECK_ENV(env);
2795
  CHECK_ARG(env, typedarray);
2796
2797
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(typedarray);
2798
  RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), napi_invalid_arg);
2799
2800
  v8::Local<v8::TypedArray> array = value.As<v8::TypedArray>();
2801
2802
  if (type != nullptr) {
2803
    if (value->IsInt8Array()) {
2804
      *type = napi_int8_array;
2805
    } else if (value->IsUint8Array()) {
2806
      *type = napi_uint8_array;
2807
    } else if (value->IsUint8ClampedArray()) {
2808
      *type = napi_uint8_clamped_array;
2809
    } else if (value->IsInt16Array()) {
2810
      *type = napi_int16_array;
2811
    } else if (value->IsUint16Array()) {
2812
      *type = napi_uint16_array;
2813
    } else if (value->IsInt32Array()) {
2814
      *type = napi_int32_array;
2815
    } else if (value->IsUint32Array()) {
2816
      *type = napi_uint32_array;
2817
    } else if (value->IsFloat32Array()) {
2818
      *type = napi_float32_array;
2819
    } else if (value->IsFloat64Array()) {
2820
      *type = napi_float64_array;
2821
    } else if (value->IsBigInt64Array()) {
2822
      *type = napi_bigint64_array;
2823
    } else if (value->IsBigUint64Array()) {
2824
      *type = napi_biguint64_array;
2825
    }
2826
  }
2827
2828
  if (length != nullptr) {
2829
    *length = array->Length();
2830
  }
2831
2832
  v8::Local<v8::ArrayBuffer> buffer;
2833
  if (data != nullptr || arraybuffer != nullptr) {
2834
    // Calling Buffer() may have the side effect of allocating the buffer,
2835
    // so only do this when it’s needed.
2836
    buffer = array->Buffer();
2837
  }
2838
2839
  if (data != nullptr) {
2840
    *data = static_cast<uint8_t*>(buffer->GetBackingStore()->Data()) +
2841
            array->ByteOffset();
2842
  }
2843
2844
  if (arraybuffer != nullptr) {
2845
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2846
  }
2847
2848
  if (byte_offset != nullptr) {
2849
    *byte_offset = array->ByteOffset();
2850
  }
2851
2852
  return napi_clear_last_error(env);
2853
}
2854
2855
napi_status napi_create_dataview(napi_env env,
2856
                                 size_t byte_length,
2857
                                 napi_value arraybuffer,
2858
                                 size_t byte_offset,
2859
                                 napi_value* result) {
2860
  NAPI_PREAMBLE(env);
2861
  CHECK_ARG(env, arraybuffer);
2862
  CHECK_ARG(env, result);
2863
2864
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2865
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2866
2867
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2868
  if (byte_length + byte_offset > buffer->ByteLength()) {
2869
    napi_throw_range_error(
2870
        env,
2871
        "ERR_NAPI_INVALID_DATAVIEW_ARGS",
2872
        "byte_offset + byte_length should be less than or "
2873
        "equal to the size in bytes of the array passed in");
2874
    return napi_set_last_error(env, napi_pending_exception);
2875
  }
2876
  v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset,
2877
                                                       byte_length);
2878
2879
  *result = v8impl::JsValueFromV8LocalValue(DataView);
2880
  return GET_RETURN_STATUS(env);
2881
}
2882
2883
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) {
2884
  CHECK_ENV(env);
2885
  CHECK_ARG(env, value);
2886
  CHECK_ARG(env, result);
2887
2888
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2889
  *result = val->IsDataView();
2890
2891
  return napi_clear_last_error(env);
2892
}
2893
2894
napi_status napi_get_dataview_info(napi_env env,
2895
                                   napi_value dataview,
2896
                                   size_t* byte_length,
2897
                                   void** data,
2898
                                   napi_value* arraybuffer,
2899
                                   size_t* byte_offset) {
2900
  CHECK_ENV(env);
2901
  CHECK_ARG(env, dataview);
2902
2903
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(dataview);
2904
  RETURN_STATUS_IF_FALSE(env, value->IsDataView(), napi_invalid_arg);
2905
2906
  v8::Local<v8::DataView> array = value.As<v8::DataView>();
2907
2908
  if (byte_length != nullptr) {
2909
    *byte_length = array->ByteLength();
2910
  }
2911
2912
  v8::Local<v8::ArrayBuffer> buffer;
2913
  if (data != nullptr || arraybuffer != nullptr) {
2914
    // Calling Buffer() may have the side effect of allocating the buffer,
2915
    // so only do this when it’s needed.
2916
    buffer = array->Buffer();
2917
  }
2918
2919
  if (data != nullptr) {
2920
    *data = static_cast<uint8_t*>(buffer->GetBackingStore()->Data()) +
2921
            array->ByteOffset();
2922
  }
2923
2924
  if (arraybuffer != nullptr) {
2925
    *arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
2926
  }
2927
2928
  if (byte_offset != nullptr) {
2929
    *byte_offset = array->ByteOffset();
2930
  }
2931
2932
  return napi_clear_last_error(env);
2933
}
2934
2935
napi_status napi_get_version(napi_env env, uint32_t* result) {
2936
  CHECK_ENV(env);
2937
  CHECK_ARG(env, result);
2938
  *result = NAPI_VERSION;
2939
  return napi_clear_last_error(env);
2940
}
2941
2942
napi_status napi_create_promise(napi_env env,
2943
                                napi_deferred* deferred,
2944
                                napi_value* promise) {
2945
  NAPI_PREAMBLE(env);
2946
  CHECK_ARG(env, deferred);
2947
  CHECK_ARG(env, promise);
2948
2949
  auto maybe = v8::Promise::Resolver::New(env->context());
2950
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2951
2952
  auto v8_resolver = maybe.ToLocalChecked();
2953
  auto v8_deferred = new v8impl::Persistent<v8::Value>();
2954
  v8_deferred->Reset(env->isolate, v8_resolver);
2955
2956
  *deferred = v8impl::JsDeferredFromNodePersistent(v8_deferred);
2957
  *promise = v8impl::JsValueFromV8LocalValue(v8_resolver->GetPromise());
2958
  return GET_RETURN_STATUS(env);
2959
}
2960
2961
napi_status napi_resolve_deferred(napi_env env,
2962
                                  napi_deferred deferred,
2963
                                  napi_value resolution) {
2964
  return v8impl::ConcludeDeferred(env, deferred, resolution, true);
2965
}
2966
2967
napi_status napi_reject_deferred(napi_env env,
2968
                                 napi_deferred deferred,
2969
                                 napi_value resolution) {
2970
  return v8impl::ConcludeDeferred(env, deferred, resolution, false);
2971
}
2972
2973
napi_status napi_is_promise(napi_env env,
2974
                            napi_value value,
2975
                            bool* is_promise) {
2976
  CHECK_ENV(env);
2977
  CHECK_ARG(env, value);
2978
  CHECK_ARG(env, is_promise);
2979
2980
  *is_promise = v8impl::V8LocalValueFromJsValue(value)->IsPromise();
2981
2982
  return napi_clear_last_error(env);
2983
}
2984
2985
napi_status napi_create_date(napi_env env,
2986
                             double time,
2987
                             napi_value* result) {
2988
  NAPI_PREAMBLE(env);
2989
  CHECK_ARG(env, result);
2990
2991
  v8::MaybeLocal<v8::Value> maybe_date = v8::Date::New(env->context(), time);
2992
  CHECK_MAYBE_EMPTY(env, maybe_date, napi_generic_failure);
2993
2994
  *result = v8impl::JsValueFromV8LocalValue(maybe_date.ToLocalChecked());
2995
2996
  return GET_RETURN_STATUS(env);
2997
}
2998
2999
napi_status napi_is_date(napi_env env,
3000
                         napi_value value,
3001
                         bool* is_date) {
3002
  CHECK_ENV(env);
3003
  CHECK_ARG(env, value);
3004
  CHECK_ARG(env, is_date);
3005
3006
  *is_date = v8impl::V8LocalValueFromJsValue(value)->IsDate();
3007
3008
  return napi_clear_last_error(env);
3009
}
3010
3011
napi_status napi_get_date_value(napi_env env,
3012
                                napi_value value,
3013
                                double* result) {
3014
  NAPI_PREAMBLE(env);
3015
  CHECK_ARG(env, value);
3016
  CHECK_ARG(env, result);
3017
3018
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
3019
  RETURN_STATUS_IF_FALSE(env, val->IsDate(), napi_date_expected);
3020
3021
  v8::Local<v8::Date> date = val.As<v8::Date>();
3022
  *result = date->ValueOf();
3023
3024
  return GET_RETURN_STATUS(env);
3025
}
3026
3027
napi_status napi_run_script(napi_env env,
3028
                            napi_value script,
3029
                            napi_value* result) {
3030
  NAPI_PREAMBLE(env);
3031
  CHECK_ARG(env, script);
3032
  CHECK_ARG(env, result);
3033
3034
  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
3035
3036
  if (!v8_script->IsString()) {
3037
    return napi_set_last_error(env, napi_string_expected);
3038
  }
3039
3040
  v8::Local<v8::Context> context = env->context();
3041
3042
  auto maybe_script = v8::Script::Compile(context,
3043
      v8::Local<v8::String>::Cast(v8_script));
3044
  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
3045
3046
  auto script_result =
3047
      maybe_script.ToLocalChecked()->Run(context);
3048
  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
3049
3050
  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
3051
  return GET_RETURN_STATUS(env);
3052
}
3053
3054
napi_status napi_add_finalizer(napi_env env,
3055
                               napi_value js_object,
3056
                               void* native_object,
3057
                               napi_finalize finalize_cb,
3058
                               void* finalize_hint,
3059
                               napi_ref* result) {
3060
  return v8impl::Wrap<v8impl::anonymous>(env,
3061
                                         js_object,
3062
                                         native_object,
3063
                                         finalize_cb,
3064
                                         finalize_hint,
3065
                                         result);
3066
}
3067
3068
napi_status napi_adjust_external_memory(napi_env env,
3069
                                        int64_t change_in_bytes,
3070
                                        int64_t* adjusted_value) {
3071
  CHECK_ENV(env);
3072
  CHECK_ARG(env, adjusted_value);
3073
3074
  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
3075
      change_in_bytes);
3076
3077
  return napi_clear_last_error(env);
3078
}
3079
3080
1
napi_status napi_set_instance_data(napi_env env,
3081
                                   void* data,
3082
                                   napi_finalize finalize_cb,
3083
                                   void* finalize_hint) {
3084
1
  CHECK_ENV(env);
3085
3086
1
  v8impl::RefBase* old_data = static_cast<v8impl::RefBase*>(env->instance_data);
3087
1
  if (old_data != nullptr) {
3088
    // Our contract so far has been to not finalize any old data there may be.
3089
    // So we simply delete it.
3090
    v8impl::RefBase::Delete(old_data);
3091
  }
3092
3093
1
  env->instance_data = v8impl::RefBase::New(env,
3094
                                            0,
3095
                                            true,
3096
                                            finalize_cb,
3097
                                            data,
3098
                                            finalize_hint);
3099
3100
1
  return napi_clear_last_error(env);
3101
}
3102
3103
napi_status napi_get_instance_data(napi_env env,
3104
                                   void** data) {
3105
  CHECK_ENV(env);
3106
  CHECK_ARG(env, data);
3107
3108
  v8impl::RefBase* idata = static_cast<v8impl::RefBase*>(env->instance_data);
3109
3110
  *data = (idata == nullptr ? nullptr : idata->Data());
3111
3112
  return napi_clear_last_error(env);
3113
}
3114
3115
napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) {
3116
  CHECK_ENV(env);
3117
  CHECK_ARG(env, arraybuffer);
3118
3119
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3120
  RETURN_STATUS_IF_FALSE(
3121
      env, value->IsArrayBuffer(), napi_arraybuffer_expected);
3122
3123
  v8::Local<v8::ArrayBuffer> it = value.As<v8::ArrayBuffer>();
3124
  RETURN_STATUS_IF_FALSE(
3125
      env, it->IsDetachable(), napi_detachable_arraybuffer_expected);
3126
3127
  it->Detach();
3128
3129
  return napi_clear_last_error(env);
3130
}
3131
3132
napi_status napi_is_detached_arraybuffer(napi_env env,
3133
                                         napi_value arraybuffer,
3134
                                         bool* result) {
3135
  CHECK_ENV(env);
3136
  CHECK_ARG(env, arraybuffer);
3137
  CHECK_ARG(env, result);
3138
3139
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3140
3141
  *result = value->IsArrayBuffer() &&
3142
            value.As<v8::ArrayBuffer>()->GetBackingStore()->Data() == nullptr;
3143
3144
  return napi_clear_last_error(env);
3145

366
}