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