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: 1260 1292 97.5 %
Date: 2019-05-05 22:32:45 Branches: 862 1472 58.6 %

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

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


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

10114
    if ((reference->RefCount() != 0) ||
243

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


54
  NAPI_PREAMBLE(env);
341
27
  CHECK_ARG(env, js_object);
342
27
  if (action == KeepWrap) {
343
24
    CHECK_ARG(env, result);
344
  }
345
346
27
  v8::Isolate* isolate = env->isolate;
347
27
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
348
349
27
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(js_object);
350
27
  RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
351
27
  v8::Local<v8::Object> obj = value.As<v8::Object>();
352
353
54
  auto val = obj->GetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
354
54
      .ToLocalChecked();
355
27
  RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
356
  Reference* reference =
357
50
      static_cast<v8impl::Reference*>(val.As<v8::External>()->Value());
358
359
25
  if (result) {
360
25
    *result = reference->Data();
361
  }
362
363
25
  if (action == RemoveWrap) {
364
6
    CHECK(obj->DeletePrivate(context, NAPI_PRIVATE_KEY(context, wrapper))
365
        .FromJust());
366
2
    Reference::Delete(reference);
367
  }
368
369
25
  return GET_RETURN_STATUS(env);
370
}
371
372
//=== Function napi_callback wrapper =================================
373
374
// Use this data structure to associate callback data with each N-API function
375
// exposed to JavaScript. The structure is stored in a v8::External which gets
376
// passed into our callback wrapper. This reduces the performance impact of
377
// calling through N-API.
378
// Ref: benchmark/misc/function_call
379
// Discussion (incl. perf. data): https://github.com/nodejs/node/pull/21072
380
688
struct CallbackBundle {
381
  // Bind the lifecycle of `this` C++ object to a JavaScript object.
382
  // We never delete a CallbackBundle C++ object directly.
383
343
  void BindLifecycleTo(v8::Isolate* isolate, v8::Local<v8::Value> target) {
384
343
    handle.Reset(isolate, target);
385
343
    handle.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
386
343
  }
387
388
  napi_env       env;      // Necessary to invoke C++ NAPI callback
389
  void*          cb_data;  // The user provided callback data
390
  napi_callback  function_or_getter;
391
  napi_callback  setter;
392
  v8impl::Persistent<v8::Value> handle;  // Die with this JavaScript object
393
394
 private:
395
1
  static void WeakCallback(v8::WeakCallbackInfo<CallbackBundle> const& info) {
396
    // Use the "WeakCallback mechanism" to delete the C++ `bundle` object.
397
    // This will be called when the v8::External containing `this` pointer
398
    // is being GC-ed.
399
1
    CallbackBundle* bundle = info.GetParameter();
400
1
    delete bundle;
401
1
  }
402
};
403
404
// Base class extended by classes that wrap V8 function and property callback
405
// info.
406
class CallbackWrapper {
407
 public:
408
4513
  CallbackWrapper(napi_value this_arg, size_t args_length, void* data)
409
4513
      : _this(this_arg), _args_length(args_length), _data(data) {}
410
411
  virtual napi_value GetNewTarget() = 0;
412
  virtual void Args(napi_value* buffer, size_t bufferlength) = 0;
413
  virtual void SetReturnValue(napi_value value) = 0;
414
415
37
  napi_value This() { return _this; }
416
417
4405
  size_t ArgsLength() { return _args_length; }
418
419
6
  void* Data() { return _data; }
420
421
 protected:
422
  const napi_value _this;
423
  const size_t _args_length;
424
  void* _data;
425
};
426
427
template <typename Info, napi_callback CallbackBundle::*FunctionField>
428
class CallbackWrapperBase : public CallbackWrapper {
429
 public:
430
4513
  CallbackWrapperBase(const Info& cbinfo, const size_t args_length)
431
      : CallbackWrapper(JsValueFromV8LocalValue(cbinfo.This()),
432
                        args_length,
433
                        nullptr),
434
4513
        _cbinfo(cbinfo) {
435
9026
    _bundle = reinterpret_cast<CallbackBundle*>(
436
        v8::Local<v8::External>::Cast(cbinfo.Data())->Value());
437
4513
    _data = _bundle->cb_data;
438
4513
  }
439
440
  napi_value GetNewTarget() override { return nullptr; }
441
442
 protected:
443
4513
  void InvokeCallback() {
444
    napi_callback_info cbinfo_wrapper = reinterpret_cast<napi_callback_info>(
445
4513
        static_cast<CallbackWrapper*>(this));
446
447
    // All other pointers we need are stored in `_bundle`
448
4513
    napi_env env = _bundle->env;
449
4513
    napi_callback cb = _bundle->*FunctionField;
450
451
    napi_value result;
452
9026
    NapiCallIntoModuleThrow(env, [&]() { result = cb(env, cbinfo_wrapper); });
453
454

4513
    if (result != nullptr) {
455
2705
      this->SetReturnValue(result);
456
    }
457
4513
  }
458
459
  const Info& _cbinfo;
460
  CallbackBundle* _bundle;
461
};
462
463
class FunctionCallbackWrapper
464
    : public CallbackWrapperBase<v8::FunctionCallbackInfo<v8::Value>,
465
                                 &CallbackBundle::function_or_getter> {
466
 public:
467
4472
  static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info) {
468
4472
    FunctionCallbackWrapper cbwrapper(info);
469
4472
    cbwrapper.InvokeCallback();
470
4472
  }
471
472
4472
  explicit FunctionCallbackWrapper(
473
      const v8::FunctionCallbackInfo<v8::Value>& cbinfo)
474
4472
      : CallbackWrapperBase(cbinfo, cbinfo.Length()) {}
475
476
8
  napi_value GetNewTarget() override {
477
16
    if (_cbinfo.IsConstructCall()) {
478
14
      return v8impl::JsValueFromV8LocalValue(_cbinfo.NewTarget());
479
    } else {
480
1
      return nullptr;
481
    }
482
  }
483
484
  /*virtual*/
485
4388
  void Args(napi_value* buffer, size_t buffer_length) override {
486
4388
    size_t i = 0;
487
4388
    size_t min = std::min(buffer_length, _args_length);
488
489
11332
    for (; i < min; i += 1) {
490
13888
      buffer[i] = v8impl::JsValueFromV8LocalValue(_cbinfo[i]);
491
    }
492
493
4388
    if (i < buffer_length) {
494
      napi_value undefined =
495
75
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
496
127
      for (; i < buffer_length; i += 1) {
497
102
        buffer[i] = undefined;
498
      }
499
    }
500
4388
  }
501
502
  /*virtual*/
503
2670
  void SetReturnValue(napi_value value) override {
504
2670
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
505
8010
    _cbinfo.GetReturnValue().Set(val);
506
2670
  }
