1 /*
2  * Copyright (c) 2021-2023 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 <functional>
22 #include <memory>
23 #include <shared_mutex>
24 #include <string>
25 #include <vector>
26 #include <map>
27 #include <sys/time.h>
28 
29 #include "ecmascript/base/aligned_struct.h"
30 #include "ecmascript/base/config.h"
31 #include "ecmascript/mem/mem_common.h"
32 #include "ecmascript/napi/include/jsnapi_expo.h"
33 #ifndef NDEBUG
34 #include "libpandabase/utils/debug.h"
35 #endif
36 
37 #ifdef ERROR
38 #undef ERROR
39 #endif
40 
41 namespace panda {
42 class JSNApiHelper;
43 class EscapeLocalScope;
44 class PromiseRejectInfo;
45 template<typename T>
46 class CopyableGlobal;
47 template<typename T>
48 class Global;
49 class JSNApi;
50 template<typename T>
51 class Local;
52 class JSValueRef;
53 class PrimitiveRef;
54 class ArrayRef;
55 class BigIntRef;
56 class StringRef;
57 class ObjectRef;
58 class FunctionRef;
59 class NumberRef;
60 class BooleanRef;
61 class NativePointerRef;
62 class JsiRuntimeCallInfo;
63 namespace test {
64 class JSNApiTests;
65 }  // namespace test
66 class BufferRef;
67 namespace ecmascript {
68 class EcmaVM;
69 class JSTaggedValue;
70 class EcmaContext;
71 class JSRuntimeOptions;
72 class JSThread;
73 struct EcmaRuntimeCallInfo;
74 static constexpr uint32_t DEFAULT_GC_POOL_SIZE = 256_MB;
75 namespace base {
76 template<size_t ElementAlign, typename... Ts>
77 struct AlignedStruct;
78 struct AlignedPointer;
79 }
80 }  // namespace ecmascript
81 
82 using WeakRefClearCallBack = void (*)(void *);
83 using EcmaVM = ecmascript::EcmaVM;
84 using EcmaContext = ecmascript::EcmaContext;
85 using JSThread = ecmascript::JSThread;
86 using JSTaggedType = uint64_t;
87 using ConcurrentCallback = void (*)(Local<JSValueRef> result, bool success, void *taskInfo, void *data);
88 using SourceMapTranslateCallback = std::function<bool(std::string& url, int& line, int& column)>;
89 using DeviceDisconnectCallback = std::function<bool()>;
90 
91 static constexpr size_t DEFAULT_GC_THREAD_NUM = 7;
92 static constexpr size_t DEFAULT_LONG_PAUSE_TIME = 40;
93 
94 class ECMA_PUBLIC_API RegExpRef : public ObjectRef {
95 public:
96     Local<StringRef> GetOriginalSource(const EcmaVM *vm);
97     std::string GetOriginalFlags(const EcmaVM *vm);
98     Local<JSValueRef> IsGlobal(const EcmaVM *vm);
99     Local<JSValueRef> IsIgnoreCase(const EcmaVM *vm);
100     Local<JSValueRef> IsMultiline(const EcmaVM *vm);
101     Local<JSValueRef> IsDotAll(const EcmaVM *vm);
102     Local<JSValueRef> IsUtf16(const EcmaVM *vm);
103     Local<JSValueRef> IsStick(const EcmaVM *vm);
104 };
105 
106 class ECMA_PUBLIC_API GeneratorFunctionRef : public ObjectRef {
107 public:
108     bool IsGenerator(const EcmaVM *vm);
109 };
110 
111 class ECMA_PUBLIC_API GeneratorObjectRef : public ObjectRef {
112 public:
113     Local<JSValueRef> GetGeneratorState(const EcmaVM *vm);
114     Local<JSValueRef> GetGeneratorFunction(const EcmaVM *vm);
115     Local<JSValueRef> GetGeneratorReceiver(const EcmaVM *vm);
116 };
117 
118 class ECMA_PUBLIC_API CollatorRef : public ObjectRef {
119 public:
120     Local<JSValueRef> GetCompareFunction(const EcmaVM *vm);
121 };
122 
123 class ECMA_PUBLIC_API DataTimeFormatRef : public ObjectRef {
124 public:
125     Local<JSValueRef> GetFormatFunction(const EcmaVM *vm);
126 };
127 
128 class ECMA_PUBLIC_API NumberFormatRef : public ObjectRef {
129 public:
130     Local<JSValueRef> GetFormatFunction(const EcmaVM *vm);
131 };
132 
133 class ECMA_PUBLIC_API JSON {
134 public:
135     static Local<JSValueRef> Parse(const EcmaVM *vm, Local<StringRef> string);
136     static Local<JSValueRef> Stringify(const EcmaVM *vm, Local<JSValueRef> json);
137 };
138 
139 using LOG_PRINT = int (*)(int id, int level, const char *tag, const char *fmt, const char *message);
140 
141 class ECMA_PUBLIC_API RuntimeOption {
142 public:
143     enum class ECMA_PUBLIC_API GC_TYPE : uint8_t { EPSILON, GEN_GC, STW };
144     enum class ECMA_PUBLIC_API LOG_LEVEL : uint8_t {
145         DEBUG = 3,
146         INFO = 4,
147         WARN = 5,
148         ERROR = 6,
149         FATAL = 7,
150         FOLLOW = 100, // if hilog enabled follow hilog, otherwise use INFO level
151     };
152 
153     // This enum should follow the same value as defined in the BMS subsystem.
154     // Refer to the specification in aot-guide_zh.md.
155     enum class AOTCompileStatus {
156         NOT_COMPILED = 0,
157         COMPILE_SUCCESS = 1,
158         COMPILE_FAILED = 2,
159         COMPILE_CRASH = 3,
160         COMPILE_CANCELLED = 4,
161     };
162 
SetGcType(GC_TYPE type)163     void SetGcType(GC_TYPE type)
164     {
165         gcType_ = type;
166     }
167 
SetGcPoolSize(uint32_t size)168     void SetGcPoolSize(uint32_t size)
169     {
170         gcPoolSize_ = size;
171     }
172 
SetLogLevel(LOG_LEVEL logLevel)173     void SetLogLevel(LOG_LEVEL logLevel)
174     {
175         logLevel_ = logLevel;
176     }
177 
SetLogBufPrint(LOG_PRINT out)178     void SetLogBufPrint(LOG_PRINT out)
179     {
180         logBufPrint_ = out;
181     }
182 
SetDebuggerLibraryPath(const std::string &path)183     void SetDebuggerLibraryPath(const std::string &path)
184     {
185         debuggerLibraryPath_ = path;
186     }
187 
SetEnableArkTools(bool value)188     void SetEnableArkTools(bool value)
189     {
190         enableArkTools_ = value;
191     }
192 
SetEnableCpuprofiler(bool value)193     void SetEnableCpuprofiler(bool value)
194     {
195         enableCpuprofiler_ = value;
196     }
197 
SetArkProperties(int prop)198     void SetArkProperties(int prop)
199     {
200         arkProperties_ = prop;
201     }
202 
SetArkBundleName(const std::string &bundleName)203     void SetArkBundleName(const std::string &bundleName)
204     {
205         arkBundleName_ = bundleName;
206     }
207 
SetMemConfigProperty(std::string configProperty)208     void SetMemConfigProperty(std::string configProperty)
209     {
210         memConfigProperty_ = configProperty;
211     }
212 
SetGcThreadNum(size_t num)213     void SetGcThreadNum(size_t num)
214     {
215         gcThreadNum_ = num;
216     }
217 
SetLongPauseTime(size_t time)218     void SetLongPauseTime(size_t time)
219     {
220         longPauseTime_ = time;
221     }
222 
SetEnableAsmInterpreter(bool value)223     void SetEnableAsmInterpreter(bool value)
224     {
225         enableAsmInterpreter_ = value;
226     }
227 
SetEnableBuiltinsLazy(bool value)228     void SetEnableBuiltinsLazy(bool value)
229     {
230         enableBuiltinsLazy_ = value;
231     }
232 
SetAsmOpcodeDisableRange(const std::string &value)233     void SetAsmOpcodeDisableRange(const std::string &value)
234     {
235         asmOpcodeDisableRange_ = value;
236     }
237 
SetIsWorker()238     void SetIsWorker()
239     {
240         isWorker_ = true;
241     }
242 
GetIsWorker() const243     bool GetIsWorker() const
244     {
245         return isWorker_;
246     }
247 
SetIsRestrictedWorker(bool isRestrictedWorker)248     inline void SetIsRestrictedWorker(bool isRestrictedWorker)
249     {
250         isRestrictedWorker_ = isRestrictedWorker;
251     }
252 
GetIsRestrictedWorker() const253     bool GetIsRestrictedWorker() const
254     {
255         return isRestrictedWorker_;
256     }
257 
SetBundleName(const std::string &value)258     void SetBundleName(const std::string &value)
259     {
260         bundleName_ = value;
261     }
262 
SetEnableAOT(bool value)263     void SetEnableAOT(bool value)
264     {
265         enableAOT_ = value;
266     }
267 
SetAnDir(const std::string &value)268     void SetAnDir(const std::string &value)
269     {
270         anDir_ = value;
271     }
272 
SetEnableProfile(bool value)273     void SetEnableProfile(bool value)
274     {
275         enableProfile_ = value;
276     }
277 
278     // Valid only when SetEnableProfile(true)
SetProfileDir(const std::string &value)279     void SetProfileDir(const std::string &value)
280     {
281         profileDir_ = value;
282     }
283 
SetEnableJIT(bool value)284     void SetEnableJIT(bool value)
285     {
286         enableFastJIT_ = value;
287     }
288 
SetEnableBaselineJIT(bool value)289     void SetEnableBaselineJIT(bool value)
290     {
291         enableBaselineJIT_ = value;
292     }
293 
SetAOTCompileStatusMap(const std::map<std::string, int32_t> &value)294     void SetAOTCompileStatusMap(const std::map<std::string, int32_t> &value)
295     {
296         aotCompileStatusMap_ = value;
297     }
298 
GetAOTCompileStatusMap() const299     const std::map<std::string, int32_t> &GetAOTCompileStatusMap() const
300     {
301         return aotCompileStatusMap_;
302     }
303 
304 private:
GetGcType() const305     std::string GetGcType() const
306     {
307         std::string gcType;
308         switch (gcType_) {
309             case GC_TYPE::GEN_GC:
310                 gcType = "gen-gc";
311                 break;
312             case GC_TYPE::STW:
313                 gcType = "stw";
314                 break;
315             case GC_TYPE::EPSILON:
316                 gcType = "epsilon";
317                 break;
318             default:
319                 break;
320         }
321         return gcType;
322     }
323 
GetLogLevel() const324     LOG_LEVEL GetLogLevel() const
325     {
326         return logLevel_;
327     }
328 
GetGcPoolSize() const329     uint32_t GetGcPoolSize() const
330     {
331         return gcPoolSize_;
332     }
333 
GetLogBufPrint() const334     LOG_PRINT GetLogBufPrint() const
335     {
336         return logBufPrint_;
337     }
338 
GetDebuggerLibraryPath() const339     std::string GetDebuggerLibraryPath() const
340     {
341         return debuggerLibraryPath_;
342     }
343 
GetEnableArkTools() const344     bool GetEnableArkTools() const
345     {
346         return enableArkTools_;
347     }
348 
GetEnableCpuprofiler() const349     bool GetEnableCpuprofiler() const
350     {
351         return enableCpuprofiler_;
352     }
353 
GetArkProperties() const354     int GetArkProperties() const
355     {
356         return arkProperties_;
357     }
358 
GetArkBundleName() const359     std::string GetArkBundleName() const
360     {
361         return arkBundleName_;
362     }
363 
GetMemConfigProperty() const364     std::string GetMemConfigProperty() const
365     {
366         return memConfigProperty_;
367     }
368 
GetGcThreadNum() const369     size_t GetGcThreadNum() const
370     {
371         return gcThreadNum_;
372     }
373 
GetLongPauseTime() const374     size_t GetLongPauseTime() const
375     {
376         return longPauseTime_;
377     }
378 
GetEnableAsmInterpreter() const379     bool GetEnableAsmInterpreter() const
380     {
381         return enableAsmInterpreter_;
382     }
383 
GetEnableBuiltinsLazy() const384     bool GetEnableBuiltinsLazy() const
385     {
386         return enableBuiltinsLazy_;
387     }
388 
GetAsmOpcodeDisableRange() const389     std::string GetAsmOpcodeDisableRange() const
390     {
391         return asmOpcodeDisableRange_;
392     }
393 
GetBundleName() const394     std::string GetBundleName() const
395     {
396         return bundleName_;
397     }
398 
GetEnableAOT() const399     bool GetEnableAOT() const
400     {
401         return enableAOT_;
402     }
403 
GetAnDir() const404     std::string GetAnDir() const
405     {
406         return anDir_;
407     }
408 
GetEnableProfile() const409     bool GetEnableProfile() const
410     {
411         return enableProfile_;
412     }
413 
GetProfileDir() const414     std::string GetProfileDir() const
415     {
416         return profileDir_;
417     }
418 
GetEnableJIT() const419     bool GetEnableJIT() const
420     {
421         return enableFastJIT_;
422     }
423 
GetEnableBaselineJIT() const424     bool GetEnableBaselineJIT() const
425     {
426         return enableBaselineJIT_;
427     }
428 
429     GC_TYPE gcType_ = GC_TYPE::EPSILON;
430     LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG;
431     uint32_t gcPoolSize_ = ecmascript::DEFAULT_GC_POOL_SIZE;
432     LOG_PRINT logBufPrint_ {nullptr};
433     std::string debuggerLibraryPath_ {};
434     bool enableArkTools_ {false};
435     bool enableCpuprofiler_ {false};
436     int arkProperties_ {-1};
437     std::string arkBundleName_ = {""};
438     std::string memConfigProperty_ = {""};
439     size_t gcThreadNum_ {DEFAULT_GC_THREAD_NUM};
440     size_t longPauseTime_ {DEFAULT_LONG_PAUSE_TIME};
441     bool enableAsmInterpreter_ {true};
442     bool enableBuiltinsLazy_ {true};
443     bool isWorker_ {false};
444     bool isRestrictedWorker_ {false};
445     std::string asmOpcodeDisableRange_ {""};
446     std::string bundleName_ {};
447     bool enableAOT_ {false};
448     std::string anDir_ {};
449     bool enableProfile_ {false};
450     std::string profileDir_ {};
451     bool enableFastJIT_ {false};
452     bool enableBaselineJIT_ {false};
453     std::map<std::string, int32_t> aotCompileStatusMap_;
454     friend JSNApi;
455 };
456 
457 template<typename T>
458 template<typename S>
Global(const EcmaVM *vm, const Local<S> &current)459 Global<T>::Global(const EcmaVM *vm, const Local<S> &current) : vm_(vm)
460 {
461     if (!current.IsEmpty()) {
462         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
463     }
464 }
465 
466 template<typename T>
467 template<typename S>
Global(const EcmaVM *vm, const Global<S> &current)468 Global<T>::Global(const EcmaVM *vm, const Global<S> &current) : vm_(vm)
469 {
470     if (!current.IsEmpty()) {
471         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
472     }
473 }
474 
475 template<typename T>
CopyableGlobal(const EcmaVM *vm, const Local<T> &current)476 CopyableGlobal<T>::CopyableGlobal(const EcmaVM *vm, const Local<T> &current) : vm_(vm)
477 {
478     if (!current.IsEmpty()) {
479         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
480     }
481 }
482 
483 template<typename T>
484 template<typename S>
CopyableGlobal(const EcmaVM *vm, const Local<S> &current)485 CopyableGlobal<T>::CopyableGlobal(const EcmaVM *vm, const Local<S> &current) : vm_(vm)
486 {
487     if (!current.IsEmpty()) {
488         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
489     }
490 }
491 
492 template<typename T>
Copy(const CopyableGlobal &that)493 void CopyableGlobal<T>::Copy(const CopyableGlobal &that)
494 {
495     Free();
496     vm_ = that.vm_;
497     if (!that.IsEmpty()) {
498         ECMA_ASSERT(vm_ != nullptr);
499         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*that));
500     }
501 }
502 
503 template<typename T>
504 template<typename S>
Copy(const CopyableGlobal<S> &that)505 void CopyableGlobal<T>::Copy(const CopyableGlobal<S> &that)
506 {
507     Free();
508     vm_ = that.GetEcmaVM();
509     if (!that.IsEmpty()) {
510         ECMA_ASSERT(vm_ != nullptr);
511         address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*that));
512     }
513 }
514 
515 template<typename T>
Move(CopyableGlobal &that)516 void CopyableGlobal<T>::Move(CopyableGlobal &that)
517 {
518     Free();
519     vm_ = that.vm_;
520     address_ = that.address_;
521     that.vm_ = nullptr;
522     that.address_ = 0U;
523 }
524 
525 template<typename T>
Free()526 inline void CopyableGlobal<T>::Free()
527 {
528     if (!IsEmpty()) {
529         JSNApi::DisposeGlobalHandleAddr(vm_, address_);
530         address_ = 0U;
531     }
532 }
533 
534 template <typename T>
SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack, WeakRefClearCallBack nativeFinalizeCallback)535 void CopyableGlobal<T>::SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack,
536                                         WeakRefClearCallBack nativeFinalizeCallback)
537 {
538     address_ = JSNApi::SetWeakCallback(vm_, address_, ref, freeGlobalCallBack, nativeFinalizeCallback);
539 }
540 
541 template<typename T>
SetWeak()542 void CopyableGlobal<T>::SetWeak()
543 {
544     address_ = JSNApi::SetWeak(vm_, address_);
545 }
546 
547 template<typename T>
ClearWeak()548 void CopyableGlobal<T>::ClearWeak()
549 {
550     address_ = JSNApi::ClearWeak(vm_, address_);
551 }
552 
553 template<typename T>
IsWeak() const554 bool CopyableGlobal<T>::IsWeak() const
555 {
556     return JSNApi::IsWeak(vm_, address_);
557 }
558 
559 template<typename T>
Update(const Global &that)560 void Global<T>::Update(const Global &that)
561 {
562     if (address_ != 0) {
563         JSNApi::DisposeGlobalHandleAddr(vm_, address_);
564     }
565     address_ = that.address_;
566     vm_ = that.vm_;
567 }
568 
569 template<typename T>
FreeGlobalHandleAddr()570 void Global<T>::FreeGlobalHandleAddr()
571 {
572     if (address_ == 0) {
573         return;
574     }
575     JSNApi::DisposeGlobalHandleAddr(vm_, address_);
576     address_ = 0;
577 }
578 
579 template<typename T>
SetWeak()580 void Global<T>::SetWeak()
581 {
582     address_ = JSNApi::SetWeak(vm_, address_);
583 }
584 
585 template <typename T>
SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack, WeakRefClearCallBack nativeFinalizeCallback)586 void Global<T>::SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack,
587                                 WeakRefClearCallBack nativeFinalizeCallback)
588 {
589     address_ = JSNApi::SetWeakCallback(vm_, address_, ref, freeGlobalCallBack, nativeFinalizeCallback);
590 }
591 
592 template<typename T>
ClearWeak()593 void Global<T>::ClearWeak()
594 {
595     address_ = JSNApi::ClearWeak(vm_, address_);
596 }
597 
598 template<typename T>
IsWeak() const599 bool Global<T>::IsWeak() const
600 {
601     return JSNApi::IsWeak(vm_, address_);
602 }
603 
604 // ---------------------------------- Local --------------------------------------------
605 template<typename T>
Local(const EcmaVM *vm, const CopyableGlobal<T> &current)606 Local<T>::Local(const EcmaVM *vm, const CopyableGlobal<T> &current)
607 {
608     address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
609 }
610 
611 template<typename T>
Local(const EcmaVM *vm, const Global<T> &current)612 Local<T>::Local(const EcmaVM *vm, const Global<T> &current)
613 {
614     address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
615 }
616 }  // namespace panda
617 
618 #undef ECMA_ASSERT
619 #undef ECMA_PUBLIC_API
620 #endif  // ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H
621