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
41namespace panda {
42class JSNApiHelper;
43class EscapeLocalScope;
44class PromiseRejectInfo;
45template<typename T>
46class CopyableGlobal;
47template<typename T>
48class Global;
49class JSNApi;
50template<typename T>
51class Local;
52class JSValueRef;
53class PrimitiveRef;
54class ArrayRef;
55class BigIntRef;
56class StringRef;
57class ObjectRef;
58class FunctionRef;
59class NumberRef;
60class BooleanRef;
61class NativePointerRef;
62class JsiRuntimeCallInfo;
63namespace test {
64class JSNApiTests;
65}  // namespace test
66class BufferRef;
67namespace ecmascript {
68class EcmaVM;
69class JSTaggedValue;
70class EcmaContext;
71class JSRuntimeOptions;
72class JSThread;
73struct EcmaRuntimeCallInfo;
74static constexpr uint32_t DEFAULT_GC_POOL_SIZE = 256_MB;
75namespace base {
76template<size_t ElementAlign, typename... Ts>
77struct AlignedStruct;
78struct AlignedPointer;
79}
80}  // namespace ecmascript
81
82using WeakRefClearCallBack = void (*)(void *);
83using EcmaVM = ecmascript::EcmaVM;
84using EcmaContext = ecmascript::EcmaContext;
85using JSThread = ecmascript::JSThread;
86using JSTaggedType = uint64_t;
87using ConcurrentCallback = void (*)(Local<JSValueRef> result, bool success, void *taskInfo, void *data);
88using SourceMapTranslateCallback = std::function<bool(std::string& url, int& line, int& column)>;
89using DeviceDisconnectCallback = std::function<bool()>;
90
91static constexpr size_t DEFAULT_GC_THREAD_NUM = 7;
92static constexpr size_t DEFAULT_LONG_PAUSE_TIME = 40;
93
94class ECMA_PUBLIC_API RegExpRef : public ObjectRef {
95public:
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
106class ECMA_PUBLIC_API GeneratorFunctionRef : public ObjectRef {
107public:
108    bool IsGenerator(const EcmaVM *vm);
109};
110
111class ECMA_PUBLIC_API GeneratorObjectRef : public ObjectRef {
112public:
113    Local<JSValueRef> GetGeneratorState(const EcmaVM *vm);
114    Local<JSValueRef> GetGeneratorFunction(const EcmaVM *vm);
115    Local<JSValueRef> GetGeneratorReceiver(const EcmaVM *vm);
116};
117
118class ECMA_PUBLIC_API CollatorRef : public ObjectRef {
119public:
120    Local<JSValueRef> GetCompareFunction(const EcmaVM *vm);
121};
122
123class ECMA_PUBLIC_API DataTimeFormatRef : public ObjectRef {
124public:
125    Local<JSValueRef> GetFormatFunction(const EcmaVM *vm);
126};
127
128class ECMA_PUBLIC_API NumberFormatRef : public ObjectRef {
129public:
130    Local<JSValueRef> GetFormatFunction(const EcmaVM *vm);
131};
132
133class ECMA_PUBLIC_API JSON {
134public:
135    static Local<JSValueRef> Parse(const EcmaVM *vm, Local<StringRef> string);
136    static Local<JSValueRef> Stringify(const EcmaVM *vm, Local<JSValueRef> json);
137};
138
139using LOG_PRINT = int (*)(int id, int level, const char *tag, const char *fmt, const char *message);
140
141class ECMA_PUBLIC_API RuntimeOption {
142public:
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
163    void SetGcType(GC_TYPE type)
164    {
165        gcType_ = type;
166    }
167
168    void SetGcPoolSize(uint32_t size)
169    {
170        gcPoolSize_ = size;
171    }
172
173    void SetLogLevel(LOG_LEVEL logLevel)
174    {
175        logLevel_ = logLevel;
176    }
177
178    void SetLogBufPrint(LOG_PRINT out)
179    {
180        logBufPrint_ = out;
181    }
182
183    void SetDebuggerLibraryPath(const std::string &path)
184    {
185        debuggerLibraryPath_ = path;
186    }
187
188    void SetEnableArkTools(bool value)
189    {
190        enableArkTools_ = value;
191    }
192
193    void SetEnableCpuprofiler(bool value)
194    {
195        enableCpuprofiler_ = value;
196    }
197
198    void SetArkProperties(int prop)
199    {
200        arkProperties_ = prop;
201    }
202
203    void SetArkBundleName(const std::string &bundleName)
204    {
205        arkBundleName_ = bundleName;
206    }
207
208    void SetMemConfigProperty(std::string configProperty)
209    {
210        memConfigProperty_ = configProperty;
211    }
212
213    void SetGcThreadNum(size_t num)
214    {
215        gcThreadNum_ = num;
216    }
217
218    void SetLongPauseTime(size_t time)
219    {
220        longPauseTime_ = time;
221    }
222
223    void SetEnableAsmInterpreter(bool value)
224    {
225        enableAsmInterpreter_ = value;
226    }
227
228    void SetEnableBuiltinsLazy(bool value)
229    {
230        enableBuiltinsLazy_ = value;
231    }
232
233    void SetAsmOpcodeDisableRange(const std::string &value)
234    {
235        asmOpcodeDisableRange_ = value;
236    }
237
238    void SetIsWorker()
239    {
240        isWorker_ = true;
241    }
242
243    bool GetIsWorker() const
244    {
245        return isWorker_;
246    }
247
248    inline void SetIsRestrictedWorker(bool isRestrictedWorker)
249    {
250        isRestrictedWorker_ = isRestrictedWorker;
251    }
252
253    bool GetIsRestrictedWorker() const
254    {
255        return isRestrictedWorker_;
256    }
257
258    void SetBundleName(const std::string &value)
259    {
260        bundleName_ = value;
261    }
262
263    void SetEnableAOT(bool value)
264    {
265        enableAOT_ = value;
266    }
267
268    void SetAnDir(const std::string &value)
269    {
270        anDir_ = value;
271    }
272
273    void SetEnableProfile(bool value)
274    {
275        enableProfile_ = value;
276    }
277
278    // Valid only when SetEnableProfile(true)
279    void SetProfileDir(const std::string &value)
280    {
281        profileDir_ = value;
282    }
283
284    void SetEnableJIT(bool value)
285    {
286        enableFastJIT_ = value;
287    }
288
289    void SetEnableBaselineJIT(bool value)
290    {
291        enableBaselineJIT_ = value;
292    }
293
294    void SetAOTCompileStatusMap(const std::map<std::string, int32_t> &value)
295    {
296        aotCompileStatusMap_ = value;
297    }
298
299    const std::map<std::string, int32_t> &GetAOTCompileStatusMap() const
300    {
301        return aotCompileStatusMap_;
302    }
303
304private:
305    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
324    LOG_LEVEL GetLogLevel() const
325    {
326        return logLevel_;
327    }
328
329    uint32_t GetGcPoolSize() const
330    {
331        return gcPoolSize_;
332    }
333
334    LOG_PRINT GetLogBufPrint() const
335    {
336        return logBufPrint_;
337    }
338
339    std::string GetDebuggerLibraryPath() const
340    {
341        return debuggerLibraryPath_;
342    }
343
344    bool GetEnableArkTools() const
345    {
346        return enableArkTools_;
347    }
348
349    bool GetEnableCpuprofiler() const
350    {
351        return enableCpuprofiler_;
352    }
353
354    int GetArkProperties() const
355    {
356        return arkProperties_;
357    }
358
359    std::string GetArkBundleName() const
360    {
361        return arkBundleName_;
362    }
363
364    std::string GetMemConfigProperty() const
365    {
366        return memConfigProperty_;
367    }
368
369    size_t GetGcThreadNum() const
370    {
371        return gcThreadNum_;
372    }
373
374    size_t GetLongPauseTime() const
375    {
376        return longPauseTime_;
377    }
378
379    bool GetEnableAsmInterpreter() const
380    {
381        return enableAsmInterpreter_;
382    }
383
384    bool GetEnableBuiltinsLazy() const
385    {
386        return enableBuiltinsLazy_;
387    }
388
389    std::string GetAsmOpcodeDisableRange() const
390    {
391        return asmOpcodeDisableRange_;
392    }
393
394    std::string GetBundleName() const
395    {
396        return bundleName_;
397    }
398
399    bool GetEnableAOT() const
400    {
401        return enableAOT_;
402    }
403
404    std::string GetAnDir() const
405    {
406        return anDir_;
407    }
408
409    bool GetEnableProfile() const
410    {
411        return enableProfile_;
412    }
413
414    std::string GetProfileDir() const
415    {
416        return profileDir_;
417    }
418
419    bool GetEnableJIT() const
420    {
421        return enableFastJIT_;
422    }
423
424    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
457template<typename T>
458template<typename S>
459Global<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
466template<typename T>
467template<typename S>
468Global<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
475template<typename T>
476CopyableGlobal<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
483template<typename T>
484template<typename S>
485CopyableGlobal<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
492template<typename T>
493void 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
503template<typename T>
504template<typename S>
505void 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
515template<typename T>
516void 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
525template<typename T>
526inline void CopyableGlobal<T>::Free()
527{
528    if (!IsEmpty()) {
529        JSNApi::DisposeGlobalHandleAddr(vm_, address_);
530        address_ = 0U;
531    }
532}
533
534template <typename T>
535void CopyableGlobal<T>::SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack,
536                                        WeakRefClearCallBack nativeFinalizeCallback)
537{
538    address_ = JSNApi::SetWeakCallback(vm_, address_, ref, freeGlobalCallBack, nativeFinalizeCallback);
539}
540
541template<typename T>
542void CopyableGlobal<T>::SetWeak()
543{
544    address_ = JSNApi::SetWeak(vm_, address_);
545}
546
547template<typename T>
548void CopyableGlobal<T>::ClearWeak()
549{
550    address_ = JSNApi::ClearWeak(vm_, address_);
551}
552
553template<typename T>
554bool CopyableGlobal<T>::IsWeak() const
555{
556    return JSNApi::IsWeak(vm_, address_);
557}
558
559template<typename T>
560void 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
569template<typename T>
570void Global<T>::FreeGlobalHandleAddr()
571{
572    if (address_ == 0) {
573        return;
574    }
575    JSNApi::DisposeGlobalHandleAddr(vm_, address_);
576    address_ = 0;
577}
578
579template<typename T>
580void Global<T>::SetWeak()
581{
582    address_ = JSNApi::SetWeak(vm_, address_);
583}
584
585template <typename T>
586void Global<T>::SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack,
587                                WeakRefClearCallBack nativeFinalizeCallback)
588{
589    address_ = JSNApi::SetWeakCallback(vm_, address_, ref, freeGlobalCallBack, nativeFinalizeCallback);
590}
591
592template<typename T>
593void Global<T>::ClearWeak()
594{
595    address_ = JSNApi::ClearWeak(vm_, address_);
596}
597
598template<typename T>
599bool Global<T>::IsWeak() const
600{
601    return JSNApi::IsWeak(vm_, address_);
602}
603
604// ---------------------------------- Local --------------------------------------------
605template<typename T>
606Local<T>::Local(const EcmaVM *vm, const CopyableGlobal<T> &current)
607{
608    address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
609}
610
611template<typename T>
612Local<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