507
};
508
509
class GetterCallbackWrapper
510
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<v8::Value>,
511
                                 &CallbackBundle::function_or_getter> {
512
 public:
513
36
  static void Invoke(v8::Local<v8::Name> property,
514
                     const v8::PropertyCallbackInfo<v8::Value>& info) {
515
36
    GetterCallbackWrapper cbwrapper(info);
516
36
    cbwrapper.InvokeCallback();
517
36
  }
518
519
36
  explicit GetterCallbackWrapper(
520
      const v8::PropertyCallbackInfo<v8::Value>& cbinfo)
521
36
      : CallbackWrapperBase(cbinfo, 0) {}
522
523
  /*virtual*/
524
  void Args(napi_value* buffer, size_t buffer_length) override {
525
    if (buffer_length > 0) {
526
      napi_value undefined =
527
          v8impl::JsValueFromV8LocalValue(v8::Undefined(_cbinfo.GetIsolate()));
528
      for (size_t i = 0; i < buffer_length; i += 1) {
529
        buffer[i] = undefined;
530
      }
531
    }
532
  }
533
534
  /*virtual*/
535
35
  void SetReturnValue(napi_value value) override {
536
35
    v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
537
105
    _cbinfo.GetReturnValue().Set(val);
538
35
  }
539
};
540
541
class SetterCallbackWrapper
542
    : public CallbackWrapperBase<v8::PropertyCallbackInfo<void>,
543
                                 &CallbackBundle::setter> {
544
 public:
545
5
  static void Invoke(v8::Local<v8::Name> property,
546
                     v8::Local<v8::Value> value,
547
                     const v8::PropertyCallbackInfo<void>& info) {
548
5
    SetterCallbackWrapper cbwrapper(info, value);
549
5
    cbwrapper.InvokeCallback();
550
5
  }
551
552
5
  SetterCallbackWrapper(const v8::PropertyCallbackInfo<void>& cbinfo,
553
                        const v8::Local<v8::Value>& value)
554
5
      : CallbackWrapperBase(cbinfo, 1), _value(value) {}
555
556
  /*virtual*/
557
5
  void Args(napi_value* buffer, size_t buffer_length) override {
558
5
    if (buffer_length > 0) {
559
5
      buffer[0] = v8impl::JsValueFromV8LocalValue(_value);
560
561
5
      if (buffer_length > 1) {
562
        napi_value undefined = v8impl::JsValueFromV8LocalValue(
563
            v8::Undefined(_cbinfo.GetIsolate()));
564
        for (size_t i = 1; i < buffer_length; i += 1) {
565
          buffer[i] = undefined;
566
        }
567
      }
568
    }
569
5
  }
570
571
  /*virtual*/
572
  void SetReturnValue(napi_value value) override {
573
    // Ignore any value returned from a setter callback.
574
  }
575
576
 private:
577
  const v8::Local<v8::Value>& _value;
578
};
579
580
// Creates an object to be made available to the static function callback
581
// wrapper, used to retrieve the native callback function and data pointer.
582
static
583
325
v8::Local<v8::Value> CreateFunctionCallbackData(napi_env env,
584
                                                napi_callback cb,
585
                                                void* data) {
586
325
  CallbackBundle* bundle = new CallbackBundle();
587
325
  bundle->function_or_getter = cb;
588
325
  bundle->cb_data = data;
589
325
  bundle->env = env;
590
325
  v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
591
325
  bundle->BindLifecycleTo(env->isolate, cbdata);
592
593
325
  return cbdata;
594
}
595
596
// Creates an object to be made available to the static getter/setter
597
// callback wrapper, used to retrieve the native getter/setter callback
598
// function and data pointer.
599
18
inline v8::Local<v8::Value> CreateAccessorCallbackData(napi_env env,
600
                                                       napi_callback getter,
601
                                                       napi_callback setter,
602
                                                       void* data) {
603
18
  CallbackBundle* bundle = new CallbackBundle();
604
18
  bundle->function_or_getter = getter;
605
18
  bundle->setter = setter;
606
18
  bundle->cb_data = data;
607
18
  bundle->env = env;
608
18
  v8::Local<v8::Value> cbdata = v8::External::New(env->isolate, bundle);
609
18
  bundle->BindLifecycleTo(env->isolate, cbdata);
610
611
18
  return cbdata;
612
}
613
614
enum WrapType {
615
  retrievable,
616
  anonymous
617
};
618
619
template <WrapType wrap_type>
620
1023
inline napi_status Wrap(napi_env env,
621
                        napi_value js_object,
622
                        void* native_object,
623
                        napi_finalize finalize_cb,
624
                        void* finalize_hint,
625
                        napi_ref* result) {
626




2046
  NAPI_PREAMBLE(env);
627

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

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

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

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

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

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


89
  NAPI_PREAMBLE(env);
726
44
  CHECK_ARG(env, result);
727
43
  CHECK_ARG(env, cb);
728
729
42
  v8::Isolate* isolate = env->isolate;
730
  v8::Local<v8::Function> return_value;
731
42
  v8::EscapableHandleScope scope(isolate);
732
  v8::Local<v8::Value> cbdata =
733
42
      v8impl::CreateFunctionCallbackData(env, cb, callback_data);
734
735
42
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
736
737
42
  v8::Local<v8::Context> context = env->context();
738
  v8::MaybeLocal<v8::Function> maybe_function =
739
      v8::Function::New(context,
740
                        v8impl::FunctionCallbackWrapper::Invoke,
741
42
                        cbdata);
742
42
  CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure);
743
744
42
  return_value = scope.Escape(maybe_function.ToLocalChecked());
745
746
42
  if (utf8name != nullptr) {
747
    v8::Local<v8::String> name_string;
748

99
    CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
749
33
    return_value->SetName(name_string);
750
  }
751
752
84
  *result = v8impl::JsValueFromV8LocalValue(return_value);
753
754
86
  return GET_RETURN_STATUS(env);
