• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H
17 #define ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H
18 
19 #include <cassert>
20 #include <cstdint>
21 #include <string>
22 #include <vector>
23 
24 #include "ecmascript/common.h"
25 #include "libpandabase/macros.h"
26 
27 namespace panda {
28 class JSNApiHelper;
29 class EscapeLocalScope;
30 class PromiseRejectInfo;
31 template<typename T>
32 class Global;
33 class JSNApi;
34 class PrimitiveRef;
35 class ArrayRef;
36 class StringRef;
37 class ObjectRef;
38 class FunctionRef;
39 class NumberRef;
40 class BooleanRef;
41 class NativePointerRef;
42 namespace test {
43 class JSNApiTests;
44 }  // namespace test
45 
46 namespace ecmascript {
47 class EcmaVM;
48 class JSRuntimeOptions;
49 }  // namespace ecmascript
50 
51 using Deleter = void (*)(void *nativePointer, void *data);
52 using EcmaVM = ecmascript::EcmaVM;
53 using JSTaggedType = uint64_t;
54 
55 static constexpr uint32_t DEFAULT_GC_POOL_SIZE = 256 * 1024 * 1024;
56 
57 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
58 #define ECMA_DISALLOW_COPY(className)      \
59     className(const className &) = delete; \
60     className &operator=(const className &) = delete
61 
62 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
63 #define ECMA_DISALLOW_MOVE(className) \
64     className(className &&) = delete; \
65     className &operator=(className &&) = delete
66 
67 template<typename T>
68 class PUBLIC_API Local {  // NOLINT(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
69 public:
70     inline Local() = default;
71 
72     template<typename S>
Local(const Local<S> & current)73     inline Local(const Local<S> &current) : address_(reinterpret_cast<uintptr_t>(*current))
74     {
75         // Check
76     }
77 
78     Local(const EcmaVM *vm, const Global<T> &current);
79 
80     ~Local() = default;
81 
82     inline T *operator*() const
83     {
84         return GetAddress();
85     }
86 
87     inline T *operator->() const
88     {
89         return GetAddress();
90     }
91 
IsEmpty()92     inline bool IsEmpty() const
93     {
94         return GetAddress() == nullptr;
95     }
96 
CheckException()97     inline bool CheckException() const
98     {
99         return IsEmpty() || GetAddress()->IsException();
100     }
101 
IsException()102     inline bool IsException() const
103     {
104         return !IsEmpty() && GetAddress()->IsException();
105     }
106 
IsNull()107     inline bool IsNull() const
108     {
109         return IsEmpty() || GetAddress()->IsHole();
110     }
111 
112 private:
Local(uintptr_t addr)113     explicit inline Local(uintptr_t addr) : address_(addr) {}
GetAddress()114     inline T *GetAddress() const
115     {
116         return reinterpret_cast<T *>(address_);
117     };
118     uintptr_t address_ = 0U;
119     friend JSNApiHelper;
120     friend EscapeLocalScope;
121 };
122 
123 template<typename T>
124 class PUBLIC_API Global {  // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions
125 public:
126     inline Global() = default;
127 
Global(const Global & that)128     inline Global(const Global &that)
129     {
130         Update(that);
131     }
132 
133     inline Global &operator=(const Global &that)
134     {
135         Update(that);
136         return *this;
137     }
138 
Global(Global && that)139     inline Global(Global &&that)
140     {
141         Update(that);
142     }
143 
144     inline Global &operator=(Global &&that)
145     {
146         Update(that);
147         return *this;
148     }
149     // Non-empty initial value.
150     explicit Global(const EcmaVM *vm);
151 
152     template<typename S>
153     Global(const EcmaVM *vm, const Local<S> &current);
154     template<typename S>
155     Global(const EcmaVM *vm, const Global<S> &current);
156     ~Global() = default;
157 
ToLocal(const EcmaVM * vm)158     Local<T> ToLocal(const EcmaVM *vm) const
159     {
160         return Local<T>(vm, *this);
161     }
162 
Empty()163     void Empty()
164     {
165         address_ = 0;
166     }
167 
168     // This method must be called before Global is released.
169     void FreeGlobalHandleAddr();
170 
171     inline T *operator*() const
172     {
173         return GetAddress();
174     }
175 
176     inline T *operator->() const
177     {
178         return GetAddress();
179     }
180 
IsEmpty()181     inline bool IsEmpty() const
182     {
183         return GetAddress() == nullptr;
184     }
185 
CheckException()186     inline bool CheckException() const
187     {
188         return IsEmpty() || GetAddress()->IsException();
189     }
190 
191     void SetWeak();
192 
193     void ClearWeak();
194 
195     bool IsWeak() const;
196 
197 private:
GetAddress()198     inline T *GetAddress() const
199     {
200         return reinterpret_cast<T *>(address_);
201     };
202     inline void Update(const Global &that);
203     uintptr_t address_ = 0U;
204     const EcmaVM *vm_ {nullptr};
205 };
206 
207 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
208 class PUBLIC_API LocalScope {
209 public:
210     explicit LocalScope(const EcmaVM *vm);
211     virtual ~LocalScope();
212 
213 protected:
214     inline LocalScope(const EcmaVM *vm, JSTaggedType value);
215 
216 private:
217     void *prevNext_ = nullptr;
218     void *prevEnd_ = nullptr;
219     int prevHandleStorageIndex_ {-1};
220     void *thread_ = nullptr;
221 };
222 
223 class PUBLIC_API EscapeLocalScope final : public LocalScope {
224 public:
225     explicit EscapeLocalScope(const EcmaVM *vm);
226     ~EscapeLocalScope() override = default;
227 
228     ECMA_DISALLOW_COPY(EscapeLocalScope);
229     ECMA_DISALLOW_MOVE(EscapeLocalScope);
230 
231     template<typename T>
Escape(Local<T> current)232     inline Local<T> Escape(Local<T> current)
233     {
234         ASSERT(!alreadyEscape_);
235         alreadyEscape_ = true;
236         *(reinterpret_cast<T *>(escapeHandle_)) = **current;
237         return Local<T>(escapeHandle_);
238     }
239 
240 private:
241     bool alreadyEscape_ = false;
242     uintptr_t escapeHandle_ = 0U;
243 };
244 
245 class PUBLIC_API JSExecutionScope {
246 public:
247     explicit JSExecutionScope(const EcmaVM *vm);
248     ~JSExecutionScope();
249     ECMA_DISALLOW_COPY(JSExecutionScope);
250     ECMA_DISALLOW_MOVE(JSExecutionScope);
251 
252 private:
253     void *last_current_thread_ = nullptr;
254     bool is_revert_ = false;
255 };
256 
257 class PUBLIC_API JSValueRef {
258 public:
259     static Local<PrimitiveRef> Undefined(const EcmaVM *vm);
260     static Local<PrimitiveRef> Null(const EcmaVM *vm);
261     static Local<PrimitiveRef> True(const EcmaVM *vm);
262     static Local<PrimitiveRef> False(const EcmaVM *vm);
263     static Local<JSValueRef> Exception(const EcmaVM *vm);
264 
265     bool BooleaValue();
266     int64_t IntegerValue(const EcmaVM *vm);
267     uint32_t Uint32Value(const EcmaVM *vm);
268     int32_t Int32Value(const EcmaVM *vm);
269 
270     Local<NumberRef> ToNumber(const EcmaVM *vm);
271     Local<BooleanRef> ToBoolean(const EcmaVM *vm);
272     Local<StringRef> ToString(const EcmaVM *vm);
273     Local<ObjectRef> ToObject(const EcmaVM *vm);
274     Local<NativePointerRef> ToNativePointer(const EcmaVM *vm);
275 
276     bool IsUndefined();
277     bool IsNull();
278     bool IsHole();
279     bool IsTrue();
280     bool IsFalse();
281     bool IsNumber();
282     bool IsBigInt();
283     bool IsInt();
284     bool WithinInt32();
285     bool IsBoolean();
286     bool IsString();
287     bool IsSymbol();
288     bool IsObject();
289     bool IsArray(const EcmaVM *vm);
290     bool IsConstructor();
291     bool IsFunction();
292     bool IsProxy();
293     bool IsException();
294     bool IsPromise();
295     bool IsDataView();
296     bool IsTypedArray();
297     bool IsNativePointer();
298     bool IsDate();
299     bool IsError();
300     bool IsMap();
301     bool IsSet();
302     bool IsWeakMap();
303     bool IsWeakSet();
304     bool IsRegExp();
305     bool IsArrayIterator();
306     bool IsStringIterator();
307     bool IsSetIterator();
308     bool IsMapIterator();
309     bool IsArrayBuffer();
310     bool IsUint8Array();
311     bool IsInt8Array();
312     bool IsUint8ClampedArray();
313     bool IsInt16Array();
314     bool IsUint16Array();
315     bool IsInt32Array();
316     bool IsUint32Array();
317     bool IsFloat32Array();
318     bool IsFloat64Array();
319     bool IsJSPrimitiveRef();
320     bool IsJSPrimitiveNumber();
321     bool IsJSPrimitiveInt();
322     bool IsJSPrimitiveBoolean();
323     bool IsJSPrimitiveString();
324 
325     bool IsGeneratorObject();
326     bool IsJSPrimitiveSymbol();
327 
328     bool IsArgumentsObject();
329     bool IsGeneratorFunction();
330     bool IsAsyncFunction();
331 
332     bool IsStrictEquals(const EcmaVM *vm, Local<JSValueRef> value);
333     Local<StringRef> Typeof(const EcmaVM *vm);
334     bool InstanceOf(const EcmaVM *vm, Local<JSValueRef> value);
335 
336 private:
337     JSTaggedType value_;
338     friend JSNApi;
339     template<typename T>
340     friend class Global;
341     template<typename T>
342     friend class Local;
343 };
344 
345 class PUBLIC_API PrimitiveRef : public JSValueRef {
346 };
347 
348 class PUBLIC_API IntegerRef : public PrimitiveRef {
349 public:
350     static Local<IntegerRef> New(const EcmaVM *vm, int input);
351     static Local<IntegerRef> NewFromUnsigned(const EcmaVM *vm, unsigned int input);
352     int Value();
353 };
354 
355 class PUBLIC_API NumberRef : public PrimitiveRef {
356 public:
357     static Local<NumberRef> New(const EcmaVM *vm, double input);
358     static Local<NumberRef> New(const EcmaVM *vm, int32_t input);
359     static Local<NumberRef> New(const EcmaVM *vm, uint32_t input);
360     static Local<NumberRef> New(const EcmaVM *vm, int64_t input);
361 
362     double Value();
363 };
364 
365 class PUBLIC_API BigIntRef : public PrimitiveRef {
366 public:
367     static Local<BigIntRef> New(const EcmaVM *vm, uint64_t input);
368     static Local<BigIntRef> New(const EcmaVM *vm, int64_t input);
369     static Local<JSValueRef> CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words);
370     void BigIntToInt64(const EcmaVM *vm, int64_t *cValue, bool *lossless);
371     void BigIntToUint64(const EcmaVM *vm, uint64_t *cValue, bool *lossless);
372     void GetWordsArray(bool* signBit, size_t wordCount, uint64_t* words);
373     uint32_t GetWordsArraySize();
374 };
375 
376 class PUBLIC_API BooleanRef : public PrimitiveRef {
377 public:
378     static Local<BooleanRef> New(const EcmaVM *vm, bool input);
379     bool Value();
380 };
381 
382 class PUBLIC_API StringRef : public PrimitiveRef {
383 public:
Cast(JSValueRef * value)384     static inline StringRef *Cast(JSValueRef *value)
385     {
386         // check
387         return static_cast<StringRef *>(value);
388     }
389     static Local<StringRef> NewFromUtf8(const EcmaVM *vm, const char *utf8, int length = -1);
390     std::string ToString();
391     int32_t Length();
392     int32_t Utf8Length();
393     int WriteUtf8(char *buffer, int length);
394 };
395 
396 class PUBLIC_API SymbolRef : public PrimitiveRef {
397 public:
398     static Local<SymbolRef> New(const EcmaVM *vm, Local<StringRef> description);
399     Local<StringRef> GetDescription(const EcmaVM *vm);
400 };
401 
402 using NativePointerCallback = void (*)(void* value, void* hint);
403 class PUBLIC_API NativePointerRef : public JSValueRef {
404 public:
405     static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer);
406     static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack,
407                                        void *data);
408     void *Value();
409 };
410 
411 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
412 class PUBLIC_API PropertyAttribute {
413 public:
Default()414     static PropertyAttribute Default()
415     {
416         return PropertyAttribute();
417     }
418     PropertyAttribute() = default;
PropertyAttribute(Local<JSValueRef> value,bool w,bool e,bool c)419     PropertyAttribute(Local<JSValueRef> value, bool w, bool e, bool c)
420         : value_(value),
421           writable_(w),
422           enumerable_(e),
423           configurable_(c),
424           hasWritable_(true),
425           hasEnumerable_(true),
426           hasConfigurable_(true)
427     {}
428     ~PropertyAttribute() = default;
429 
IsWritable()430     bool IsWritable() const
431     {
432         return writable_;
433     }
SetWritable(bool flag)434     void SetWritable(bool flag)
435     {
436         writable_ = flag;
437         hasWritable_ = true;
438     }
IsEnumerable()439     bool IsEnumerable() const
440     {
441         return enumerable_;
442     }
SetEnumerable(bool flag)443     void SetEnumerable(bool flag)
444     {
445         enumerable_ = flag;
446         hasEnumerable_ = true;
447     }
IsConfigurable()448     bool IsConfigurable() const
449     {
450         return configurable_;
451     }
SetConfigurable(bool flag)452     void SetConfigurable(bool flag)
453     {
454         configurable_ = flag;
455         hasConfigurable_ = true;
456     }
HasWritable()457     bool HasWritable() const
458     {
459         return hasWritable_;
460     }
HasConfigurable()461     bool HasConfigurable() const
462     {
463         return hasConfigurable_;
464     }
HasEnumerable()465     bool HasEnumerable() const
466     {
467         return hasEnumerable_;
468     }
GetValue(const EcmaVM * vm)469     Local<JSValueRef> GetValue(const EcmaVM *vm) const
470     {
471         if (value_.IsEmpty()) {
472             return JSValueRef::Undefined(vm);
473         }
474         return value_;
475     }
SetValue(Local<JSValueRef> value)476     void SetValue(Local<JSValueRef> value)
477     {
478         value_ = value;
479     }
HasValue()480     inline bool HasValue() const
481     {
482         return !value_.IsEmpty();
483     }
GetGetter(const EcmaVM * vm)484     Local<JSValueRef> GetGetter(const EcmaVM *vm) const
485     {
486         if (getter_.IsEmpty()) {
487             return JSValueRef::Undefined(vm);
488         }
489         return getter_;
490     }
SetGetter(Local<JSValueRef> value)491     void SetGetter(Local<JSValueRef> value)
492     {
493         getter_ = value;
494     }
HasGetter()495     bool HasGetter() const
496     {
497         return !getter_.IsEmpty();
498     }
GetSetter(const EcmaVM * vm)499     Local<JSValueRef> GetSetter(const EcmaVM *vm) const
500     {
501         if (setter_.IsEmpty()) {
502             return JSValueRef::Undefined(vm);
503         }
504         return setter_;
505     }
SetSetter(Local<JSValueRef> value)506     void SetSetter(Local<JSValueRef> value)
507     {
508         setter_ = value;
509     }
HasSetter()510     bool HasSetter() const
511     {
512         return !setter_.IsEmpty();
513     }
514 
515 private:
516     Local<JSValueRef> value_;
517     Local<JSValueRef> getter_;
518     Local<JSValueRef> setter_;
519     bool writable_ = false;
520     bool enumerable_ = false;
521     bool configurable_ = false;
522     bool hasWritable_ = false;
523     bool hasEnumerable_ = false;
524     bool hasConfigurable_ = false;
525 };
526 
527 class PUBLIC_API ObjectRef : public JSValueRef {
528 public:
Cast(JSValueRef * value)529     static inline ObjectRef *Cast(JSValueRef *value)
530     {
531         // check
532         return static_cast<ObjectRef *>(value);
533     }
534     static Local<ObjectRef> New(const EcmaVM *vm);
535     bool Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value);
536     bool Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value);
537     bool SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter,
538                              Local<FunctionRef> setter, PropertyAttribute attribute = PropertyAttribute::Default());
539     Local<JSValueRef> Get(const EcmaVM *vm, Local<JSValueRef> key);
540     Local<JSValueRef> Get(const EcmaVM *vm, int32_t key);
541 
542     bool GetOwnProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute &property);
543     Local<ArrayRef> GetOwnPropertyNames(const EcmaVM *vm);
544     Local<ArrayRef> GetOwnEnumerablePropertyNames(const EcmaVM *vm);
545     Local<JSValueRef> GetPrototype(const EcmaVM *vm);
546 
547     bool DefineProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute attribute);
548 
549     bool Has(const EcmaVM *vm, Local<JSValueRef> key);
550     bool Has(const EcmaVM *vm, uint32_t key);
551 
552     bool Delete(const EcmaVM *vm, Local<JSValueRef> key);
553     bool Delete(const EcmaVM *vm, uint32_t key);
554 
555     void SetNativePointerFieldCount(int32_t count);
556     int32_t GetNativePointerFieldCount();
557     void *GetNativePointerField(int32_t index);
558     void SetNativePointerField(int32_t index,
559                                void *nativePointer = nullptr,
560                                NativePointerCallback callBack = nullptr,
561                                void *data = nullptr);
562 };
563 
564 using FunctionCallback = Local<JSValueRef> (*)(EcmaVM *, Local<JSValueRef>,
565                                                const Local<JSValueRef>[],  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
566                                                int32_t, void *);
567 using FunctionCallbackWithNewTarget =
568     Local<JSValueRef> (*)(EcmaVM *, Local<JSValueRef>, Local<JSValueRef>, const Local<JSValueRef>[], int32_t, void *);
569 class PUBLIC_API FunctionRef : public ObjectRef {
570 public:
571     static Local<FunctionRef> New(EcmaVM *vm, FunctionCallback nativeFunc, void *data);
572     static Local<FunctionRef> New(EcmaVM *vm, FunctionCallback nativeFunc, Deleter deleter, void *data);
573     static Local<FunctionRef> NewWithProperty(EcmaVM *vm, FunctionCallback nativeFunc, void *data);
574     static Local<FunctionRef> NewClassFunction(EcmaVM *vm, FunctionCallbackWithNewTarget nativeFunc, Deleter deleter,
575         void *data);
576     Local<JSValueRef> Call(const EcmaVM *vm, Local<JSValueRef> thisObj, const Local<JSValueRef> argv[],
577         int32_t length);
578     Local<JSValueRef> Constructor(const EcmaVM *vm, const Local<JSValueRef> argv[], int32_t length);
579     Local<JSValueRef> GetFunctionPrototype(const EcmaVM *vm);
580     // Inherit Prototype from parent function
581     // set this.Prototype.__proto__ to parent.Prototype, set this.__proto__ to parent function
582     bool Inherit(const EcmaVM *vm, Local<FunctionRef> parent);
583     void SetName(const EcmaVM *vm, Local<StringRef> name);
584     Local<StringRef> GetName(const EcmaVM *vm);
585     bool IsNative(const EcmaVM *vm);
586 };
587 
588 class PUBLIC_API ArrayRef : public ObjectRef {
589 public:
590     static Local<ArrayRef> New(const EcmaVM *vm, int32_t length = 0);
591     int32_t Length(const EcmaVM *vm);
592     static bool SetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value);
593     static Local<JSValueRef> GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index);
594 };
595 
596 class PUBLIC_API PromiseRef : public ObjectRef {
597 public:
598     Local<PromiseRef> Catch(const EcmaVM *vm, Local<FunctionRef> handler);
599     Local<PromiseRef> Then(const EcmaVM *vm, Local<FunctionRef> handler);
600     Local<PromiseRef> Then(const EcmaVM *vm, Local<FunctionRef> onFulfilled, Local<FunctionRef> onRejected);
601 };
602 
603 class PUBLIC_API PromiseCapabilityRef : public ObjectRef {
604 public:
605     static Local<PromiseCapabilityRef> New(const EcmaVM *vm);
606     bool Resolve(const EcmaVM *vm, Local<JSValueRef> value);
607     bool Reject(const EcmaVM *vm, Local<JSValueRef> reason);
608     Local<PromiseRef> GetPromise(const EcmaVM *vm);
609 };
610 
611 class PUBLIC_API ArrayBufferRef : public ObjectRef {
612 public:
613     static Local<ArrayBufferRef> New(const EcmaVM *vm, int32_t length);
614     static Local<ArrayBufferRef> New(const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter,
615                                      void *data);
616 
617     int32_t ByteLength(const EcmaVM *vm);
618     void *GetBuffer();
619 };
620 
621 class PUBLIC_API DataViewRef : public ObjectRef {
622 public:
623     static Local<DataViewRef> New(const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset,
624                                   uint32_t byteLength);
625     uint32_t ByteLength();
626     uint32_t ByteOffset();
627     Local<ArrayBufferRef> GetArrayBuffer(const EcmaVM *vm);
628 };
629 
630 class PUBLIC_API TypedArrayRef : public ObjectRef {
631 public:
632     int32_t ByteLength(const EcmaVM *vm);
633     int32_t ByteOffset(const EcmaVM *vm);
634     int32_t ArrayLength(const EcmaVM *vm);
635     Local<ArrayBufferRef> GetArrayBuffer(const EcmaVM *vm);
636 };
637 
638 class PUBLIC_API Int8ArrayRef : public TypedArrayRef {
639 public:
640     static Local<Int8ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
641 };
642 
643 class PUBLIC_API Uint8ArrayRef : public TypedArrayRef {
644 public:
645     static Local<Uint8ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
646 };
647 
648 class PUBLIC_API Uint8ClampedArrayRef : public TypedArrayRef {
649 public:
650     static Local<Uint8ClampedArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
651                                            int32_t length);
652 };
653 
654 class PUBLIC_API Int16ArrayRef : public TypedArrayRef {
655 public:
656     static Local<Int16ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
657 };
658 
659 class PUBLIC_API Uint16ArrayRef : public TypedArrayRef {
660 public:
661     static Local<Uint16ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
662                                      int32_t length);
663 };
664 
665 class PUBLIC_API Int32ArrayRef : public TypedArrayRef {
666 public:
667     static Local<Int32ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
668 };
669 
670 class PUBLIC_API Uint32ArrayRef : public TypedArrayRef {
671 public:
672     static Local<Uint32ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
673                                      int32_t length);
674 };
675 
676 class PUBLIC_API Float32ArrayRef : public TypedArrayRef {
677 public:
678     static Local<Float32ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
679                                       int32_t length);
680 };
681 
682 class PUBLIC_API Float64ArrayRef : public TypedArrayRef {
683 public:
684     static Local<Float64ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
685                                       int32_t length);
686 };
687 
688 class PUBLIC_API RegExpRef : public ObjectRef {
689 public:
690     Local<StringRef> GetOriginalSource(const EcmaVM *vm);
691 };
692 
693 class PUBLIC_API DateRef : public ObjectRef {
694 public:
695     static Local<DateRef> New(const EcmaVM *vm, double time);
696     Local<StringRef> ToString(const EcmaVM *vm);
697     double GetTime();
698 };
699 
700 class PUBLIC_API MapRef : public ObjectRef {
701 public:
702     int32_t GetSize();
703 };
704 
705 class PUBLIC_API SetRef : public ObjectRef {
706 public:
707     int32_t GetSize();
708 };
709 
710 class PUBLIC_API JSON {
711 public:
712     static Local<JSValueRef> Parse(const EcmaVM *vm, Local<StringRef> string);
713     static Local<JSValueRef> Stringify(const EcmaVM *vm, Local<JSValueRef> json);
714 };
715 
716 class PUBLIC_API Exception {
717 public:
718     static Local<JSValueRef> Error(const EcmaVM *vm, Local<StringRef> message);
719     static Local<JSValueRef> RangeError(const EcmaVM *vm, Local<StringRef> message);
720     static Local<JSValueRef> ReferenceError(const EcmaVM *vm, Local<StringRef> message);
721     static Local<JSValueRef> SyntaxError(const EcmaVM *vm, Local<StringRef> message);
722     static Local<JSValueRef> TypeError(const EcmaVM *vm, Local<StringRef> message);
723     static Local<JSValueRef> EvalError(const EcmaVM *vm, Local<StringRef> message);
724 };
725 
726 using LOG_PRINT = int (*)(int id, int level, const char *tag, const char *fmt, const char *message);
727 
728 class PUBLIC_API RuntimeOption {
729 public:
730     enum class PUBLIC_API GC_TYPE : uint8_t { EPSILON, GEN_GC, STW };
731     enum class PUBLIC_API LOG_LEVEL : uint8_t {
732         DEBUG = 3,
733         INFO = 4,
734         WARN = 5,
735         ERROR = 6,
736         FATAL = 7,
737     };
738 
SetGcType(GC_TYPE type)739     void SetGcType(GC_TYPE type)
740     {
741         gcType_ = type;
742     }
743 
SetGcPoolSize(uint32_t size)744     void SetGcPoolSize(uint32_t size)
745     {
746         gcPoolSize_ = size;
747     }
748 
SetLogLevel(LOG_LEVEL logLevel)749     void SetLogLevel(LOG_LEVEL logLevel)
750     {
751         logLevel_ = logLevel;
752     }
753 
SetLogBufPrint(LOG_PRINT out)754     void SetLogBufPrint(LOG_PRINT out)
755     {
756         logBufPrint_ = out;
757     }
758 
SetDebuggerLibraryPath(const std::string & path)759     void SetDebuggerLibraryPath(const std::string &path)
760     {
761         debuggerLibraryPath_ = path;
762     }
763 
SetEnableArkTools(bool value)764     void SetEnableArkTools(bool value) {
765         enableArkTools_ = value;
766     }
767 
SetEnableCpuprofiler(bool value)768     void SetEnableCpuprofiler(bool value) {
769         enableCpuprofiler_ = value;
770     }
771 
SetArkProperties(int prop)772     void SetArkProperties(int prop) {
773         arkProperties_ = prop;
774     }
775 
776 private:
GetGcType()777     std::string GetGcType() const
778     {
779         std::string gcType;
780         switch (gcType_) {
781             case GC_TYPE::GEN_GC:
782                 gcType = "gen-gc";
783                 break;
784             case GC_TYPE::STW:
785                 gcType = "stw";
786                 break;
787             case GC_TYPE::EPSILON:
788                 gcType = "epsilon";
789                 break;
790             default:
791                 UNREACHABLE();
792         }
793         return gcType;
794     }
795 
GetLogLevel()796     std::string GetLogLevel() const
797     {
798         std::string logLevel;
799         switch (logLevel_) {
800             case LOG_LEVEL::INFO:
801             case LOG_LEVEL::WARN:
802                 logLevel = "info";
803                 break;
804             case LOG_LEVEL::ERROR:
805                 logLevel = "error";
806                 break;
807             case LOG_LEVEL::FATAL:
808                 logLevel = "fatal";
809                 break;
810             case LOG_LEVEL::DEBUG:
811             default:
812                 logLevel = "debug";
813                 break;
814         }
815 
816         return logLevel;
817     }
818 
GetGcPoolSize()819     uint32_t GetGcPoolSize() const
820     {
821         return gcPoolSize_;
822     }
823 
GetLogBufPrint()824     LOG_PRINT GetLogBufPrint() const
825     {
826         return logBufPrint_;
827     }
828 
GetDebuggerLibraryPath()829     std::string GetDebuggerLibraryPath() const
830     {
831         return debuggerLibraryPath_;
832     }
833 
GetEnableArkTools()834     bool GetEnableArkTools() const
835     {
836         return enableArkTools_;
837     }
838 
GetEnableCpuprofiler()839     bool GetEnableCpuprofiler() const
840     {
841         return enableCpuprofiler_;
842     }
843 
GetArkProperties()844     int GetArkProperties() const
845     {
846         return arkProperties_;
847     }
848 
849     GC_TYPE gcType_ = GC_TYPE::EPSILON;
850     LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG;
851     uint32_t gcPoolSize_ = DEFAULT_GC_POOL_SIZE;
852     LOG_PRINT logBufPrint_ {nullptr};
853     std::string debuggerLibraryPath_ {};
854     bool enableArkTools_ {false};
855     bool enableCpuprofiler_ {false};
856     int arkProperties_ {-1};
857     friend JSNApi;
858 };
859 
860 class PUBLIC_API PromiseRejectInfo {
861 public:
862     enum class PUBLIC_API PROMISE_REJECTION_EVENT : uint32_t { REJECT = 0, HANDLE };
863     PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason,
864                       PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data);
~PromiseRejectInfo()865     ~PromiseRejectInfo() {}
866     Local<JSValueRef> GetPromise() const;
867     Local<JSValueRef> GetReason() const;
868     PromiseRejectInfo::PROMISE_REJECTION_EVENT GetOperation() const;
869     void* GetData() const;
870 
871 private:
872     Local<JSValueRef> promise_ {};
873     Local<JSValueRef> reason_ {};
874     PROMISE_REJECTION_EVENT operation_ = PROMISE_REJECTION_EVENT::REJECT;
875     void* data_ {nullptr};
876 };
877 
878 class PUBLIC_API JSNApi {
879 public:
880     using DebuggerPostTask = std::function<void(std::function<void()>&&)>;
881 
882     // JSVM
883     enum class PUBLIC_API TRIGGER_GC_TYPE : uint8_t { SEMI_GC, OLD_GC, FULL_GC };
884     static EcmaVM *CreateJSVM(const RuntimeOption &option);
885     static void DestroyJSVM(EcmaVM *ecmaVm);
886 
887     // JS code
888     static bool Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry);
889     static bool Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry,
890                         const std::string &filename = "");
891     static bool ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file);
892     static Local<ObjectRef> GetExportObject(EcmaVM *vm, const std::string &file, const std::string &itemName);
893 
894     // ObjectRef Operation
895     static Local<ObjectRef> GetGlobalObject(const EcmaVM *vm);
896     static void ExecutePendingJob(const EcmaVM *vm);
897 
898     // Memory
899     static void TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType = TRIGGER_GC_TYPE::SEMI_GC);
900     // Exception
901     static void ThrowException(const EcmaVM *vm, Local<JSValueRef> error);
902     static Local<ObjectRef> GetAndClearUncaughtException(const EcmaVM *vm);
903     static Local<ObjectRef> GetUncaughtException(const EcmaVM *vm);
904     static void EnableUserUncaughtErrorHandler(EcmaVM *vm);
905 
906     static bool StartDebugger(const char *libraryPath, EcmaVM *vm, bool isDebugMode, int32_t instanceId = 0,
907         const DebuggerPostTask &debuggerPostTask = {});
908     static bool StopDebugger(EcmaVM *vm);
909     // Serialize & Deserialize.
910     static void* SerializeValue(const EcmaVM *vm, Local<JSValueRef> data, Local<JSValueRef> transfer);
911     static Local<JSValueRef> DeserializeValue(const EcmaVM *vm, void* recoder);
912     static void DeleteSerializationData(void *data);
913     static void SetOptions(const ecmascript::JSRuntimeOptions &options);
914     static void SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data);
915     static void SetHostEnqueueJob(const EcmaVM* vm, Local<JSValueRef> cb);
916     // profile generator
917     static void StartCpuProfiler(const EcmaVM *vm, const std::string &fileName);
918     static void StopCpuProfiler();
919     static void ResumeVM(const EcmaVM *vm);
920     static bool SuspendVM(const EcmaVM *vm);
921     static bool IsSuspended(const EcmaVM *vm);
922     static bool CheckSafepoint(const EcmaVM *vm);
923 
924 private:
925     static int vmCount;
926     static bool CreateRuntime(const RuntimeOption &option);
927     static bool DestroyRuntime();
928 
929     static uintptr_t GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress);
930     static uintptr_t GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress);
931     static uintptr_t SetWeak(const EcmaVM *vm, uintptr_t localAddress);
932     static uintptr_t ClearWeak(const EcmaVM *vm, uintptr_t localAddress);
933     static bool IsWeak(const EcmaVM *vm, uintptr_t localAddress);
934     static void DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr);
935     template<typename T>
936     friend class Global;
937     template<typename T>
938     friend class Local;
939     friend class test::JSNApiTests;
940 };
941 
942 
943 template<typename T>
944 template<typename S>
Global(const EcmaVM * vm,const Local<S> & current)945 Global<T>::Global(const EcmaVM *vm, const Local<S> &current) : vm_(vm)
946 {
947     if (!current.IsEmpty()) {
948         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
949     }
950 }
951 
952 template<typename T>
953 template<typename S>
Global(const EcmaVM * vm,const Global<S> & current)954 Global<T>::Global(const EcmaVM *vm, const Global<S> &current) : vm_(vm)
955 {
956     if (!current.IsEmpty()) {
957         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
958     }
959 }
960 
961 template<typename T>
Update(const Global & that)962 void Global<T>::Update(const Global &that)
963 {
964     if (address_ != 0) {
965         JSNApi::DisposeGlobalHandleAddr(vm_, address_);
966     }
967     address_ = that.address_;
968     vm_ = that.vm_;
969 }
970 
971 template<typename T>
FreeGlobalHandleAddr()972 void Global<T>::FreeGlobalHandleAddr()
973 {
974     if (address_ == 0) {
975         return;
976     }
977     JSNApi::DisposeGlobalHandleAddr(vm_, address_);
978     address_ = 0;
979 }
980 
981 template<typename T>
SetWeak()982 void Global<T>::SetWeak()
983 {
984     address_ = JSNApi::SetWeak(vm_, address_);
985 }
986 
987 template<typename T>
ClearWeak()988 void Global<T>::ClearWeak()
989 {
990     address_ = JSNApi::ClearWeak(vm_, address_);
991 }
992 
993 template<typename T>
IsWeak()994 bool Global<T>::IsWeak() const
995 {
996     return JSNApi::IsWeak(vm_, address_);
997 }
998 
999 // ---------------------------------- Local --------------------------------------------
1000 template<typename T>
Local(const EcmaVM * vm,const Global<T> & current)1001 Local<T>::Local(const EcmaVM *vm, const Global<T> &current)
1002 {
1003     address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
1004 }
1005 }  // namespace panda
1006 #endif  // ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H
1007