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
28 #include "ecmascript/base/aligned_struct.h"
29 #include "ecmascript/base/config.h"
30 #include "ecmascript/mem/mem_common.h"
31 #include "ecmascript/napi/include/jsnapi_expo.h"
32 #ifndef NDEBUG
33 #include "libpandabase/utils/debug.h"
34 #endif
35
36 #ifdef ERROR
37 #undef ERROR
38 #endif
39
40 namespace panda {
41 class JSNApiHelper;
42 class EscapeLocalScope;
43 class PromiseRejectInfo;
44 template<typename T>
45 class CopyableGlobal;
46 template<typename T>
47 class Global;
48 class JSNApi;
49 template<typename T>
50 class Local;
51 class JSValueRef;
52 class PrimitiveRef;
53 class ArrayRef;
54 class BigIntRef;
55 class StringRef;
56 class ObjectRef;
57 class FunctionRef;
58 class NumberRef;
59 class BooleanRef;
60 class NativePointerRef;
61 class JsiRuntimeCallInfo;
62 namespace test {
63 class JSNApiTests;
64 } // namespace test
65 class BufferRef;
66 namespace ecmascript {
67 class EcmaVM;
68 class JSTaggedValue;
69 class EcmaContext;
70 class JSRuntimeOptions;
71 class JSThread;
72 struct EcmaRuntimeCallInfo;
73 static constexpr uint32_t DEFAULT_GC_POOL_SIZE = 256_MB;
74 namespace base {
75 template<size_t ElementAlign, typename... Ts>
76 struct AlignedStruct;
77 struct AlignedPointer;
78 }
79 } // namespace ecmascript
80
81 using Deleter = void (*)(void *nativePointer, void *data);
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();
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();
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
SetGcType(GC_TYPE type)153 void SetGcType(GC_TYPE type)
154 {
155 gcType_ = type;
156 }
157
SetGcPoolSize(uint32_t size)158 void SetGcPoolSize(uint32_t size)
159 {
160 gcPoolSize_ = size;
161 }
162
SetLogLevel(LOG_LEVEL logLevel)163 void SetLogLevel(LOG_LEVEL logLevel)
164 {
165 logLevel_ = logLevel;
166 }
167
SetLogBufPrint(LOG_PRINT out)168 void SetLogBufPrint(LOG_PRINT out)
169 {
170 logBufPrint_ = out;
171 }
172
SetDebuggerLibraryPath(const std::string & path)173 void SetDebuggerLibraryPath(const std::string &path)
174 {
175 debuggerLibraryPath_ = path;
176 }
177
SetEnableArkTools(bool value)178 void SetEnableArkTools(bool value)
179 {
180 enableArkTools_ = value;
181 }
182
SetEnableCpuprofiler(bool value)183 void SetEnableCpuprofiler(bool value)
184 {
185 enableCpuprofiler_ = value;
186 }
187
SetArkProperties(int prop)188 void SetArkProperties(int prop)
189 {
190 arkProperties_ = prop;
191 }
192
SetArkBundleName(const std::string & bundleName)193 void SetArkBundleName(const std::string &bundleName)
194 {
195 arkBundleName_ = bundleName;
196 }
197
SetGcThreadNum(size_t num)198 void SetGcThreadNum(size_t num)
199 {
200 gcThreadNum_ = num;
201 }
202
SetLongPauseTime(size_t time)203 void SetLongPauseTime(size_t time)
204 {
205 longPauseTime_ = time;
206 }
207
SetEnableAsmInterpreter(bool value)208 void SetEnableAsmInterpreter(bool value)
209 {
210 enableAsmInterpreter_ = value;
211 }
212
SetEnableBuiltinsLazy(bool value)213 void SetEnableBuiltinsLazy(bool value)
214 {
215 enableBuiltinsLazy_ = value;
216 }
217
SetAsmOpcodeDisableRange(const std::string & value)218 void SetAsmOpcodeDisableRange(const std::string &value)
219 {
220 asmOpcodeDisableRange_ = value;
221 }
222
SetIsWorker()223 void SetIsWorker()
224 {
225 isWorker_ = true;
226 }
227
GetIsWorker()228 bool GetIsWorker() const
229 {
230 return isWorker_;
231 }
232
SetBundleName(const std::string & value)233 void SetBundleName(const std::string &value)
234 {
235 bundleName_ = value;
236 }
237
SetEnableAOT(bool value)238 void SetEnableAOT(bool value)
239 {
240 enableAOT_ = value;
241 }
242
SetAnDir(const std::string & value)243 void SetAnDir(const std::string &value)
244 {
245 anDir_ = value;
246 }
247
SetEnableProfile(bool value)248 void SetEnableProfile(bool value)
249 {
250 enableProfile_ = value;
251 }
252
253 // Valid only when SetEnableProfile(true)
SetProfileDir(const std::string & value)254 void SetProfileDir(const std::string &value)
255 {
256 profileDir_ = value;
257 }
258
259 private:
GetGcType()260 std::string GetGcType() const
261 {
262 std::string gcType;
263 switch (gcType_) {
264 case GC_TYPE::GEN_GC:
265 gcType = "gen-gc";
266 break;
267 case GC_TYPE::STW:
268 gcType = "stw";
269 break;
270 case GC_TYPE::EPSILON:
271 gcType = "epsilon";
272 break;
273 default:
274 break;
275 }
276 return gcType;
277 }
278
GetLogLevel()279 LOG_LEVEL GetLogLevel() const
280 {
281 return logLevel_;
282 }
283
GetGcPoolSize()284 uint32_t GetGcPoolSize() const
285 {
286 return gcPoolSize_;
287 }
288
GetLogBufPrint()289 LOG_PRINT GetLogBufPrint() const
290 {
291 return logBufPrint_;
292 }
293
GetDebuggerLibraryPath()294 std::string GetDebuggerLibraryPath() const
295 {
296 return debuggerLibraryPath_;
297 }
298
GetEnableArkTools()299 bool GetEnableArkTools() const
300 {
301 return enableArkTools_;
302 }
303
GetEnableCpuprofiler()304 bool GetEnableCpuprofiler() const
305 {
306 return enableCpuprofiler_;
307 }
308
GetArkProperties()309 int GetArkProperties() const
310 {
311 return arkProperties_;
312 }
313
GetArkBundleName()314 std::string GetArkBundleName() const
315 {
316 return arkBundleName_;
317 }
318
GetGcThreadNum()319 size_t GetGcThreadNum() const
320 {
321 return gcThreadNum_;
322 }
323
GetLongPauseTime()324 size_t GetLongPauseTime() const
325 {
326 return longPauseTime_;
327 }
328
GetEnableAsmInterpreter()329 bool GetEnableAsmInterpreter() const
330 {
331 return enableAsmInterpreter_;
332 }
333
GetEnableBuiltinsLazy()334 bool GetEnableBuiltinsLazy() const
335 {
336 return enableBuiltinsLazy_;
337 }
338
GetAsmOpcodeDisableRange()339 std::string GetAsmOpcodeDisableRange() const
340 {
341 return asmOpcodeDisableRange_;
342 }
343
GetBundleName()344 std::string GetBundleName() const
345 {
346 return bundleName_;
347 }
348
GetEnableAOT()349 bool GetEnableAOT() const
350 {
351 return enableAOT_;
352 }
353
GetAnDir()354 std::string GetAnDir() const
355 {
356 return anDir_;
357 }
358
GetEnableProfile()359 bool GetEnableProfile() const
360 {
361 return enableProfile_;
362 }
363
GetProfileDir()364 std::string GetProfileDir() const
365 {
366 return profileDir_;
367 }
368
369 GC_TYPE gcType_ = GC_TYPE::EPSILON;
370 LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG;
371 uint32_t gcPoolSize_ = ecmascript::DEFAULT_GC_POOL_SIZE;
372 LOG_PRINT logBufPrint_ {nullptr};
373 std::string debuggerLibraryPath_ {};
374 bool enableArkTools_ {false};
375 bool enableCpuprofiler_ {false};
376 int arkProperties_ {-1};
377 std::string arkBundleName_ = {""};
378 size_t gcThreadNum_ {DEFAULT_GC_THREAD_NUM};
379 size_t longPauseTime_ {DEFAULT_LONG_PAUSE_TIME};
380 bool enableAsmInterpreter_ {true};
381 bool enableBuiltinsLazy_ {true};
382 bool isWorker_ {false};
383 std::string asmOpcodeDisableRange_ {""};
384 std::string bundleName_ {};
385 bool enableAOT_ {false};
386 std::string anDir_ {};
387 bool enableProfile_ {false};
388 std::string profileDir_ {};
389 friend JSNApi;
390 };
391
392 template<typename T>
393 template<typename S>
Global(const EcmaVM * vm,const Local<S> & current)394 Global<T>::Global(const EcmaVM *vm, const Local<S> ¤t) : vm_(vm)
395 {
396 if (!current.IsEmpty()) {
397 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
398 }
399 }
400
401 template<typename T>
402 template<typename S>
Global(const EcmaVM * vm,const Global<S> & current)403 Global<T>::Global(const EcmaVM *vm, const Global<S> ¤t) : vm_(vm)
404 {
405 if (!current.IsEmpty()) {
406 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
407 }
408 }
409
410 template<typename T>
CopyableGlobal(const EcmaVM * vm,const Local<T> & current)411 CopyableGlobal<T>::CopyableGlobal(const EcmaVM *vm, const Local<T> ¤t) : vm_(vm)
412 {
413 if (!current.IsEmpty()) {
414 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
415 }
416 }
417
418 template<typename T>
419 template<typename S>
CopyableGlobal(const EcmaVM * vm,const Local<S> & current)420 CopyableGlobal<T>::CopyableGlobal(const EcmaVM *vm, const Local<S> ¤t) : vm_(vm)
421 {
422 if (!current.IsEmpty()) {
423 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
424 }
425 }
426
427 template<typename T>
Copy(const CopyableGlobal & that)428 void CopyableGlobal<T>::Copy(const CopyableGlobal &that)
429 {
430 Free();
431 vm_ = that.vm_;
432 if (!that.IsEmpty()) {
433 ECMA_ASSERT(vm_ != nullptr);
434 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*that));
435 }
436 }
437
438 template<typename T>
439 template<typename S>
Copy(const CopyableGlobal<S> & that)440 void CopyableGlobal<T>::Copy(const CopyableGlobal<S> &that)
441 {
442 Free();
443 vm_ = that.GetEcmaVM();
444 if (!that.IsEmpty()) {
445 ECMA_ASSERT(vm_ != nullptr);
446 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*that));
447 }
448 }
449
450 template<typename T>
Move(CopyableGlobal & that)451 void CopyableGlobal<T>::Move(CopyableGlobal &that)
452 {
453 Free();
454 vm_ = that.vm_;
455 address_ = that.address_;
456 that.vm_ = nullptr;
457 that.address_ = 0U;
458 }
459
460 template<typename T>
Free()461 inline void CopyableGlobal<T>::Free()
462 {
463 if (!IsEmpty()) {
464 JSNApi::DisposeGlobalHandleAddr(vm_, address_);
465 address_ = 0U;
466 }
467 }
468
469 template <typename T>
SetWeakCallback(void * ref,WeakRefClearCallBack freeGlobalCallBack,WeakRefClearCallBack nativeFinalizeCallback)470 void CopyableGlobal<T>::SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack,
471 WeakRefClearCallBack nativeFinalizeCallback)
472 {
473 address_ = JSNApi::SetWeakCallback(vm_, address_, ref, freeGlobalCallBack, nativeFinalizeCallback);
474 }
475
476 template<typename T>
SetWeak()477 void CopyableGlobal<T>::SetWeak()
478 {
479 address_ = JSNApi::SetWeak(vm_, address_);
480 }
481
482 template<typename T>
ClearWeak()483 void CopyableGlobal<T>::ClearWeak()
484 {
485 address_ = JSNApi::ClearWeak(vm_, address_);
486 }
487
488 template<typename T>
IsWeak()489 bool CopyableGlobal<T>::IsWeak() const
490 {
491 return JSNApi::IsWeak(vm_, address_);
492 }
493
494 template<typename T>
Update(const Global & that)495 void Global<T>::Update(const Global &that)
496 {
497 if (address_ != 0) {
498 JSNApi::DisposeGlobalHandleAddr(vm_, address_);
499 }
500 address_ = that.address_;
501 vm_ = that.vm_;
502 }
503
504 template<typename T>
FreeGlobalHandleAddr()505 void Global<T>::FreeGlobalHandleAddr()
506 {
507 if (address_ == 0) {
508 return;
509 }
510 JSNApi::DisposeGlobalHandleAddr(vm_, address_);
511 address_ = 0;
512 }
513
514 template<typename T>
SetWeak()515 void Global<T>::SetWeak()
516 {
517 address_ = JSNApi::SetWeak(vm_, address_);
518 }
519
520 template <typename T>
SetWeakCallback(void * ref,WeakRefClearCallBack freeGlobalCallBack,WeakRefClearCallBack nativeFinalizeCallback)521 void Global<T>::SetWeakCallback(void *ref, WeakRefClearCallBack freeGlobalCallBack,
522 WeakRefClearCallBack nativeFinalizeCallback)
523 {
524 address_ = JSNApi::SetWeakCallback(vm_, address_, ref, freeGlobalCallBack, nativeFinalizeCallback);
525 }
526
527 template<typename T>
ClearWeak()528 void Global<T>::ClearWeak()
529 {
530 address_ = JSNApi::ClearWeak(vm_, address_);
531 }
532
533 template<typename T>
IsWeak()534 bool Global<T>::IsWeak() const
535 {
536 return JSNApi::IsWeak(vm_, address_);
537 }
538
539 // ---------------------------------- Local --------------------------------------------
540 template<typename T>
Local(const EcmaVM * vm,const CopyableGlobal<T> & current)541 Local<T>::Local(const EcmaVM *vm, const CopyableGlobal<T> ¤t)
542 {
543 address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
544 }
545
546 template<typename T>
Local(const EcmaVM * vm,const Global<T> & current)547 Local<T>::Local(const EcmaVM *vm, const Global<T> ¤t)
548 {
549 address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
550 }
551 } // namespace panda
552
553 #undef ECMA_ASSERT
554 #undef ECMA_PUBLIC_API
555 #endif // ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H
556