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> ¤t)459 Global<T>::Global(const EcmaVM *vm, const Local<S> ¤t) : 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> ¤t)468 Global<T>::Global(const EcmaVM *vm, const Global<S> ¤t) : 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> ¤t)476 CopyableGlobal<T>::CopyableGlobal(const EcmaVM *vm, const Local<T> ¤t) : 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> ¤t)485 CopyableGlobal<T>::CopyableGlobal(const EcmaVM *vm, const Local<S> ¤t) : 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> ¤t)606 Local<T>::Local(const EcmaVM *vm, const CopyableGlobal<T> ¤t)
607 {
608 address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
609 }
610
611 template<typename T>
Local(const EcmaVM *vm, const Global<T> ¤t)612 Local<T>::Local(const EcmaVM *vm, const Global<T> ¤t)
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