755
}
756
757
7
napi_status napi_define_class(napi_env env,
758
                              const char* utf8name,
759
                              size_t length,
760
                              napi_callback constructor,
761
                              void* callback_data,
762
                              size_t property_count,
763
                              const napi_property_descriptor* properties,
764
                              napi_value* result) {
765


14
  NAPI_PREAMBLE(env);
766
7
  CHECK_ARG(env, result);
767
7
  CHECK_ARG(env, constructor);
768
769
7
  v8::Isolate* isolate = env->isolate;
770
771
7
  v8::EscapableHandleScope scope(isolate);
772
  v8::Local<v8::Value> cbdata =
773
7
      v8impl::CreateFunctionCallbackData(env, constructor, callback_data);
774
775
7
  RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
776
777
  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(
778
7
      isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
779
780
  v8::Local<v8::String> name_string;
781

21
  CHECK_NEW_FROM_UTF8_LEN(env, name_string, utf8name, length);
782
7
  tpl->SetClassName(name_string);
783
784
7
  size_t static_property_count = 0;
785
31
  for (size_t i = 0; i < property_count; i++) {
786
24
    const napi_property_descriptor* p = properties + i;
787
788
24
    if ((p->attributes & napi_static) != 0) {
789
      // Static properties are handled separately below.
790
4
      static_property_count++;
791
4
      continue;
792
    }
793
794
    v8::Local<v8::Name> property_name;
795
    napi_status status =
796
20
        v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
797
798
20
    if (status != napi_ok) {
799
      return napi_set_last_error(env, status);
800
    }
801
802
    v8::PropertyAttribute attributes =
803
20
        v8impl::V8PropertyAttributesFromDescriptor(p);
804
805
    // This code is similar to that in napi_define_properties(); the
806
    // difference is it applies to a template instead of an object.
807

20
    if (p->getter != nullptr || p->setter != nullptr) {
808
      v8::Local<v8::Value> cbdata = v8impl::CreateAccessorCallbackData(
809
9
        env, p->getter, p->setter, p->data);
810
811
9
      tpl->PrototypeTemplate()->SetAccessor(
812
        property_name,
813
        p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
814
        p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
815
        cbdata,
816
        v8::AccessControl::DEFAULT,
817

27
        attributes);
818
11
    } else if (p->method != nullptr) {
819
      v8::Local<v8::Value> cbdata =
820
5
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
821
822
5
      RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure);
823
824
      v8::Local<v8::FunctionTemplate> t =
825
        v8::FunctionTemplate::New(isolate,
826
          v8impl::FunctionCallbackWrapper::Invoke,
827
          cbdata,
828
5
          v8::Signature::New(isolate, tpl));
829
830
10
      tpl->PrototypeTemplate()->Set(property_name, t, attributes);
831
    } else {
832
6
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
833
12
      tpl->PrototypeTemplate()->Set(property_name, value, attributes);
834
    }
835
  }
836
837
7
  v8::Local<v8::Context> context = env->context();
838
  *result = v8impl::JsValueFromV8LocalValue(
839
21
      scope.Escape(tpl->GetFunction(context).ToLocalChecked()));
840
841
7
  if (static_property_count > 0) {
842
2
    std::vector<napi_property_descriptor> static_descriptors;
843
2
    static_descriptors.reserve(static_property_count);
844
845
22
    for (size_t i = 0; i < property_count; i++) {
846
20
      const napi_property_descriptor* p = properties + i;
847
20
      if ((p->attributes & napi_static) != 0) {
848
4
        static_descriptors.push_back(*p);
849
      }
850
    }
851
852
    napi_status status =
853
        napi_define_properties(env,
854
                               *result,
855
                               static_descriptors.size(),
856
2
                               static_descriptors.data());
857

2
    if (status != napi_ok) return status;
858
  }
859
860
14
  return GET_RETURN_STATUS(env);
861
}
862
863
4
napi_status napi_get_property_names(napi_env env,
864
                                    napi_value object,
865
                                    napi_value* result) {
866


8
  NAPI_PREAMBLE(env);
867
4
  CHECK_ARG(env, result);
868
869
4
  v8::Local<v8::Context> context = env->context();
870
  v8::Local<v8::Object> obj;
871

16
  CHECK_TO_OBJECT(env, context, obj, object);
872
873
4
  auto maybe_propertynames = obj->GetPropertyNames(context);
874
875
4
  CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure);
876
877
  *result = v8impl::JsValueFromV8LocalValue(
878
8
      maybe_propertynames.ToLocalChecked());
879
4
  return GET_RETURN_STATUS(env);
880
}
881
882
15
napi_status napi_set_property(napi_env env,
883
                              napi_value object,
884
                              napi_value key,
885
                              napi_value value) {
886


30
  NAPI_PREAMBLE(env);
887
15
  CHECK_ARG(env, key);
888
15
  CHECK_ARG(env, value);
889
890
15
  v8::Local<v8::Context> context = env->context();
891
  v8::Local<v8::Object> obj;
892
893

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


16
  NAPI_PREAMBLE(env);
909
8
  CHECK_ARG(env, result);
910
8
  CHECK_ARG(env, key);
911
912
8
  v8::Local<v8::Context> context = env->context();
913
  v8::Local<v8::Object> obj;
914
915

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


48
  NAPI_PREAMBLE(env);
931
24
  CHECK_ARG(env, key);
932
24
  CHECK_ARG(env, result);
933
934
24
  v8::Local<v8::Context> context = env->context();
935
24
  v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key);
936
  v8::Local<v8::Object> obj;
937
938

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


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

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


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

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


108
  NAPI_PREAMBLE(env);
995
54
  CHECK_ARG(env, value);
996
997
54
  v8::Local<v8::Context> context = env->context();
998
  v8::Local<v8::Object> obj;
999
1000

216
  CHECK_TO_OBJECT(env, context, obj, object);
1001
1002
  v8::Local<v8::Name> key;
1003
162
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1004
1005
54
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1006
1007
54
  v8::Maybe<bool> set_maybe = obj->Set(context, key, val);
1008
1009
108
  RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure);
1010
54
  return GET_RETURN_STATUS(env);
1011
}
1012
1013
5
napi_status napi_has_named_property(napi_env env,
1014
                                    napi_value object,
1015
                                    const char* utf8name,
1016
                                    bool* result) {
1017


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

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


2
  NAPI_PREAMBLE(env);
1041
1
  CHECK_ARG(env, result);
1042
1043
1
  v8::Local<v8::Context> context = env->context();
1044
1045
  v8::Local<v8::Name> key;
1046
3
  CHECK_NEW_FROM_UTF8(env, key, utf8name);
1047
1048
  v8::Local<v8::Object> obj;
1049
1050

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


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

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


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

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


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

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


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

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


108
  NAPI_PREAMBLE(env);
1145
54
  if (property_count > 0) {
1146
54
    CHECK_ARG(env, properties);
1147
  }
1148
1149
54
  v8::Local<v8::Context> context = env->context();
1150
1151
  v8::Local<v8::Object> obj;
1152

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

293
    if (p->getter != nullptr || p->setter != nullptr) {
1169
      v8::Local<v8::Value> cbdata = v8impl::CreateAccessorCallbackData(
1170
        env,
1171
        p->getter,
1172
        p->setter,
1173
9
        p->data);
1174
1175
      auto set_maybe = obj->SetAccessor(
1176
        context,
1177
        property_name,
1178
        p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
1179
        p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
1180
        cbdata,
1181
        v8::AccessControl::DEFAULT,
1182

18
        attributes);
1183
1184
18
      if (!set_maybe.FromMaybe(false)) {
1185
        return napi_set_last_error(env, napi_invalid_arg);
1186
9
      }
1187
284
    } else if (p->method != nullptr) {
1188
      v8::Local<v8::Value> cbdata =
1189
271
          v8impl::CreateFunctionCallbackData(env, p->method, p->data);
1190
1191
271
      CHECK_MAYBE_EMPTY(env, cbdata, napi_generic_failure);
1192
1193
      v8::MaybeLocal<v8::Function> maybe_fn =
1194
          v8::Function::New(context,
1195
                            v8impl::FunctionCallbackWrapper::Invoke,
1196
271
                            cbdata);
1197
1198
271
      CHECK_MAYBE_EMPTY(env, maybe_fn, napi_generic_failure);
1199
1200
      auto define_maybe = obj->DefineOwnProperty(
1201
271
        context, property_name, maybe_fn.ToLocalChecked(), attributes);
1202
1203
542
      if (!define_maybe.FromMaybe(false)) {
1204
        return napi_set_last_error(env, napi_generic_failure);
1205
      }
1206
    } else {
1207
13
      v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
1208
1209
      auto define_maybe =
1210
13
          obj->DefineOwnProperty(context, property_name, value, attributes);
1211
1212
26
      if (!define_maybe.FromMaybe(false)) {
1213
        return napi_set_last_error(env, napi_invalid_arg);
1214
      }
1215
    }
1216
  }
1217
1218
54
  return GET_RETURN_STATUS(env);
1219
}
1220
1221
11
napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
1222
11
  CHECK_ENV(env);
1223
11
  CHECK_ARG(env, value);
1224
11
  CHECK_ARG(env, result);
1225
1226
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1227
1228
22
  *result = val->IsArray();
1229
11
  return napi_clear_last_error(env);
