1 /*
2 * Copyright (c) 2021 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 <string>
22 #include <vector>
23
24 #include "ecmascript/common.h"
25 #include "libpandabase/macros.h"
26
27 namespace panda {
28 class JSNApiHelper;
29 class EscapeLocalScope;
30 class PromiseRejectInfo;
31 template<typename T>
32 class Global;
33 class JSNApi;
34 class PrimitiveRef;
35 class ArrayRef;
36 class StringRef;
37 class ObjectRef;
38 class FunctionRef;
39 class NumberRef;
40 class BooleanRef;
41 class NativePointerRef;
42 namespace test {
43 class JSNApiTests;
44 } // namespace test
45
46 namespace ecmascript {
47 class EcmaVM;
48 class JSRuntimeOptions;
49 } // namespace ecmascript
50
51 using Deleter = void (*)(void *nativePointer, void *data);
52 using EcmaVM = ecmascript::EcmaVM;
53 using JSTaggedType = uint64_t;
54
55 static constexpr uint32_t DEFAULT_GC_POOL_SIZE = 256 * 1024 * 1024;
56
57 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
58 #define ECMA_DISALLOW_COPY(className) \
59 className(const className &) = delete; \
60 className &operator=(const className &) = delete
61
62 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
63 #define ECMA_DISALLOW_MOVE(className) \
64 className(className &&) = delete; \
65 className &operator=(className &&) = delete
66
67 template<typename T>
68 class PUBLIC_API Local { // NOLINT(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
69 public:
70 inline Local() = default;
71
72 template<typename S>
Local(const Local<S> & current)73 inline Local(const Local<S> ¤t) : address_(reinterpret_cast<uintptr_t>(*current))
74 {
75 // Check
76 }
77
78 Local(const EcmaVM *vm, const Global<T> ¤t);
79
80 ~Local() = default;
81
82 inline T *operator*() const
83 {
84 return GetAddress();
85 }
86
87 inline T *operator->() const
88 {
89 return GetAddress();
90 }
91
IsEmpty()92 inline bool IsEmpty() const
93 {
94 return GetAddress() == nullptr;
95 }
96
CheckException()97 inline bool CheckException() const
98 {
99 return IsEmpty() || GetAddress()->IsException();
100 }
101
IsException()102 inline bool IsException() const
103 {
104 return !IsEmpty() && GetAddress()->IsException();
105 }
106
IsNull()107 inline bool IsNull() const
108 {
109 return IsEmpty() || GetAddress()->IsHole();
110 }
111
112 private:
Local(uintptr_t addr)113 explicit inline Local(uintptr_t addr) : address_(addr) {}
GetAddress()114 inline T *GetAddress() const
115 {
116 return reinterpret_cast<T *>(address_);
117 };
118 uintptr_t address_ = 0U;
119 friend JSNApiHelper;
120 friend EscapeLocalScope;
121 };
122
123 template<typename T>
124 class PUBLIC_API Global { // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions
125 public:
126 inline Global() = default;
127
Global(const Global & that)128 inline Global(const Global &that)
129 {
130 Update(that);
131 }
132
133 inline Global &operator=(const Global &that)
134 {
135 Update(that);
136 return *this;
137 }
138
Global(Global && that)139 inline Global(Global &&that)
140 {
141 Update(that);
142 }
143
144 inline Global &operator=(Global &&that)
145 {
146 Update(that);
147 return *this;
148 }
149 // Non-empty initial value.
150 explicit Global(const EcmaVM *vm);
151
152 template<typename S>
153 Global(const EcmaVM *vm, const Local<S> ¤t);
154 template<typename S>
155 Global(const EcmaVM *vm, const Global<S> ¤t);
156 ~Global() = default;
157
ToLocal(const EcmaVM * vm)158 Local<T> ToLocal(const EcmaVM *vm) const
159 {
160 return Local<T>(vm, *this);
161 }
162
Empty()163 void Empty()
164 {
165 address_ = 0;
166 }
167
168 // This method must be called before Global is released.
169 void FreeGlobalHandleAddr();
170
171 inline T *operator*() const
172 {
173 return GetAddress();
174 }
175
176 inline T *operator->() const
177 {
178 return GetAddress();
179 }
180
IsEmpty()181 inline bool IsEmpty() const
182 {
183 return GetAddress() == nullptr;
184 }
185
CheckException()186 inline bool CheckException() const
187 {
188 return IsEmpty() || GetAddress()->IsException();
189 }
190
191 void SetWeak();
192
193 void ClearWeak();
194
195 bool IsWeak() const;
196
197 private:
GetAddress()198 inline T *GetAddress() const
199 {
200 return reinterpret_cast<T *>(address_);
201 };
202 inline void Update(const Global &that);
203 uintptr_t address_ = 0U;
204 const EcmaVM *vm_ {nullptr};
205 };
206
207 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
208 class PUBLIC_API LocalScope {
209 public:
210 explicit LocalScope(const EcmaVM *vm);
211 virtual ~LocalScope();
212
213 protected:
214 inline LocalScope(const EcmaVM *vm, JSTaggedType value);
215
216 private:
217 void *prevNext_ = nullptr;
218 void *prevEnd_ = nullptr;
219 int prevHandleStorageIndex_ {-1};
220 void *thread_ = nullptr;
221 };
222
223 class PUBLIC_API EscapeLocalScope final : public LocalScope {
224 public:
225 explicit EscapeLocalScope(const EcmaVM *vm);
226 ~EscapeLocalScope() override = default;
227
228 ECMA_DISALLOW_COPY(EscapeLocalScope);
229 ECMA_DISALLOW_MOVE(EscapeLocalScope);
230
231 template<typename T>
Escape(Local<T> current)232 inline Local<T> Escape(Local<T> current)
233 {
234 ASSERT(!alreadyEscape_);
235 alreadyEscape_ = true;
236 *(reinterpret_cast<T *>(escapeHandle_)) = **current;
237 return Local<T>(escapeHandle_);
238 }
239
240 private:
241 bool alreadyEscape_ = false;
242 uintptr_t escapeHandle_ = 0U;
243 };
244
245 class PUBLIC_API JSExecutionScope {
246 public:
247 explicit JSExecutionScope(const EcmaVM *vm);
248 ~JSExecutionScope();
249 ECMA_DISALLOW_COPY(JSExecutionScope);
250 ECMA_DISALLOW_MOVE(JSExecutionScope);
251
252 private:
253 void *last_current_thread_ = nullptr;
254 bool is_revert_ = false;
255 };
256
257 class PUBLIC_API JSValueRef {
258 public:
259 static Local<PrimitiveRef> Undefined(const EcmaVM *vm);
260 static Local<PrimitiveRef> Null(const EcmaVM *vm);
261 static Local<PrimitiveRef> True(const EcmaVM *vm);
262 static Local<PrimitiveRef> False(const EcmaVM *vm);
263 static Local<JSValueRef> Exception(const EcmaVM *vm);
264
265 bool BooleaValue();
266 int64_t IntegerValue(const EcmaVM *vm);
267 uint32_t Uint32Value(const EcmaVM *vm);
268 int32_t Int32Value(const EcmaVM *vm);
269
270 Local<NumberRef> ToNumber(const EcmaVM *vm);
271 Local<BooleanRef> ToBoolean(const EcmaVM *vm);
272 Local<StringRef> ToString(const EcmaVM *vm);
273 Local<ObjectRef> ToObject(const EcmaVM *vm);
274 Local<NativePointerRef> ToNativePointer(const EcmaVM *vm);
275
276 bool IsUndefined();
277 bool IsNull();
278 bool IsHole();
279 bool IsTrue();
280 bool IsFalse();
281 bool IsNumber();
282 bool IsBigInt();
283 bool IsInt();
284 bool WithinInt32();
285 bool IsBoolean();
286 bool IsString();
287 bool IsSymbol();
288 bool IsObject();
289 bool IsArray(const EcmaVM *vm);
290 bool IsConstructor();
291 bool IsFunction();
292 bool IsProxy();
293 bool IsException();
294 bool IsPromise();
295 bool IsDataView();
296 bool IsTypedArray();
297 bool IsNativePointer();
298 bool IsDate();
299 bool IsError();
300 bool IsMap();
301 bool IsSet();
302 bool IsWeakMap();
303 bool IsWeakSet();
304 bool IsRegExp();
305 bool IsArrayIterator();
306 bool IsStringIterator();
307 bool IsSetIterator();
308 bool IsMapIterator();
309 bool IsArrayBuffer();
310 bool IsUint8Array();
311 bool IsInt8Array();
312 bool IsUint8ClampedArray();
313 bool IsInt16Array();
314 bool IsUint16Array();
315 bool IsInt32Array();
316 bool IsUint32Array();
317 bool IsFloat32Array();
318 bool IsFloat64Array();
319 bool IsJSPrimitiveRef();
320 bool IsJSPrimitiveNumber();
321 bool IsJSPrimitiveInt();
322 bool IsJSPrimitiveBoolean();
323 bool IsJSPrimitiveString();
324
325 bool IsGeneratorObject();
326 bool IsJSPrimitiveSymbol();
327
328 bool IsArgumentsObject();
329 bool IsGeneratorFunction();
330 bool IsAsyncFunction();
331
332 bool IsStrictEquals(const EcmaVM *vm, Local<JSValueRef> value);
333 Local<StringRef> Typeof(const EcmaVM *vm);
334 bool InstanceOf(const EcmaVM *vm, Local<JSValueRef> value);
335
336 private:
337 JSTaggedType value_;
338 friend JSNApi;
339 template<typename T>
340 friend class Global;
341 template<typename T>
342 friend class Local;
343 };
344
345 class PUBLIC_API PrimitiveRef : public JSValueRef {
346 };
347
348 class PUBLIC_API IntegerRef : public PrimitiveRef {
349 public:
350 static Local<IntegerRef> New(const EcmaVM *vm, int input);
351 static Local<IntegerRef> NewFromUnsigned(const EcmaVM *vm, unsigned int input);
352 int Value();
353 };
354
355 class PUBLIC_API NumberRef : public PrimitiveRef {
356 public:
357 static Local<NumberRef> New(const EcmaVM *vm, double input);
358 static Local<NumberRef> New(const EcmaVM *vm, int32_t input);
359 static Local<NumberRef> New(const EcmaVM *vm, uint32_t input);
360 static Local<NumberRef> New(const EcmaVM *vm, int64_t input);
361
362 double Value();
363 };
364
365 class PUBLIC_API BigIntRef : public PrimitiveRef {
366 public:
367 static Local<BigIntRef> New(const EcmaVM *vm, uint64_t input);
368 static Local<BigIntRef> New(const EcmaVM *vm, int64_t input);
369 static Local<JSValueRef> CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words);
370 void BigIntToInt64(const EcmaVM *vm, int64_t *cValue, bool *lossless);
371 void BigIntToUint64(const EcmaVM *vm, uint64_t *cValue, bool *lossless);
372 void GetWordsArray(bool* signBit, size_t wordCount, uint64_t* words);
373 uint32_t GetWordsArraySize();
374 };
375
376 class PUBLIC_API BooleanRef : public PrimitiveRef {
377 public:
378 static Local<BooleanRef> New(const EcmaVM *vm, bool input);
379 bool Value();
380 };
381
382 class PUBLIC_API StringRef : public PrimitiveRef {
383 public:
Cast(JSValueRef * value)384 static inline StringRef *Cast(JSValueRef *value)
385 {
386 // check
387 return static_cast<StringRef *>(value);
388 }
389 static Local<StringRef> NewFromUtf8(const EcmaVM *vm, const char *utf8, int length = -1);
390 std::string ToString();
391 int32_t Length();
392 int32_t Utf8Length();
393 int WriteUtf8(char *buffer, int length);
394 };
395
396 class PUBLIC_API SymbolRef : public PrimitiveRef {
397 public:
398 static Local<SymbolRef> New(const EcmaVM *vm, Local<StringRef> description);
399 Local<StringRef> GetDescription(const EcmaVM *vm);
400 };
401
402 using NativePointerCallback = void (*)(void* value, void* hint);
403 class PUBLIC_API NativePointerRef : public JSValueRef {
404 public:
405 static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer);
406 static Local<NativePointerRef> New(const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack,
407 void *data);
408 void *Value();
409 };
410
411 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
412 class PUBLIC_API PropertyAttribute {
413 public:
Default()414 static PropertyAttribute Default()
415 {
416 return PropertyAttribute();
417 }
418 PropertyAttribute() = default;
PropertyAttribute(Local<JSValueRef> value,bool w,bool e,bool c)419 PropertyAttribute(Local<JSValueRef> value, bool w, bool e, bool c)
420 : value_(value),
421 writable_(w),
422 enumerable_(e),
423 configurable_(c),
424 hasWritable_(true),
425 hasEnumerable_(true),
426 hasConfigurable_(true)
427 {}
428 ~PropertyAttribute() = default;
429
IsWritable()430 bool IsWritable() const
431 {
432 return writable_;
433 }
SetWritable(bool flag)434 void SetWritable(bool flag)
435 {
436 writable_ = flag;
437 hasWritable_ = true;
438 }
IsEnumerable()439 bool IsEnumerable() const
440 {
441 return enumerable_;
442 }
SetEnumerable(bool flag)443 void SetEnumerable(bool flag)
444 {
445 enumerable_ = flag;
446 hasEnumerable_ = true;
447 }
IsConfigurable()448 bool IsConfigurable() const
449 {
450 return configurable_;
451 }
SetConfigurable(bool flag)452 void SetConfigurable(bool flag)
453 {
454 configurable_ = flag;
455 hasConfigurable_ = true;
456 }
HasWritable()457 bool HasWritable() const
458 {
459 return hasWritable_;
460 }
HasConfigurable()461 bool HasConfigurable() const
462 {
463 return hasConfigurable_;
464 }
HasEnumerable()465 bool HasEnumerable() const
466 {
467 return hasEnumerable_;
468 }
GetValue(const EcmaVM * vm)469 Local<JSValueRef> GetValue(const EcmaVM *vm) const
470 {
471 if (value_.IsEmpty()) {
472 return JSValueRef::Undefined(vm);
473 }
474 return value_;
475 }
SetValue(Local<JSValueRef> value)476 void SetValue(Local<JSValueRef> value)
477 {
478 value_ = value;
479 }
HasValue()480 inline bool HasValue() const
481 {
482 return !value_.IsEmpty();
483 }
GetGetter(const EcmaVM * vm)484 Local<JSValueRef> GetGetter(const EcmaVM *vm) const
485 {
486 if (getter_.IsEmpty()) {
487 return JSValueRef::Undefined(vm);
488 }
489 return getter_;
490 }
SetGetter(Local<JSValueRef> value)491 void SetGetter(Local<JSValueRef> value)
492 {
493 getter_ = value;
494 }
HasGetter()495 bool HasGetter() const
496 {
497 return !getter_.IsEmpty();
498 }
GetSetter(const EcmaVM * vm)499 Local<JSValueRef> GetSetter(const EcmaVM *vm) const
500 {
501 if (setter_.IsEmpty()) {
502 return JSValueRef::Undefined(vm);
503 }
504 return setter_;
505 }
SetSetter(Local<JSValueRef> value)506 void SetSetter(Local<JSValueRef> value)
507 {
508 setter_ = value;
509 }
HasSetter()510 bool HasSetter() const
511 {
512 return !setter_.IsEmpty();
513 }
514
515 private:
516 Local<JSValueRef> value_;
517 Local<JSValueRef> getter_;
518 Local<JSValueRef> setter_;
519 bool writable_ = false;
520 bool enumerable_ = false;
521 bool configurable_ = false;
522 bool hasWritable_ = false;
523 bool hasEnumerable_ = false;
524 bool hasConfigurable_ = false;
525 };
526
527 class PUBLIC_API ObjectRef : public JSValueRef {
528 public:
Cast(JSValueRef * value)529 static inline ObjectRef *Cast(JSValueRef *value)
530 {
531 // check
532 return static_cast<ObjectRef *>(value);
533 }
534 static Local<ObjectRef> New(const EcmaVM *vm);
535 bool Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value);
536 bool Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value);
537 bool SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter,
538 Local<FunctionRef> setter, PropertyAttribute attribute = PropertyAttribute::Default());
539 Local<JSValueRef> Get(const EcmaVM *vm, Local<JSValueRef> key);
540 Local<JSValueRef> Get(const EcmaVM *vm, int32_t key);
541
542 bool GetOwnProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute &property);
543 Local<ArrayRef> GetOwnPropertyNames(const EcmaVM *vm);
544 Local<ArrayRef> GetOwnEnumerablePropertyNames(const EcmaVM *vm);
545 Local<JSValueRef> GetPrototype(const EcmaVM *vm);
546
547 bool DefineProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute attribute);
548
549 bool Has(const EcmaVM *vm, Local<JSValueRef> key);
550 bool Has(const EcmaVM *vm, uint32_t key);
551
552 bool Delete(const EcmaVM *vm, Local<JSValueRef> key);
553 bool Delete(const EcmaVM *vm, uint32_t key);
554
555 void SetNativePointerFieldCount(int32_t count);
556 int32_t GetNativePointerFieldCount();
557 void *GetNativePointerField(int32_t index);
558 void SetNativePointerField(int32_t index,
559 void *nativePointer = nullptr,
560 NativePointerCallback callBack = nullptr,
561 void *data = nullptr);
562 };
563
564 using FunctionCallback = Local<JSValueRef> (*)(EcmaVM *, Local<JSValueRef>,
565 const Local<JSValueRef>[], // NOLINTNEXTLINE(modernize-avoid-c-arrays)
566 int32_t, void *);
567 using FunctionCallbackWithNewTarget =
568 Local<JSValueRef> (*)(EcmaVM *, Local<JSValueRef>, Local<JSValueRef>, const Local<JSValueRef>[], int32_t, void *);
569 class PUBLIC_API FunctionRef : public ObjectRef {
570 public:
571 static Local<FunctionRef> New(EcmaVM *vm, FunctionCallback nativeFunc, void *data);
572 static Local<FunctionRef> New(EcmaVM *vm, FunctionCallback nativeFunc, Deleter deleter, void *data);
573 static Local<FunctionRef> NewWithProperty(EcmaVM *vm, FunctionCallback nativeFunc, void *data);
574 static Local<FunctionRef> NewClassFunction(EcmaVM *vm, FunctionCallbackWithNewTarget nativeFunc, Deleter deleter,
575 void *data);
576 Local<JSValueRef> Call(const EcmaVM *vm, Local<JSValueRef> thisObj, const Local<JSValueRef> argv[],
577 int32_t length);
578 Local<JSValueRef> Constructor(const EcmaVM *vm, const Local<JSValueRef> argv[], int32_t length);
579 Local<JSValueRef> GetFunctionPrototype(const EcmaVM *vm);
580 // Inherit Prototype from parent function
581 // set this.Prototype.__proto__ to parent.Prototype, set this.__proto__ to parent function
582 bool Inherit(const EcmaVM *vm, Local<FunctionRef> parent);
583 void SetName(const EcmaVM *vm, Local<StringRef> name);
584 Local<StringRef> GetName(const EcmaVM *vm);
585 bool IsNative(const EcmaVM *vm);
586 };
587
588 class PUBLIC_API ArrayRef : public ObjectRef {
589 public:
590 static Local<ArrayRef> New(const EcmaVM *vm, int32_t length = 0);
591 int32_t Length(const EcmaVM *vm);
592 static bool SetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value);
593 static Local<JSValueRef> GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index);
594 };
595
596 class PUBLIC_API PromiseRef : public ObjectRef {
597 public:
598 Local<PromiseRef> Catch(const EcmaVM *vm, Local<FunctionRef> handler);
599 Local<PromiseRef> Then(const EcmaVM *vm, Local<FunctionRef> handler);
600 Local<PromiseRef> Then(const EcmaVM *vm, Local<FunctionRef> onFulfilled, Local<FunctionRef> onRejected);
601 };
602
603 class PUBLIC_API PromiseCapabilityRef : public ObjectRef {
604 public:
605 static Local<PromiseCapabilityRef> New(const EcmaVM *vm);
606 bool Resolve(const EcmaVM *vm, Local<JSValueRef> value);
607 bool Reject(const EcmaVM *vm, Local<JSValueRef> reason);
608 Local<PromiseRef> GetPromise(const EcmaVM *vm);
609 };
610
611 class PUBLIC_API ArrayBufferRef : public ObjectRef {
612 public:
613 static Local<ArrayBufferRef> New(const EcmaVM *vm, int32_t length);
614 static Local<ArrayBufferRef> New(const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter,
615 void *data);
616
617 int32_t ByteLength(const EcmaVM *vm);
618 void *GetBuffer();
619 };
620
621 class PUBLIC_API DataViewRef : public ObjectRef {
622 public:
623 static Local<DataViewRef> New(const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset,
624 uint32_t byteLength);
625 uint32_t ByteLength();
626 uint32_t ByteOffset();
627 Local<ArrayBufferRef> GetArrayBuffer(const EcmaVM *vm);
628 };
629
630 class PUBLIC_API TypedArrayRef : public ObjectRef {
631 public:
632 int32_t ByteLength(const EcmaVM *vm);
633 int32_t ByteOffset(const EcmaVM *vm);
634 int32_t ArrayLength(const EcmaVM *vm);
635 Local<ArrayBufferRef> GetArrayBuffer(const EcmaVM *vm);
636 };
637
638 class PUBLIC_API Int8ArrayRef : public TypedArrayRef {
639 public:
640 static Local<Int8ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
641 };
642
643 class PUBLIC_API Uint8ArrayRef : public TypedArrayRef {
644 public:
645 static Local<Uint8ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
646 };
647
648 class PUBLIC_API Uint8ClampedArrayRef : public TypedArrayRef {
649 public:
650 static Local<Uint8ClampedArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
651 int32_t length);
652 };
653
654 class PUBLIC_API Int16ArrayRef : public TypedArrayRef {
655 public:
656 static Local<Int16ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
657 };
658
659 class PUBLIC_API Uint16ArrayRef : public TypedArrayRef {
660 public:
661 static Local<Uint16ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
662 int32_t length);
663 };
664
665 class PUBLIC_API Int32ArrayRef : public TypedArrayRef {
666 public:
667 static Local<Int32ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length);
668 };
669
670 class PUBLIC_API Uint32ArrayRef : public TypedArrayRef {
671 public:
672 static Local<Uint32ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
673 int32_t length);
674 };
675
676 class PUBLIC_API Float32ArrayRef : public TypedArrayRef {
677 public:
678 static Local<Float32ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
679 int32_t length);
680 };
681
682 class PUBLIC_API Float64ArrayRef : public TypedArrayRef {
683 public:
684 static Local<Float64ArrayRef> New(const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset,
685 int32_t length);
686 };
687
688 class PUBLIC_API RegExpRef : public ObjectRef {
689 public:
690 Local<StringRef> GetOriginalSource(const EcmaVM *vm);
691 };
692
693 class PUBLIC_API DateRef : public ObjectRef {
694 public:
695 static Local<DateRef> New(const EcmaVM *vm, double time);
696 Local<StringRef> ToString(const EcmaVM *vm);
697 double GetTime();
698 };
699
700 class PUBLIC_API MapRef : public ObjectRef {
701 public:
702 int32_t GetSize();
703 };
704
705 class PUBLIC_API SetRef : public ObjectRef {
706 public:
707 int32_t GetSize();
708 };
709
710 class PUBLIC_API JSON {
711 public:
712 static Local<JSValueRef> Parse(const EcmaVM *vm, Local<StringRef> string);
713 static Local<JSValueRef> Stringify(const EcmaVM *vm, Local<JSValueRef> json);
714 };
715
716 class PUBLIC_API Exception {
717 public:
718 static Local<JSValueRef> Error(const EcmaVM *vm, Local<StringRef> message);
719 static Local<JSValueRef> RangeError(const EcmaVM *vm, Local<StringRef> message);
720 static Local<JSValueRef> ReferenceError(const EcmaVM *vm, Local<StringRef> message);
721 static Local<JSValueRef> SyntaxError(const EcmaVM *vm, Local<StringRef> message);
722 static Local<JSValueRef> TypeError(const EcmaVM *vm, Local<StringRef> message);
723 static Local<JSValueRef> EvalError(const EcmaVM *vm, Local<StringRef> message);
724 };
725
726 using LOG_PRINT = int (*)(int id, int level, const char *tag, const char *fmt, const char *message);
727
728 class PUBLIC_API RuntimeOption {
729 public:
730 enum class PUBLIC_API GC_TYPE : uint8_t { EPSILON, GEN_GC, STW };
731 enum class PUBLIC_API LOG_LEVEL : uint8_t {
732 DEBUG = 3,
733 INFO = 4,
734 WARN = 5,
735 ERROR = 6,
736 FATAL = 7,
737 };
738
SetGcType(GC_TYPE type)739 void SetGcType(GC_TYPE type)
740 {
741 gcType_ = type;
742 }
743
SetGcPoolSize(uint32_t size)744 void SetGcPoolSize(uint32_t size)
745 {
746 gcPoolSize_ = size;
747 }
748
SetLogLevel(LOG_LEVEL logLevel)749 void SetLogLevel(LOG_LEVEL logLevel)
750 {
751 logLevel_ = logLevel;
752 }
753
SetLogBufPrint(LOG_PRINT out)754 void SetLogBufPrint(LOG_PRINT out)
755 {
756 logBufPrint_ = out;
757 }
758
SetDebuggerLibraryPath(const std::string & path)759 void SetDebuggerLibraryPath(const std::string &path)
760 {
761 debuggerLibraryPath_ = path;
762 }
763
SetEnableArkTools(bool value)764 void SetEnableArkTools(bool value) {
765 enableArkTools_ = value;
766 }
767
SetEnableCpuprofiler(bool value)768 void SetEnableCpuprofiler(bool value) {
769 enableCpuprofiler_ = value;
770 }
771
SetArkProperties(int prop)772 void SetArkProperties(int prop) {
773 arkProperties_ = prop;
774 }
775
776 private:
GetGcType()777 std::string GetGcType() const
778 {
779 std::string gcType;
780 switch (gcType_) {
781 case GC_TYPE::GEN_GC:
782 gcType = "gen-gc";
783 break;
784 case GC_TYPE::STW:
785 gcType = "stw";
786 break;
787 case GC_TYPE::EPSILON:
788 gcType = "epsilon";
789 break;
790 default:
791 UNREACHABLE();
792 }
793 return gcType;
794 }
795
GetLogLevel()796 std::string GetLogLevel() const
797 {
798 std::string logLevel;
799 switch (logLevel_) {
800 case LOG_LEVEL::INFO:
801 case LOG_LEVEL::WARN:
802 logLevel = "info";
803 break;
804 case LOG_LEVEL::ERROR:
805 logLevel = "error";
806 break;
807 case LOG_LEVEL::FATAL:
808 logLevel = "fatal";
809 break;
810 case LOG_LEVEL::DEBUG:
811 default:
812 logLevel = "debug";
813 break;
814 }
815
816 return logLevel;
817 }
818
GetGcPoolSize()819 uint32_t GetGcPoolSize() const
820 {
821 return gcPoolSize_;
822 }
823
GetLogBufPrint()824 LOG_PRINT GetLogBufPrint() const
825 {
826 return logBufPrint_;
827 }
828
GetDebuggerLibraryPath()829 std::string GetDebuggerLibraryPath() const
830 {
831 return debuggerLibraryPath_;
832 }
833
GetEnableArkTools()834 bool GetEnableArkTools() const
835 {
836 return enableArkTools_;
837 }
838
GetEnableCpuprofiler()839 bool GetEnableCpuprofiler() const
840 {
841 return enableCpuprofiler_;
842 }
843
GetArkProperties()844 int GetArkProperties() const
845 {
846 return arkProperties_;
847 }
848
849 GC_TYPE gcType_ = GC_TYPE::EPSILON;
850 LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG;
851 uint32_t gcPoolSize_ = DEFAULT_GC_POOL_SIZE;
852 LOG_PRINT logBufPrint_ {nullptr};
853 std::string debuggerLibraryPath_ {};
854 bool enableArkTools_ {false};
855 bool enableCpuprofiler_ {false};
856 int arkProperties_ {-1};
857 friend JSNApi;
858 };
859
860 class PUBLIC_API PromiseRejectInfo {
861 public:
862 enum class PUBLIC_API PROMISE_REJECTION_EVENT : uint32_t { REJECT = 0, HANDLE };
863 PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason,
864 PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data);
~PromiseRejectInfo()865 ~PromiseRejectInfo() {}
866 Local<JSValueRef> GetPromise() const;
867 Local<JSValueRef> GetReason() const;
868 PromiseRejectInfo::PROMISE_REJECTION_EVENT GetOperation() const;
869 void* GetData() const;
870
871 private:
872 Local<JSValueRef> promise_ {};
873 Local<JSValueRef> reason_ {};
874 PROMISE_REJECTION_EVENT operation_ = PROMISE_REJECTION_EVENT::REJECT;
875 void* data_ {nullptr};
876 };
877
878 class PUBLIC_API JSNApi {
879 public:
880 using DebuggerPostTask = std::function<void(std::function<void()>&&)>;
881
882 // JSVM
883 enum class PUBLIC_API TRIGGER_GC_TYPE : uint8_t { SEMI_GC, OLD_GC, FULL_GC };
884 static EcmaVM *CreateJSVM(const RuntimeOption &option);
885 static void DestroyJSVM(EcmaVM *ecmaVm);
886
887 // JS code
888 static bool Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry);
889 static bool Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry,
890 const std::string &filename = "");
891 static bool ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file);
892 static Local<ObjectRef> GetExportObject(EcmaVM *vm, const std::string &file, const std::string &itemName);
893
894 // ObjectRef Operation
895 static Local<ObjectRef> GetGlobalObject(const EcmaVM *vm);
896 static void ExecutePendingJob(const EcmaVM *vm);
897
898 // Memory
899 static void TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType = TRIGGER_GC_TYPE::SEMI_GC);
900 // Exception
901 static void ThrowException(const EcmaVM *vm, Local<JSValueRef> error);
902 static Local<ObjectRef> GetAndClearUncaughtException(const EcmaVM *vm);
903 static Local<ObjectRef> GetUncaughtException(const EcmaVM *vm);
904 static void EnableUserUncaughtErrorHandler(EcmaVM *vm);
905
906 static bool StartDebugger(const char *libraryPath, EcmaVM *vm, bool isDebugMode, int32_t instanceId = 0,
907 const DebuggerPostTask &debuggerPostTask = {});
908 static bool StopDebugger(EcmaVM *vm);
909 // Serialize & Deserialize.
910 static void* SerializeValue(const EcmaVM *vm, Local<JSValueRef> data, Local<JSValueRef> transfer);
911 static Local<JSValueRef> DeserializeValue(const EcmaVM *vm, void* recoder);
912 static void DeleteSerializationData(void *data);
913 static void SetOptions(const ecmascript::JSRuntimeOptions &options);
914 static void SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data);
915 static void SetHostEnqueueJob(const EcmaVM* vm, Local<JSValueRef> cb);
916 // profile generator
917 static void StartCpuProfiler(const EcmaVM *vm, const std::string &fileName);
918 static void StopCpuProfiler();
919 static void ResumeVM(const EcmaVM *vm);
920 static bool SuspendVM(const EcmaVM *vm);
921 static bool IsSuspended(const EcmaVM *vm);
922 static bool CheckSafepoint(const EcmaVM *vm);
923
924 private:
925 static int vmCount;
926 static bool CreateRuntime(const RuntimeOption &option);
927 static bool DestroyRuntime();
928
929 static uintptr_t GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress);
930 static uintptr_t GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress);
931 static uintptr_t SetWeak(const EcmaVM *vm, uintptr_t localAddress);
932 static uintptr_t ClearWeak(const EcmaVM *vm, uintptr_t localAddress);
933 static bool IsWeak(const EcmaVM *vm, uintptr_t localAddress);
934 static void DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr);
935 template<typename T>
936 friend class Global;
937 template<typename T>
938 friend class Local;
939 friend class test::JSNApiTests;
940 };
941
942
943 template<typename T>
944 template<typename S>
Global(const EcmaVM * vm,const Local<S> & current)945 Global<T>::Global(const EcmaVM *vm, const Local<S> ¤t) : vm_(vm)
946 {
947 if (!current.IsEmpty()) {
948 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
949 }
950 }
951
952 template<typename T>
953 template<typename S>
Global(const EcmaVM * vm,const Global<S> & current)954 Global<T>::Global(const EcmaVM *vm, const Global<S> ¤t) : vm_(vm)
955 {
956 if (!current.IsEmpty()) {
957 address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast<uintptr_t>(*current));
958 }
959 }
960
961 template<typename T>
Update(const Global & that)962 void Global<T>::Update(const Global &that)
963 {
964 if (address_ != 0) {
965 JSNApi::DisposeGlobalHandleAddr(vm_, address_);
966 }
967 address_ = that.address_;
968 vm_ = that.vm_;
969 }
970
971 template<typename T>
FreeGlobalHandleAddr()972 void Global<T>::FreeGlobalHandleAddr()
973 {
974 if (address_ == 0) {
975 return;
976 }
977 JSNApi::DisposeGlobalHandleAddr(vm_, address_);
978 address_ = 0;
979 }
980
981 template<typename T>
SetWeak()982 void Global<T>::SetWeak()
983 {
984 address_ = JSNApi::SetWeak(vm_, address_);
985 }
986
987 template<typename T>
ClearWeak()988 void Global<T>::ClearWeak()
989 {
990 address_ = JSNApi::ClearWeak(vm_, address_);
991 }
992
993 template<typename T>
IsWeak()994 bool Global<T>::IsWeak() const
995 {
996 return JSNApi::IsWeak(vm_, address_);
997 }
998
999 // ---------------------------------- Local --------------------------------------------
1000 template<typename T>
Local(const EcmaVM * vm,const Global<T> & current)1001 Local<T>::Local(const EcmaVM *vm, const Global<T> ¤t)
1002 {
1003 address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast<uintptr_t>(*current));
1004 }
1005 } // namespace panda
1006 #endif // ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H
1007