1230
}
1231
1232
13
napi_status napi_get_array_length(napi_env env,
1233
                                  napi_value value,
1234
                                  uint32_t* result) {
1235


26
  NAPI_PREAMBLE(env);
1236
13
  CHECK_ARG(env, value);
1237
13
  CHECK_ARG(env, result);
1238
1239
13
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
1240
13
  RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected);
1241
1242
13
  v8::Local<v8::Array> arr = val.As<v8::Array>();
1243
26
  *result = arr->Length();
1244
1245
13
  return GET_RETURN_STATUS(env);
1246
}
1247
1248
9
napi_status napi_strict_equals(napi_env env,
1249
                               napi_value lhs,
1250
                               napi_value rhs,
1251
                               bool* result) {
1252


18
  NAPI_PREAMBLE(env);
1253
9
  CHECK_ARG(env, lhs);
1254
9
  CHECK_ARG(env, rhs);
1255
9
  CHECK_ARG(env, result);
1256
1257
9
  v8::Local<v8::Value> a = v8impl::V8LocalValueFromJsValue(lhs);
1258
9
  v8::Local<v8::Value> b = v8impl::V8LocalValueFromJsValue(rhs);
1259
1260
18
  *result = a->StrictEquals(b);
1261
9
  return GET_RETURN_STATUS(env);
1262
}
1263
1264
4
napi_status napi_get_prototype(napi_env env,
1265
                               napi_value object,
1266
                               napi_value* result) {
1267


8
  NAPI_PREAMBLE(env);
1268
4
  CHECK_ARG(env, result);
1269
1270
4
  v8::Local<v8::Context> context = env->context();
1271
1272
  v8::Local<v8::Object> obj;
1273

16
  CHECK_TO_OBJECT(env, context, obj, object);
1274
1275
4
  v8::Local<v8::Value> val = obj->GetPrototype();
1276
4
  *result = v8impl::JsValueFromV8LocalValue(val);
1277
4
  return GET_RETURN_STATUS(env);
1278
}
1279
1280
10
napi_status napi_create_object(napi_env env, napi_value* result) {
1281
10
  CHECK_ENV(env);
1282
10
  CHECK_ARG(env, result);
1283
1284
  *result = v8impl::JsValueFromV8LocalValue(
1285
20
      v8::Object::New(env->isolate));
1286
1287
10
  return napi_clear_last_error(env);
1288
}
1289
1290
1
napi_status napi_create_array(napi_env env, napi_value* result) {
1291
1
  CHECK_ENV(env);
1292
1
  CHECK_ARG(env, result);
1293
1294
  *result = v8impl::JsValueFromV8LocalValue(
1295
2
      v8::Array::New(env->isolate));
1296
1297
1
  return napi_clear_last_error(env);
1298
}
1299
1300
4
napi_status napi_create_array_with_length(napi_env env,
1301
                                          size_t length,
1302
                                          napi_value* result) {
1303
4
  CHECK_ENV(env);
1304
4
  CHECK_ARG(env, result);
1305
1306
  *result = v8impl::JsValueFromV8LocalValue(
1307
8
      v8::Array::New(env->isolate, length));
1308
1309
4
  return napi_clear_last_error(env);
1310
}
1311
1312
12
napi_status napi_create_string_latin1(napi_env env,
1313
                                      const char* str,
1314
                                      size_t length,
1315
                                      napi_value* result) {
1316
12
  CHECK_ENV(env);
1317
12
  CHECK_ARG(env, result);
1318

12
  RETURN_STATUS_IF_FALSE(env,
1319
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1320
      napi_invalid_arg);
1321
1322
11
  auto isolate = env->isolate;
1323
  auto str_maybe =
1324
      v8::String::NewFromOneByte(isolate,
1325
                                 reinterpret_cast<const uint8_t*>(str),
1326
                                 v8::NewStringType::kNormal,
1327
11
                                 length);
1328
11
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1329
1330
22
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1331
11
  return napi_clear_last_error(env);
1332
}
1333
1334
579
napi_status napi_create_string_utf8(napi_env env,
1335
                                    const char* str,
1336
                                    size_t length,
1337
                                    napi_value* result) {
1338
579
  CHECK_ENV(env);
1339
579
  CHECK_ARG(env, result);
1340

579
  RETURN_STATUS_IF_FALSE(env,
1341
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1342
      napi_invalid_arg);
1343
1344
578
  auto isolate = env->isolate;
1345
  auto str_maybe =
1346
      v8::String::NewFromUtf8(isolate,
1347
                              str,
1348
                              v8::NewStringType::kNormal,
1349
578
                              static_cast<int>(length));
1350
578
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1351
1156
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1352
578
  return napi_clear_last_error(env);
1353
}
1354
1355
14
napi_status napi_create_string_utf16(napi_env env,
1356
                                     const char16_t* str,
1357
                                     size_t length,
1358
                                     napi_value* result) {
1359
14
  CHECK_ENV(env);
1360
14
  CHECK_ARG(env, result);
1361

14
  RETURN_STATUS_IF_FALSE(env,
1362
      (length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1363
      napi_invalid_arg);
1364
1365
13
  auto isolate = env->isolate;
1366
  auto str_maybe =
1367
      v8::String::NewFromTwoByte(isolate,
1368
                                 reinterpret_cast<const uint16_t*>(str),
1369
                                 v8::NewStringType::kNormal,
1370
13
                                 length);
1371
13
  CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1372
1373
26
  *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
1374
13
  return napi_clear_last_error(env);
1375
}
1376
1377
69
napi_status napi_create_double(napi_env env,
1378
                               double value,
1379
                               napi_value* result) {
1380
69
  CHECK_ENV(env);
1381
69
  CHECK_ARG(env, result);
1382
1383
  *result = v8impl::JsValueFromV8LocalValue(
1384
138
      v8::Number::New(env->isolate, value));
1385
1386
69
  return napi_clear_last_error(env);
1387
}
1388
1389
144
napi_status napi_create_int32(napi_env env,
1390
                              int32_t value,
1391
                              napi_value* result) {
1392
144
  CHECK_ENV(env);
1393
144
  CHECK_ARG(env, result);
1394
1395
  *result = v8impl::JsValueFromV8LocalValue(
1396
288
      v8::Integer::New(env->isolate, value));
1397
1398
144
  return napi_clear_last_error(env);
1399
}
1400
1401
549
napi_status napi_create_uint32(napi_env env,
1402
                               uint32_t value,
1403
                               napi_value* result) {
1404
549
  CHECK_ENV(env);
1405
549
  CHECK_ARG(env, result);
1406
1407
  *result = v8impl::JsValueFromV8LocalValue(
1408
1098
      v8::Integer::NewFromUnsigned(env->isolate, value));
1409
1410
549
  return napi_clear_last_error(env);
1411
}
1412
1413
24
napi_status napi_create_int64(napi_env env,
1414
                              int64_t value,
1415
                              napi_value* result) {
1416
24
  CHECK_ENV(env);
1417
24
  CHECK_ARG(env, result);
1418
1419
  *result = v8impl::JsValueFromV8LocalValue(
1420
48
      v8::Number::New(env->isolate, static_cast<double>(value)));
1421
1422
24
  return napi_clear_last_error(env);
1423
}
1424
1425
9
napi_status napi_create_bigint_int64(napi_env env,
1426
                                     int64_t value,
1427
                                     napi_value* result) {
1428
9
  CHECK_ENV(env);
1429
9
  CHECK_ARG(env, result);
1430
1431
  *result = v8impl::JsValueFromV8LocalValue(
1432
18
      v8::BigInt::New(env->isolate, value));
1433
1434
9
  return napi_clear_last_error(env);
1435
}
1436
1437
6
napi_status napi_create_bigint_uint64(napi_env env,
1438
                                      uint64_t value,
1439
                                      napi_value* result) {
1440
6
  CHECK_ENV(env);
1441
6
  CHECK_ARG(env, result);
1442
1443
  *result = v8impl::JsValueFromV8LocalValue(
1444
12
      v8::BigInt::NewFromUnsigned(env->isolate, value));
1445
1446
6
  return napi_clear_last_error(env);
1447
}
1448
1449
12
napi_status napi_create_bigint_words(napi_env env,
1450
                                     int sign_bit,
1451
                                     size_t word_count,
1452
                                     const uint64_t* words,
1453
                                     napi_value* result) {
1454


24
  NAPI_PREAMBLE(env);
1455
12
  CHECK_ARG(env, words);
1456
12
  CHECK_ARG(env, result);
1457
1458
12
  v8::Local<v8::Context> context = env->context();
1459
1460
12
  if (word_count > INT_MAX) {
1461
1
    napi_throw_range_error(env, nullptr, "Maximum BigInt size exceeded");
1462
1
    return napi_set_last_error(env, napi_pending_exception);
1463
  }
1464
1465
  v8::MaybeLocal<v8::BigInt> b = v8::BigInt::NewFromWords(
1466
11
      context, sign_bit, word_count, words);
1467
1468
11
  if (try_catch.HasCaught()) {
1469
    return napi_set_last_error(env, napi_pending_exception);
1470
  } else {
1471
11
    CHECK_MAYBE_EMPTY(env, b, napi_generic_failure);
1472
22
    *result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
1473
11
    return napi_clear_last_error(env);
1474
12
  }
1475
}
1476
1477
1260
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
1478
1260
  CHECK_ENV(env);
1479
1260
  CHECK_ARG(env, result);
1480
1481
1260
  v8::Isolate* isolate = env->isolate;
1482
1483
1260
  if (value) {
1484
1434
    *result = v8impl::JsValueFromV8LocalValue(v8::True(isolate));
1485
  } else {
1486
1086
    *result = v8impl::JsValueFromV8LocalValue(v8::False(isolate));
1487
  }
1488
1489
1260
  return napi_clear_last_error(env);
1490
}
1491
1492
13
napi_status napi_create_symbol(napi_env env,
1493
                               napi_value description,
1494
                               napi_value* result) {
1495
13
  CHECK_ENV(env);
1496
13
  CHECK_ARG(env, result);
1497
1498
13
  v8::Isolate* isolate = env->isolate;
1499
1500
13
  if (description == nullptr) {
1501
6
    *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate));
1502
  } else {
1503
11
    v8::Local<v8::Value> desc = v8impl::V8LocalValueFromJsValue(description);
1504
22
    RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
1505
1506
    *result = v8impl::JsValueFromV8LocalValue(
1507
33
      v8::Symbol::New(isolate, desc.As<v8::String>()));
1508
  }
1509
1510
13
  return napi_clear_last_error(env);
1511
}
1512
1513
196
static inline napi_status set_error_code(napi_env env,
1514
                                         v8::Local<v8::Value> error,
1515
                                         napi_value code,
1516
                                         const char* code_cstring) {
1517

196
  if ((code != nullptr) || (code_cstring != nullptr)) {
1518
115
    v8::Local<v8::Context> context = env->context();
1519
115
    v8::Local<v8::Object> err_object = error.As<v8::Object>();
1520
1521
115
    v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1522
115
    if (code != nullptr) {
1523
4
      code_value = v8impl::V8LocalValueFromJsValue(code);
1524
8
      RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1525
    } else {
1526
333
      CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
1527
    }
1528
1529
    v8::Local<v8::Name> code_key;
1530
345
    CHECK_NEW_FROM_UTF8(env, code_key, "code");
1531
1532
115
    v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
1533
230
    RETURN_STATUS_IF_FALSE(env,
1534
                           set_maybe.FromMaybe(false),
1535
                           napi_generic_failure);
1536
  }
1537
196
  return napi_ok;
1538
}
1539
1540
4
napi_status napi_create_error(napi_env env,
1541
                              napi_value code,
1542
                              napi_value msg,
1543
                              napi_value* result) {
1544
4
  CHECK_ENV(env);
1545
4
  CHECK_ARG(env, msg);
1546
4
  CHECK_ARG(env, result);
1547
1548
4
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1549
8
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1550
1551
  v8::Local<v8::Value> error_obj =
1552
4
      v8::Exception::Error(message_value.As<v8::String>());
1553
4
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1554
4
  if (status != napi_ok) return status;
1555
1556
4
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1557
1558
4
  return napi_clear_last_error(env);
1559
}
1560
1561
2
napi_status napi_create_type_error(napi_env env,
1562
                                   napi_value code,
1563
                                   napi_value msg,
1564
                                   napi_value* result) {
1565
2
  CHECK_ENV(env);
1566
2
  CHECK_ARG(env, msg);
1567
2
  CHECK_ARG(env, result);
1568
1569
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1570
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1571
1572
  v8::Local<v8::Value> error_obj =
1573
2
      v8::Exception::TypeError(message_value.As<v8::String>());
1574
2
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1575
2
  if (status != napi_ok) return status;
1576
1577
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1578
1579
2
  return napi_clear_last_error(env);
1580
}
1581
1582
2
napi_status napi_create_range_error(napi_env env,
1583
                                    napi_value code,
1584
                                    napi_value msg,
1585
                                    napi_value* result) {
1586
2
  CHECK_ENV(env);
1587
2
  CHECK_ARG(env, msg);
1588
2
  CHECK_ARG(env, result);
1589
1590
2
  v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1591
4
  RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1592
1593
  v8::Local<v8::Value> error_obj =
1594
2
      v8::Exception::RangeError(message_value.As<v8::String>());
1595
2
  napi_status status = set_error_code(env, error_obj, code, nullptr);
1596
2
  if (status != napi_ok) return status;
1597
1598
2
  *result = v8impl::JsValueFromV8LocalValue(error_obj);
1599
1600
2
  return napi_clear_last_error(env);
1601
}
1602
1603
435
napi_status napi_typeof(napi_env env,
1604
                        napi_value value,
1605
                        napi_valuetype* result) {
1606
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
1607
  // JS exceptions.
1608
435
  CHECK_ENV(env);
1609
435
  CHECK_ARG(env, value);
1610
435
  CHECK_ARG(env, result);
1611
1612
435
  v8::Local<v8::Value> v = v8impl::V8LocalValueFromJsValue(value);
1613
1614
435
  if (v->IsNumber()) {
1615
141
    *result = napi_number;
1616
294
  } else if (v->IsBigInt()) {
1617
26
    *result = napi_bigint;
1618
536
  } else if (v->IsString()) {
1619
84
    *result = napi_string;
1620
184
  } else if (v->IsFunction()) {
1621
    // This test has to come before IsObject because IsFunction
1622
    // implies IsObject
1623
34
    *result = napi_function;
1624
150
  } else if (v->IsExternal()) {
1625
    // This test has to come before IsObject because IsExternal
1626
    // implies IsObject
1627
2
    *result = napi_external;
1628
148
  } else if (v->IsObject()) {
1629
135
    *result = napi_object;
1630
13
  } else if (v->IsBoolean()) {
1631
1
    *result = napi_boolean;
1632
24
  } else if (v->IsUndefined()) {
1633
2
    *result = napi_undefined;
1634
10
  } else if (v->IsSymbol()) {
1635
9
    *result = napi_symbol;
1636
2
  } else if (v->IsNull()) {
1637
1
    *result = napi_null;
1638
  } else {
1639
    // Should not get here unless V8 has added some new kind of value.
1640
    return napi_set_last_error(env, napi_invalid_arg);
1641
  }
1642
1643
435
  return napi_clear_last_error(env);
1644
}
1645
1646
120
napi_status napi_get_undefined(napi_env env, napi_value* result) {
1647
120
  CHECK_ENV(env);
1648
120
  CHECK_ARG(env, result);
1649
1650
  *result = v8impl::JsValueFromV8LocalValue(
1651
240
      v8::Undefined(env->isolate));
1652
1653
120
  return napi_clear_last_error(env);
1654
}
1655
1656
5
napi_status napi_get_null(napi_env env, napi_value* result) {
1657
5
  CHECK_ENV(env);
1658
5
  CHECK_ARG(env, result);
1659
1660
  *result = v8impl::JsValueFromV8LocalValue(
1661
10
        v8::Null(env->isolate));
1662
1663
5
  return napi_clear_last_error(env);
1664
}
1665
1666
// Gets all callback info in a single call. (Ugly, but faster.)
1667
4422
napi_status napi_get_cb_info(
1668
    napi_env env,               // [in] NAPI environment handle
1669
    napi_callback_info cbinfo,  // [in] Opaque callback-info handle
1670
    size_t* argc,      // [in-out] Specifies the size of the provided argv array
1671
                       // and receives the actual count of args.
1672
    napi_value* argv,  // [out] Array of values
1673
    napi_value* this_arg,  // [out] Receives the JS 'this' arg for the call
1674
    void** data) {         // [out] Receives the data pointer for the callback.
1675
4422
  CHECK_ENV(env);
1676
4422
  CHECK_ARG(env, cbinfo);
1677
1678
  v8impl::CallbackWrapper* info =
1679
4422
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1680
1681
4422
  if (argv != nullptr) {
1682
4393
    CHECK_ARG(env, argc);
1683
4393
    info->Args(argv, *argc);
1684
  }
1685
4422
  if (argc != nullptr) {
1686
4405
    *argc = info->ArgsLength();
1687
  }
1688
4422
  if (this_arg != nullptr) {
1689
37
    *this_arg = info->This();
1690
  }
1691
4422
  if (data != nullptr) {
1692
6
    *data = info->Data();
1693
  }
1694
1695
4422
  return napi_clear_last_error(env);
1696
}
1697
1698
8
napi_status napi_get_new_target(napi_env env,
1699
                                napi_callback_info cbinfo,
1700
                                napi_value* result) {
1701
8
  CHECK_ENV(env);
1702
8
  CHECK_ARG(env, cbinfo);
1703
8
  CHECK_ARG(env, result);
1704
1705
  v8impl::CallbackWrapper* info =
1706
8
      reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
1707
1708
8
  *result = info->GetNewTarget();
1709
8
  return napi_clear_last_error(env);
1710
}
1711
1712
642
napi_status napi_call_function(napi_env env,
1713
                               napi_value recv,
1714
                               napi_value func,
1715
                               size_t argc,
1716
                               const napi_value* argv,
1717
                               napi_value* result) {
1718


1284
  NAPI_PREAMBLE(env);
1719
640
  CHECK_ARG(env, recv);
1720
640
  if (argc > 0) {
1721
594
    CHECK_ARG(env, argv);
1722
  }
1723
1724
640
  v8::Local<v8::Context> context = env->context();
1725
1726
640
  v8::Local<v8::Value> v8recv = v8impl::V8LocalValueFromJsValue(recv);
1727
1728
  v8::Local<v8::Function> v8func;
1729

1920
  CHECK_TO_FUNCTION(env, v8func, func);
1730
1731
  auto maybe = v8func->Call(context, v8recv, argc,
1732
1280
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
1733
1734
640
  if (try_catch.HasCaught()) {
1735
6
    return napi_set_last_error(env, napi_pending_exception);
1736
  } else {
1737
634
    if (result != nullptr) {
1738
11
      CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
1739
11
      *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
1740
    }
1741
634
    return napi_clear_last_error(env);
1742
640
  }
1743
}
1744
1745
14
napi_status napi_get_global(napi_env env, napi_value* result) {
1746
14
  CHECK_ENV(env);
1747
14
  CHECK_ARG(env, result);
1748
1749
42
  *result = v8impl::JsValueFromV8LocalValue(env->context()->Global());
1750
1751
14
  return napi_clear_last_error(env);
1752
}
1753
1754
11
napi_status napi_throw(napi_env env, napi_value error) {
1755


22
  NAPI_PREAMBLE(env);
1756
11
  CHECK_ARG(env, error);
1757
1758
11
  v8::Isolate* isolate = env->isolate;
1759
1760
11
  isolate->ThrowException(v8impl::V8LocalValueFromJsValue(error));
1761
  // any VM calls after this point and before returning
1762
  // to the javascript invoker will fail
1763
11
  return napi_clear_last_error(env);
1764
}
1765
1766
78
napi_status napi_throw_error(napi_env env,
1767
                             const char* code,
1768
                             const char* msg) {
1769


156
  NAPI_PREAMBLE(env);
1770
1771
75
  v8::Isolate* isolate = env->isolate;
1772
  v8::Local<v8::String> str;
1773
225
  CHECK_NEW_FROM_UTF8(env, str, msg);
1774
1775
75
  v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1776
75
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1777
75
  if (status != napi_ok) return status;
1778
1779
75
  isolate->ThrowException(error_obj);
1780
  // any VM calls after this point and before returning
1781
  // to the javascript invoker will fail
1782
75
  return napi_clear_last_error(env);
1783
}
1784
1785
90
napi_status napi_throw_type_error(napi_env env,
1786
                                  const char* code,
1787
                                  const char* msg) {
1788


180
  NAPI_PREAMBLE(env);
1789
1790
90
  v8::Isolate* isolate = env->isolate;
1791
  v8::Local<v8::String> str;
1792
270
  CHECK_NEW_FROM_UTF8(env, str, msg);
1793
1794
90
  v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1795
90
  napi_status status = set_error_code(env, error_obj, nullptr, code);
1796
90
  if (status != napi_ok) return status;
1797
1798
90
  isolate->ThrowException(error_obj);
1799
  // any VM calls after this point and before returning
1800
  // to the javascript invoker will fail
1801
90
  return napi_clear_last_error(env);
1802
}
1803
1804
23
napi_status napi_throw_range_error(napi_env env,
1805
                                   const char* code,
1806
                                   const char* msg) {
1807


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

22
  if (sign_bit == nullptr && words == nullptr) {
1989
11
    word_count_int = big->WordCount();
1990
  } else {
1991
11
    CHECK_ARG(env, sign_bit);
1992
11
    CHECK_ARG(env, words);
1993
22
    big->ToWordsArray(sign_bit, &word_count_int, words);
1994
  }
1995
1996
22
  *word_count = word_count_int;
1997
1998
22
  return napi_clear_last_error(env);
1999
}
2000
2001
80
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) {
2002
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
2003
  // JS exceptions.
2004
80
  CHECK_ENV(env);
2005
80
  CHECK_ARG(env, value);
2006
80
  CHECK_ARG(env, result);
2007
2008
80
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2009
80
  RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected);
2010
2011
204
  *result = val.As<v8::Boolean>()->Value();
2012
2013
68
  return napi_clear_last_error(env);
2014
}
2015
2016
// Copies a JavaScript string into a LATIN-1 string buffer. The result is the
2017
// number of bytes (excluding the null terminator) copied into buf.
2018
// A sufficient buffer size should be greater than the length of string,
2019
// reserving space for null terminator.
2020
// If bufsize is insufficient, the string will be truncated and null terminated.
2021
// If buf is NULL, this method returns the length of the string (in bytes)
2022
// via the result parameter.
2023
// The result argument is optional unless buf is NULL.
2024
11
napi_status napi_get_value_string_latin1(napi_env env,
2025
                                         napi_value value,
2026
                                         char* buf,
2027
                                         size_t bufsize,
2028
                                         size_t* result) {
2029
11
  CHECK_ENV(env);
2030
11
  CHECK_ARG(env, value);
2031
2032
11
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2033
22
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2034
2035
11
  if (!buf) {
2036
    CHECK_ARG(env, result);
2037
    *result = val.As<v8::String>()->Length();
2038
  } else {
2039
    int copied =
2040
        val.As<v8::String>()->WriteOneByte(env->isolate,
2041
                                           reinterpret_cast<uint8_t*>(buf),
2042
                                           0,
2043
                                           bufsize - 1,
2044
33
                                           v8::String::NO_NULL_TERMINATION);
2045
2046
11
    buf[copied] = '\0';
2047
11
    if (result != nullptr) {
2048
11
      *result = copied;
2049
    }
2050
  }
2051
2052
11
  return napi_clear_last_error(env);
2053
}
2054
2055
// Copies a JavaScript string into a UTF-8 string buffer. The result is the
2056
// number of bytes (excluding the null terminator) copied into buf.
2057
// A sufficient buffer size should be greater than the length of string,
2058
// reserving space for null terminator.
2059
// If bufsize is insufficient, the string will be truncated and null terminated.
2060
// If buf is NULL, this method returns the length of the string (in bytes)
2061
// via the result parameter.
2062
// The result argument is optional unless buf is NULL.
2063
38
napi_status napi_get_value_string_utf8(napi_env env,
2064
                                       napi_value value,
2065
                                       char* buf,
2066
                                       size_t bufsize,
2067
                                       size_t* result) {
2068
38
  CHECK_ENV(env);
2069
38
  CHECK_ARG(env, value);
2070
2071
38
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2072
76
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2073
2074
29
  if (!buf) {
2075
7
    CHECK_ARG(env, result);
2076
21
    *result = val.As<v8::String>()->Utf8Length(env->isolate);
2077
  } else {
2078
    int copied = val.As<v8::String>()->WriteUtf8(
2079
        env->isolate,
2080
        buf,
2081
        bufsize - 1,
2082
        nullptr,
2083
66
        v8::String::REPLACE_INVALID_UTF8 | v8::String::NO_NULL_TERMINATION);
2084
2085
22
    buf[copied] = '\0';
2086
22
    if (result != nullptr) {
2087
20
      *result = copied;
2088
    }
2089
  }
2090
2091
29
  return napi_clear_last_error(env);
2092
}
2093
2094
// Copies a JavaScript string into a UTF-16 string buffer. The result is the
2095
// number of 2-byte code units (excluding the null terminator) copied into buf.
2096
// A sufficient buffer size should be greater than the length of string,
2097
// reserving space for null terminator.
2098
// If bufsize is insufficient, the string will be truncated and null terminated.
2099
// If buf is NULL, this method returns the length of the string (in 2-byte
2100
// code units) via the result parameter.
2101
// The result argument is optional unless buf is NULL.
2102
20
napi_status napi_get_value_string_utf16(napi_env env,
2103
                                        napi_value value,
2104
                                        char16_t* buf,
2105
                                        size_t bufsize,
2106
                                        size_t* result) {
2107
20
  CHECK_ENV(env);
2108
20
  CHECK_ARG(env, value);
2109
2110
20
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2111
40
  RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected);
2112
2113
20
  if (!buf) {
2114
7
    CHECK_ARG(env, result);
2115
    // V8 assumes UTF-16 length is the same as the number of characters.
2116
21
    *result = val.As<v8::String>()->Length();
2117
  } else {
2118
    int copied = val.As<v8::String>()->Write(env->isolate,
2119
                                             reinterpret_cast<uint16_t*>(buf),
2120
                                             0,
2121
                                             bufsize - 1,
2122
39
                                             v8::String::NO_NULL_TERMINATION);
2123
2124
13
    buf[copied] = '\0';
2125
13
    if (result != nullptr) {
2126
13
      *result = copied;
2127
    }
2128
  }
2129
2130
20
  return napi_clear_last_error(env);
2131
}
2132
2133
15
napi_status napi_coerce_to_object(napi_env env,
2134
                                  napi_value value,
2135
                                  napi_value* result) {
2136


30
  NAPI_PREAMBLE(env);
2137
15
  CHECK_ARG(env, value);
2138
15
  CHECK_ARG(env, result);
2139
2140
15
  v8::Local<v8::Context> context = env->context();
2141
  v8::Local<v8::Object> obj;
2142

60
  CHECK_TO_OBJECT(env, context, obj, value);
2143
2144
30
  *result = v8impl::JsValueFromV8LocalValue(obj);
2145
15
  return GET_RETURN_STATUS(env);
2146
}
2147
2148
14
napi_status napi_coerce_to_bool(napi_env env,
2149
                                napi_value value,
2150
                                napi_value* result) {
2151


28
  NAPI_PREAMBLE(env);
2152
14
  CHECK_ARG(env, value);
2153
14
  CHECK_ARG(env, result);
2154
2155
14
  v8::Isolate* isolate = env->isolate;
2156
  v8::Local<v8::Boolean> b =
2157
28
    v8impl::V8LocalValueFromJsValue(value)->ToBoolean(isolate);
2158
28
  *result = v8impl::JsValueFromV8LocalValue(b);
2159
14
  return GET_RETURN_STATUS(env);
2160
}
2161
2162
15
napi_status napi_coerce_to_number(napi_env env,
2163
                                  napi_value value,
2164
                                  napi_value* result) {
2165


30
  NAPI_PREAMBLE(env);
2166
15
  CHECK_ARG(env, value);
2167
15
  CHECK_ARG(env, result);
2168
2169
15
  v8::Local<v8::Context> context = env->context();
2170
  v8::Local<v8::Number> num;
2171
2172

60
  CHECK_TO_NUMBER(env, context, num, value);
2173
2174
28
  *result = v8impl::JsValueFromV8LocalValue(num);
2175
14
  return GET_RETURN_STATUS(env);
2176
}
2177
2178
14
napi_status napi_coerce_to_string(napi_env env,
2179
                                  napi_value value,
2180
                                  napi_value* result) {
2181


28
  NAPI_PREAMBLE(env);
2182
14
  CHECK_ARG(env, value);
2183
14
  CHECK_ARG(env, result);
2184
2185
14
  v8::Local<v8::Context> context = env->context();
2186
  v8::Local<v8::String> str;
2187
2188

56
  CHECK_TO_STRING(env, context, str, value);
2189
2190
26
  *result = v8impl::JsValueFromV8LocalValue(str);
2191
13
  return GET_RETURN_STATUS(env);
2192
}
2193
2194
1019
napi_status napi_wrap(napi_env env,
2195
                      napi_value js_object,
2196
                      void* native_object,
2197
                      napi_finalize finalize_cb,
2198
                      void* finalize_hint,
2199
                      napi_ref* result) {
2200
  return v8impl::Wrap<v8impl::retrievable>(env,
2201
                                           js_object,
2202
                                           native_object,
2203
                                           finalize_cb,
2204
                                           finalize_hint,
2205
1019
                                           result);
2206
}
2207
2208
24
napi_status napi_unwrap(napi_env env, napi_value obj, void** result) {
2209
24
  return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap);
2210
}
2211
2212
3
napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) {
2213
3
  return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap);
2214
}
2215
2216
7
napi_status napi_create_external(napi_env env,
2217
                                 void* data,
2218
                                 napi_finalize finalize_cb,
2219
                                 void* finalize_hint,
2220
                                 napi_value* result) {
2221


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

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


14
  NAPI_PREAMBLE(env);
2443
7
  CHECK_ARG(env, constructor);
2444
7
  if (argc > 0) {
2445
7
    CHECK_ARG(env, argv);
2446
  }
2447
7
  CHECK_ARG(env, result);
2448
2449
7
  v8::Local<v8::Context> context = env->context();
2450
2451
  v8::Local<v8::Function> ctor;
2452

21
  CHECK_TO_FUNCTION(env, ctor, constructor);
2453
2454
  auto maybe = ctor->NewInstance(context, argc,
2455
14
    reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
2456
2457
7
  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);
2458
2459
14
  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
2460
7
  return GET_RETURN_STATUS(env);
2461
}
2462
2463
2278
napi_status napi_instanceof(napi_env env,
2464
                            napi_value object,
2465
                            napi_value constructor,
2466
                            bool* result) {
2467


4556
  NAPI_PREAMBLE(env);
2468
2278
  CHECK_ARG(env, object);
2469
2278
  CHECK_ARG(env, result);
2470
2471
2278
  *result = false;
2472
2473
  v8::Local<v8::Object> ctor;
2474
2278
  v8::Local<v8::Context> context = env->context();
2475
2476

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


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


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


66
  NAPI_PREAMBLE(env);
2627
33
  CHECK_ARG(env, arraybuffer);
2628
33
  CHECK_ARG(env, result);
2629
2630
33
  v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
2631
33
  RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
2632
2633
33
  v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
2634
  v8::Local<v8::TypedArray> typedArray;
2635
2636



33
  switch (type) {
2637
    case napi_int8_array:
2638
8
      CREATE_TYPED_ARRAY(
2639
          env, Int8Array, 1, buffer, byte_offset, length, typedArray);
2640
2
      break;
2641
    case napi_uint8_array:
2642
8
      CREATE_TYPED_ARRAY(
2643
          env, Uint8Array, 1, buffer, byte_offset, length, typedArray);
2644
2
      break;
2645
    case napi_uint8_clamped_array:
2646
5
      CREATE_TYPED_ARRAY(
2647
          env, Uint8ClampedArray, 1, buffer, byte_offset, length, typedArray);
2648
1
      break;
2649
    case napi_int16_array:
2650

6
      CREATE_TYPED_ARRAY(
2651
          env, Int16Array, 2, buffer, byte_offset, length, typedArray);
2652
1
      break;
2653
    case napi_uint16_array:
2654

6
      CREATE_TYPED_ARRAY(
2655
          env, Uint16Array, 2, buffer, byte_offset, length, typedArray);
2656
1
      break;
2657
    case napi_int32_array:
2658

6
      CREATE_TYPED_ARRAY(
2659
          env, Int32Array, 4, buffer, byte_offset, length, typedArray);
2660
1
      break;
2661
    case napi_uint32_array:
2662

6
      CREATE_TYPED_ARRAY(
2663
          env, Uint32Array, 4, buffer, byte_offset, length, typedArray);
2664
1
      break;
2665
    case napi_float32_array:
2666

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

9
      CREATE_TYPED_ARRAY(
2671
          env, Float64Array, 8, buffer, byte_offset, length, typedArray);
2672
2
      break;
2673
    case napi_bigint64_array:
2674

6
      CREATE_TYPED_ARRAY(
2675
          env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
2676
1
      break;
2677
    case napi_biguint64_array:
2678

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


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


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


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


2
  NAPI_PREAMBLE(env);
2905
1
  CHECK_ARG(env, value);
2906
1
  CHECK_ARG(env, result);
2907
2908
1
  v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
2909
1
  RETURN_STATUS_IF_FALSE(env, val->IsDate(), napi_date_expected);
2910
2911
1
  v8::Local<v8::Date> date = val.As<v8::Date>();
2912
2
  *result = date->ValueOf();
2913
2914
1
  return GET_RETURN_STATUS(env);
2915
}
2916
2917
2
napi_status napi_run_script(napi_env env,
2918
                            napi_value script,
2919
                            napi_value* result) {
2920


4
  NAPI_PREAMBLE(env);
2921
2
  CHECK_ARG(env, script);
2922
2
  CHECK_ARG(env, result);
2923
2924
2
  v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue(script);
2925
2926
4
  if (!v8_script->IsString()) {
2927
1
    return napi_set_last_error(env, napi_string_expected);
2928
  }
2929
2930
1
  v8::Local<v8::Context> context = env->context();
2931
2932
  auto maybe_script = v8::Script::Compile(context,
2933
1
      v8::Local<v8::String>::Cast(v8_script));
2934
1
  CHECK_MAYBE_EMPTY(env, maybe_script, napi_generic_failure);
2935
2936
  auto script_result =
2937
2
      maybe_script.ToLocalChecked()->Run(context);
2938
1
  CHECK_MAYBE_EMPTY(env, script_result, napi_generic_failure);
2939
2940
2
  *result = v8impl::JsValueFromV8LocalValue(script_result.ToLocalChecked());
2941
1
  return GET_RETURN_STATUS(env);
2942
}
2943
2944
4
napi_status napi_add_finalizer(napi_env env,
2945
                               napi_value js_object,
2946
                               void* native_object,
2947
                               napi_finalize finalize_cb,
2948
                               void* finalize_hint,
2949
                               napi_ref* result) {
2950
  return v8impl::Wrap<v8impl::anonymous>(env,
2951
                                         js_object,
2952
                                         native_object,
2953
                                         finalize_cb,
2954
                                         finalize_hint,
2955
4
                                         result);
2956
}
2957
2958
1
napi_status napi_adjust_external_memory(napi_env env,
2959
                                        int64_t change_in_bytes,
2960
                                        int64_t* adjusted_value) {
2961
1
  CHECK_ENV(env);
2962
1
  CHECK_ARG(env, adjusted_value);
2963
2964
  *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory(
2965
2
      change_in_bytes);
2966
2967
1
  return napi_clear_last_error(env);
2968
}