• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "dfx_jsnapi.h"
17 #include "jsnapi_helper.h"
18 
19 #include <array>
20 #include <cstdint>
21 #include <fcntl.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <utility>
25 
26 #include "ecmascript/base/builtins_base.h"
27 #include "ecmascript/base/json_parser.h"
28 #include "ecmascript/base/json_stringifier.h"
29 #include "ecmascript/base/path_helper.h"
30 #include "ecmascript/base/string_helper.h"
31 #include "ecmascript/base/typed_array_helper-inl.h"
32 #include "ecmascript/builtins/builtins_object.h"
33 #include "ecmascript/builtins/builtins_string.h"
34 #include "ecmascript/builtins/builtins_typedarray.h"
35 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
36 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
37 #endif
38 #include "ecmascript/accessor_data.h"
39 #include "ecmascript/byte_array.h"
40 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
41 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
42 #include "ecmascript/debugger/js_debugger_manager.h"
43 #include "ecmascript/ecma_context.h"
44 #include "ecmascript/ecma_global_storage.h"
45 #include "ecmascript/ecma_runtime_call_info.h"
46 #include "ecmascript/ecma_string.h"
47 #include "ecmascript/ecma_vm.h"
48 #include "ecmascript/global_env.h"
49 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
50 #include "ecmascript/interpreter/frame_handler.h"
51 #include "ecmascript/interpreter/interpreter_assembly.h"
52 #include "ecmascript/jobs/micro_job_queue.h"
53 #include "ecmascript/js_array.h"
54 #include "ecmascript/js_arraybuffer.h"
55 #include "ecmascript/js_dataview.h"
56 #include "ecmascript/js_file_path.h"
57 #include "ecmascript/js_function.h"
58 #include "ecmascript/js_generator_object.h"
59 #include "ecmascript/js_iterator.h"
60 #include "ecmascript/js_map.h"
61 #include "ecmascript/js_map_iterator.h"
62 #include "ecmascript/js_primitive_ref.h"
63 #include "ecmascript/js_promise.h"
64 #include "ecmascript/js_regexp.h"
65 #include "ecmascript/js_runtime_options.h"
66 #include "ecmascript/js_serializer.h"
67 #include "ecmascript/js_set.h"
68 #include "ecmascript/js_set_iterator.h"
69 #include "ecmascript/js_tagged_number.h"
70 #include "ecmascript/js_thread.h"
71 #include "ecmascript/js_typed_array.h"
72 #include "ecmascript/jspandafile/debug_info_extractor.h"
73 #include "ecmascript/jspandafile/js_pandafile_executor.h"
74 #include "ecmascript/jspandafile/js_pandafile_manager.h"
75 #include "ecmascript/linked_hash_table.h"
76 #include "ecmascript/log.h"
77 #include "ecmascript/mem/mem.h"
78 #include "ecmascript/mem/mem_map_allocator.h"
79 #include "ecmascript/mem/region.h"
80 #include "ecmascript/module/js_module_manager.h"
81 #include "ecmascript/module/js_module_source_text.h"
82 #include "ecmascript/module/module_path_helper.h"
83 #include "ecmascript/object_factory.h"
84 #include "ecmascript/patch/quick_fix_manager.h"
85 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
86 #include "ecmascript/platform/file.h"
87 #include "ecmascript/regexp/regexp_parser.h"
88 #include "ecmascript/serializer/base_deserializer.h"
89 #include "ecmascript/serializer/value_serializer.h"
90 #include "ecmascript/tagged_array.h"
91 #include "ecmascript/js_weak_container.h"
92 #ifdef ARK_SUPPORT_INTL
93 #include "ecmascript/js_bigint.h"
94 #include "ecmascript/js_collator.h"
95 #include "ecmascript/js_date_time_format.h"
96 #include "ecmascript/js_number_format.h"
97 #endif
98 
99 #include "ohos/init_data.h"
100 
101 #include "ecmascript/platform/mutex.h"
102 #include "ecmascript/platform/log.h"
103 
104 namespace panda {
105 using ecmascript::AccessorData;
106 using ecmascript::BigInt;
107 using ecmascript::ByteArray;
108 using ecmascript::ECMAObject;
109 using ecmascript::EcmaRuntimeCallInfo;
110 using ecmascript::EcmaString;
111 using ecmascript::EcmaStringAccessor;
112 using ecmascript::ErrorType;
113 using ecmascript::FastRuntimeStub;
114 using ecmascript::GeneratorContext;
115 using ecmascript::GlobalEnv;
116 using ecmascript::GlobalEnvConstants;
117 using ecmascript::IterationKind;
118 using ecmascript::JSArray;
119 using ecmascript::JSArrayBuffer;
120 using ecmascript::JSDataView;
121 using ecmascript::JSDate;
122 using ecmascript::JSFunction;
123 using ecmascript::JSFunctionBase;
124 using ecmascript::JSGeneratorFunction;
125 using ecmascript::JSGeneratorObject;
126 using ecmascript::JSGeneratorState;
127 using ecmascript::JSHClass;
128 using ecmascript::JSIterator;
129 using ecmascript::JSMap;
130 using ecmascript::JSMapIterator;
131 using ecmascript::JSNativePointer;
132 using ecmascript::JSObject;
133 using ecmascript::JSPandaFile;
134 using ecmascript::JSPandaFileManager;
135 using ecmascript::JSPrimitiveRef;
136 using ecmascript::JSPromise;
137 using ecmascript::JSProxy;
138 using ecmascript::ObjectFastOperator;
139 using ecmascript::JSRegExp;
140 using ecmascript::JSRuntimeOptions;
141 using ecmascript::JSSerializer;
142 using ecmascript::JSSet;
143 using ecmascript::JSSetIterator;
144 using ecmascript::JSSymbol;
145 using ecmascript::JSTaggedNumber;
146 using ecmascript::JSTaggedType;
147 using ecmascript::JSTaggedValue;
148 using ecmascript::JSThread;
149 using ecmascript::JSTypedArray;
150 using ecmascript::LinkedHashMap;
151 using ecmascript::LinkedHashSet;
152 using ecmascript::LockHolder;
153 using ecmascript::MemMapAllocator;
154 using ecmascript::Method;
155 using ecmascript::Mutex;
156 using ecmascript::ObjectFactory;
157 using ecmascript::OperationResult;
158 using ecmascript::PromiseCapability;
159 using ecmascript::PropertyDescriptor;
160 using ecmascript::Region;
161 using ecmascript::TaggedArray;
162 using ecmascript::base::BuiltinsBase;
163 using ecmascript::base::JsonStringifier;
164 using ecmascript::base::StringHelper;
165 using ecmascript::base::TypedArrayHelper;
166 using ecmascript::base::Utf16JsonParser;
167 using ecmascript::base::Utf8JsonParser;
168 using ecmascript::builtins::BuiltinsObject;
169 using ecmascript::job::MicroJobQueue;
170 using ecmascript::job::QueueType;
171 #ifdef ARK_SUPPORT_INTL
172 using ecmascript::JSCollator;
173 using ecmascript::JSDateTimeFormat;
174 using ecmascript::JSNumberFormat;
175 #endif
176 using ecmascript::DebugInfoExtractor;
177 using ecmascript::EcmaContext;
178 using ecmascript::JSWeakMap;
179 using ecmascript::JSWeakSet;
180 using ecmascript::Log;
181 using ecmascript::PatchErrorCode;
182 using ecmascript::RegExpParser;
183 using ecmascript::base::NumberHelper;
184 template <typename T>
185 using JSHandle = ecmascript::JSHandle<T>;
186 template <typename T>
187 using JSMutableHandle = ecmascript::JSMutableHandle<T>;
188 
189 using PathHelper = ecmascript::base::PathHelper;
190 using ModulePathHelper = ecmascript::ModulePathHelper;
191 using JsDebuggerManager = ecmascript::tooling::JsDebuggerManager;
192 using FrameIterator = ecmascript::FrameIterator;
193 
194 namespace {
195 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
196 constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0";
197 }
198 int JSNApi::vmCount_ = 0;
199 bool JSNApi::initialize_ = false;
200 static Mutex *mutex = new panda::Mutex();
201 #define XPM_PROC_LENGTH 50
202 #define PROC_SELF_XPM_REGION_PATH "/proc/self/xpm_region"
203 
204 // ----------------------------------- JSValueRef --------------------------------------
Undefined(const EcmaVM * vm)205 Local<PrimitiveRef> JSValueRef::Undefined(const EcmaVM *vm)
206 {
207     return JSNApiHelper::ToLocal<PrimitiveRef>(
208         vm->GetJSThread()->GlobalConstants()->GetHandledUndefined());
209 }
210 
Null(const EcmaVM * vm)211 Local<PrimitiveRef> JSValueRef::Null(const EcmaVM *vm)
212 {
213     return JSNApiHelper::ToLocal<PrimitiveRef>(
214         vm->GetJSThread()->GlobalConstants()->GetHandledNull());
215 }
216 
True(const EcmaVM * vm)217 Local<PrimitiveRef> JSValueRef::True(const EcmaVM *vm)
218 {
219     return JSNApiHelper::ToLocal<PrimitiveRef>(
220         vm->GetJSThread()->GlobalConstants()->GetHandledTrue());
221 }
222 
False(const EcmaVM * vm)223 Local<PrimitiveRef> JSValueRef::False(const EcmaVM *vm)
224 {
225     return JSNApiHelper::ToLocal<PrimitiveRef>(
226         vm->GetJSThread()->GlobalConstants()->GetHandledFalse());
227 }
228 
ToObject(const EcmaVM * vm)229 Local<ObjectRef> JSValueRef::ToObject(const EcmaVM *vm)
230 {
231     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
232     if (IsUndefined() || IsNull()) {
233         return Undefined(vm);
234     }
235     JSHandle<JSTaggedValue> obj(JSTaggedValue::ToObject(thread, JSNApiHelper::ToJSHandle(this)));
236     LOG_IF_SPECIAL(obj, ERROR);
237     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
238     return JSNApiHelper::ToLocal<ObjectRef>(obj);
239 }
240 
ToString(const EcmaVM * vm)241 Local<StringRef> JSValueRef::ToString(const EcmaVM *vm)
242 {
243     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
244     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
245     LOG_IF_SPECIAL(obj, ERROR);
246     if (!obj->IsString()) {
247         obj = JSHandle<JSTaggedValue>(JSTaggedValue::ToString(thread, obj));
248         RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
249     }
250     return JSNApiHelper::ToLocal<StringRef>(obj);
251 }
252 
ToNativePointer(const EcmaVM * vm)253 Local<NativePointerRef> JSValueRef::ToNativePointer(const EcmaVM *vm)
254 {
255     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
256     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
257     LOG_IF_SPECIAL(obj, ERROR);
258     return JSNApiHelper::ToLocal<NativePointerRef>(obj);
259 }
260 
BooleaValue()261 bool JSValueRef::BooleaValue()
262 {
263     return JSNApiHelper::ToJSTaggedValue(this).ToBoolean();
264 }
265 
IntegerValue(const EcmaVM * vm)266 int64_t JSValueRef::IntegerValue(const EcmaVM *vm)
267 {
268     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
269     JSHandle<JSTaggedValue> tagged = JSNApiHelper::ToJSHandle(this);
270     LOG_IF_SPECIAL(tagged, ERROR);
271     if (tagged->IsNumber()) {
272         if (!NumberHelper::IsFinite(tagged.GetTaggedValue()) || NumberHelper::IsNaN(tagged.GetTaggedValue())) {
273             return 0;
274         } else {
275             return NumberHelper::DoubleToInt64(tagged->GetNumber());
276         }
277     }
278     JSTaggedNumber number = JSTaggedValue::ToInteger(thread, tagged);
279     RETURN_VALUE_IF_ABRUPT(thread, 0);
280     return NumberHelper::DoubleToInt64(number.GetNumber());
281 }
282 
Uint32Value(const EcmaVM * vm)283 uint32_t JSValueRef::Uint32Value(const EcmaVM *vm)
284 {
285     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
286     uint32_t number = JSTaggedValue::ToUint32(thread, JSNApiHelper::ToJSHandle(this));
287     RETURN_VALUE_IF_ABRUPT(thread, 0);
288     return number;
289 }
290 
Int32Value(const EcmaVM * vm)291 int32_t JSValueRef::Int32Value(const EcmaVM *vm)
292 {
293     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
294     int32_t number = JSTaggedValue::ToInt32(thread, JSNApiHelper::ToJSHandle(this));
295     RETURN_VALUE_IF_ABRUPT(thread, 0);
296     return number;
297 }
298 
ToBoolean(const EcmaVM * vm)299 Local<BooleanRef> JSValueRef::ToBoolean(const EcmaVM *vm)
300 {
301     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
302     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
303     LOG_IF_SPECIAL(obj, ERROR);
304     JSHandle<JSTaggedValue> booleanObj(thread, JSTaggedValue(obj->ToBoolean()));
305     return JSNApiHelper::ToLocal<BooleanRef>(booleanObj);
306 }
307 
ToBigInt(const EcmaVM * vm)308 Local<BigIntRef> JSValueRef::ToBigInt(const EcmaVM *vm)
309 {
310     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
311     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
312     LOG_IF_SPECIAL(obj, ERROR);
313     JSHandle<JSTaggedValue> bigIntObj(thread, JSTaggedValue::ToBigInt(thread, obj));
314     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
315     return JSNApiHelper::ToLocal<BigIntRef>(bigIntObj);
316 }
317 
ToNumber(const EcmaVM * vm)318 Local<NumberRef> JSValueRef::ToNumber(const EcmaVM *vm)
319 {
320     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
321     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
322     LOG_IF_SPECIAL(obj, ERROR);
323     JSHandle<JSTaggedValue> number(thread, JSTaggedValue::ToNumber(thread, obj));
324     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
325     return JSNApiHelper::ToLocal<NumberRef>(number);
326 }
327 
IsStrictEquals(const EcmaVM * vm,Local<JSValueRef> value)328 bool JSValueRef::IsStrictEquals(const EcmaVM *vm, Local<JSValueRef> value)
329 {
330     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
331     JSHandle<JSTaggedValue> xValue = JSNApiHelper::ToJSHandle(this);
332     LOG_IF_SPECIAL(xValue, ERROR);
333     JSHandle<JSTaggedValue> yValue = JSNApiHelper::ToJSHandle(value);
334     return JSTaggedValue::StrictEqual(thread, xValue, yValue);
335 }
336 
Typeof(const EcmaVM * vm)337 Local<StringRef> JSValueRef::Typeof(const EcmaVM *vm)
338 {
339     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
340     JSTaggedValue value = FastRuntimeStub::FastTypeOf(thread, JSNApiHelper::ToJSTaggedValue(this));
341     return JSNApiHelper::ToLocal<StringRef>(JSHandle<JSTaggedValue>(thread, value));
342 }
343 
InstanceOf(const EcmaVM * vm,Local<JSValueRef> value)344 bool JSValueRef::InstanceOf(const EcmaVM *vm, Local<JSValueRef> value)
345 {
346     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
347     JSHandle<JSTaggedValue> origin = JSNApiHelper::ToJSHandle(this);
348     LOG_IF_SPECIAL(origin, ERROR);
349     JSHandle<JSTaggedValue> target = JSNApiHelper::ToJSHandle(value);
350     return JSObject::InstanceOf(thread, origin, target);
351 }
352 
353 // Omit exception check for JSValueRef::IsXxx because ark calls here may not
354 // cause side effect even pending exception exists.
IsUndefined()355 bool JSValueRef::IsUndefined()
356 {
357     return JSNApiHelper::ToJSTaggedValue(this).IsUndefined();
358 }
359 
IsNull()360 bool JSValueRef::IsNull()
361 {
362     return JSNApiHelper::ToJSTaggedValue(this).IsNull();
363 }
364 
IsHole()365 bool JSValueRef::IsHole()
366 {
367     return JSNApiHelper::ToJSTaggedValue(this).IsHole();
368 }
369 
IsTrue()370 bool JSValueRef::IsTrue()
371 {
372     return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
373 }
374 
IsFalse()375 bool JSValueRef::IsFalse()
376 {
377     return JSNApiHelper::ToJSTaggedValue(this).IsFalse();
378 }
379 
IsNumber()380 bool JSValueRef::IsNumber()
381 {
382     return JSNApiHelper::ToJSTaggedValue(this).IsNumber();
383 }
384 
IsBigInt()385 bool JSValueRef::IsBigInt()
386 {
387     return JSNApiHelper::ToJSTaggedValue(this).IsBigInt();
388 }
389 
IsInt()390 bool JSValueRef::IsInt()
391 {
392     return JSNApiHelper::ToJSTaggedValue(this).IsInt();
393 }
394 
WithinInt32()395 bool JSValueRef::WithinInt32()
396 {
397     return JSNApiHelper::ToJSTaggedValue(this).WithinInt32();
398 }
399 
IsBoolean()400 bool JSValueRef::IsBoolean()
401 {
402     return JSNApiHelper::ToJSTaggedValue(this).IsBoolean();
403 }
404 
IsString()405 bool JSValueRef::IsString()
406 {
407     return JSNApiHelper::ToJSTaggedValue(this).IsString();
408 }
409 
IsSymbol()410 bool JSValueRef::IsSymbol()
411 {
412     return JSNApiHelper::ToJSTaggedValue(this).IsSymbol();
413 }
414 
IsObject()415 bool JSValueRef::IsObject()
416 {
417     return JSNApiHelper::ToJSTaggedValue(this).IsECMAObject();
418 }
419 
IsArray(const EcmaVM * vm)420 bool JSValueRef::IsArray(const EcmaVM *vm)
421 {
422     CROSS_THREAD_CHECK(vm);
423     return JSNApiHelper::ToJSTaggedValue(this).IsArray(thread);
424 }
425 
IsJSArray(const EcmaVM * vm)426 bool JSValueRef::IsJSArray([[maybe_unused]] const EcmaVM *vm)
427 {
428     return JSNApiHelper::ToJSTaggedValue(this).IsJSArray();
429 }
430 
IsConstructor()431 bool JSValueRef::IsConstructor()
432 {
433     JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
434     return value.IsHeapObject() && value.IsConstructor();
435 }
436 
IsFunction()437 bool JSValueRef::IsFunction()
438 {
439     JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
440     return value.IsCallable();
441 }
442 
IsJSFunction()443 bool JSValueRef::IsJSFunction()
444 {
445     JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
446     return value.IsJSFunction();
447 }
448 
IsProxy()449 bool JSValueRef::IsProxy()
450 {
451     return JSNApiHelper::ToJSTaggedValue(this).IsJSProxy();
452 }
453 
IsPromise()454 bool JSValueRef::IsPromise()
455 {
456     return JSNApiHelper::ToJSTaggedValue(this).IsJSPromise();
457 }
458 
IsDataView()459 bool JSValueRef::IsDataView()
460 {
461     return JSNApiHelper::ToJSTaggedValue(this).IsDataView();
462 }
463 
IsTypedArray()464 bool JSValueRef::IsTypedArray()
465 {
466     return JSNApiHelper::ToJSTaggedValue(this).IsTypedArray();
467 }
468 
IsNativePointer()469 bool JSValueRef::IsNativePointer()
470 {
471     return JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer();
472 }
473 
IsDate()474 bool JSValueRef::IsDate()
475 {
476     return JSNApiHelper::ToJSTaggedValue(this).IsDate();
477 }
478 
IsError()479 bool JSValueRef::IsError()
480 {
481     return JSNApiHelper::ToJSTaggedValue(this).IsJSError();
482 }
483 
IsMap()484 bool JSValueRef::IsMap()
485 {
486     return JSNApiHelper::ToJSTaggedValue(this).IsJSMap();
487 }
488 
IsSet()489 bool JSValueRef::IsSet()
490 {
491     return JSNApiHelper::ToJSTaggedValue(this).IsJSSet();
492 }
493 
IsWeakRef()494 bool JSValueRef::IsWeakRef()
495 {
496     return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakRef();
497 }
498 
IsWeakMap()499 bool JSValueRef::IsWeakMap()
500 {
501     return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakMap();
502 }
503 
IsWeakSet()504 bool JSValueRef::IsWeakSet()
505 {
506     return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakSet();
507 }
508 
IsRegExp()509 bool JSValueRef::IsRegExp()
510 {
511     return JSNApiHelper::ToJSTaggedValue(this).IsJSRegExp();
512 }
513 
IsArrayIterator()514 bool JSValueRef::IsArrayIterator()
515 {
516     return JSNApiHelper::ToJSTaggedValue(this).IsJSArrayIterator();
517 }
518 
IsStringIterator()519 bool JSValueRef::IsStringIterator()
520 {
521     return JSNApiHelper::ToJSTaggedValue(this).IsStringIterator();
522 }
523 
IsSetIterator()524 bool JSValueRef::IsSetIterator()
525 {
526     return JSNApiHelper::ToJSTaggedValue(this).IsJSSetIterator();
527 }
528 
IsMapIterator()529 bool JSValueRef::IsMapIterator()
530 {
531     return JSNApiHelper::ToJSTaggedValue(this).IsJSMapIterator();
532 }
533 
IsArrayBuffer()534 bool JSValueRef::IsArrayBuffer()
535 {
536     return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer();
537 }
538 
IsBuffer()539 bool JSValueRef::IsBuffer()
540 {
541     return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer();
542 }
543 
IsUint8Array()544 bool JSValueRef::IsUint8Array()
545 {
546     return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8Array();
547 }
548 
IsInt8Array()549 bool JSValueRef::IsInt8Array()
550 {
551     return JSNApiHelper::ToJSTaggedValue(this).IsJSInt8Array();
552 }
553 
IsUint8ClampedArray()554 bool JSValueRef::IsUint8ClampedArray()
555 {
556     return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8ClampedArray();
557 }
558 
IsInt16Array()559 bool JSValueRef::IsInt16Array()
560 {
561     return JSNApiHelper::ToJSTaggedValue(this).IsJSInt16Array();
562 }
563 
IsUint16Array()564 bool JSValueRef::IsUint16Array()
565 {
566     return JSNApiHelper::ToJSTaggedValue(this).IsJSUint16Array();
567 }
568 
IsInt32Array()569 bool JSValueRef::IsInt32Array()
570 {
571     return JSNApiHelper::ToJSTaggedValue(this).IsJSInt32Array();
572 }
573 
IsUint32Array()574 bool JSValueRef::IsUint32Array()
575 {
576     return JSNApiHelper::ToJSTaggedValue(this).IsJSUint32Array();
577 }
578 
IsFloat32Array()579 bool JSValueRef::IsFloat32Array()
580 {
581     return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat32Array();
582 }
583 
IsFloat64Array()584 bool JSValueRef::IsFloat64Array()
585 {
586     return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat64Array();
587 }
588 
IsBigInt64Array()589 bool JSValueRef::IsBigInt64Array()
590 {
591     return JSNApiHelper::ToJSTaggedValue(this).IsJSBigInt64Array();
592 }
593 
IsBigUint64Array()594 bool JSValueRef::IsBigUint64Array()
595 {
596     return JSNApiHelper::ToJSTaggedValue(this).IsJSBigUint64Array();
597 }
598 
IsJSPrimitiveRef()599 bool JSValueRef::IsJSPrimitiveRef()
600 {
601     return JSNApiHelper::ToJSTaggedValue(this).IsJSPrimitiveRef();
602 }
603 
IsJSPrimitiveNumber()604 bool JSValueRef::IsJSPrimitiveNumber()
605 {
606     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
607     LOG_IF_SPECIAL(obj, FATAL);
608     return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsNumber();
609 }
610 
IsJSPrimitiveInt()611 bool JSValueRef::IsJSPrimitiveInt()
612 {
613     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
614     LOG_IF_SPECIAL(obj, FATAL);
615     return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsInt();
616 }
617 
IsJSPrimitiveBoolean()618 bool JSValueRef::IsJSPrimitiveBoolean()
619 {
620     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
621     LOG_IF_SPECIAL(obj, FATAL);
622     return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsBoolean();
623 }
624 
IsJSPrimitiveString()625 bool JSValueRef::IsJSPrimitiveString()
626 {
627     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
628     LOG_IF_SPECIAL(obj, FATAL);
629     return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsString();
630 }
631 
IsJSPrimitiveSymbol()632 bool JSValueRef::IsJSPrimitiveSymbol()
633 {
634     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
635     LOG_IF_SPECIAL(obj, FATAL);
636     return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsSymbol();
637 }
638 
IsGeneratorObject()639 bool JSValueRef::IsGeneratorObject()
640 {
641     return JSNApiHelper::ToJSTaggedValue(this).IsGeneratorObject();
642 }
643 
IsModuleNamespaceObject()644 bool JSValueRef::IsModuleNamespaceObject()
645 {
646     return JSNApiHelper::ToJSTaggedValue(this).IsModuleNamespace();
647 }
648 
IsSharedArrayBuffer()649 bool JSValueRef::IsSharedArrayBuffer()
650 {
651     return JSNApiHelper::ToJSTaggedValue(this).IsSharedArrayBuffer();
652 }
653 
IsJSLocale()654 bool JSValueRef::IsJSLocale()
655 {
656     return JSNApiHelper::ToJSTaggedValue(this).IsJSLocale();
657 }
658 
IsJSDateTimeFormat()659 bool JSValueRef::IsJSDateTimeFormat()
660 {
661     return JSNApiHelper::ToJSTaggedValue(this).IsJSDateTimeFormat();
662 }
663 
IsJSRelativeTimeFormat()664 bool JSValueRef::IsJSRelativeTimeFormat()
665 {
666     return JSNApiHelper::ToJSTaggedValue(this).IsJSRelativeTimeFormat();
667 }
668 
IsJSIntl()669 bool JSValueRef::IsJSIntl()
670 {
671     return JSNApiHelper::ToJSTaggedValue(this).IsJSIntl();
672 }
673 
IsJSNumberFormat()674 bool JSValueRef::IsJSNumberFormat()
675 {
676     return JSNApiHelper::ToJSTaggedValue(this).IsJSNumberFormat();
677 }
678 
IsJSCollator()679 bool JSValueRef::IsJSCollator()
680 {
681     return JSNApiHelper::ToJSTaggedValue(this).IsJSCollator();
682 }
683 
IsJSPluralRules()684 bool JSValueRef::IsJSPluralRules()
685 {
686     return JSNApiHelper::ToJSTaggedValue(this).IsJSPluralRules();
687 }
688 
IsJSListFormat()689 bool JSValueRef::IsJSListFormat()
690 {
691     return JSNApiHelper::ToJSTaggedValue(this).IsJSListFormat();
692 }
693 
IsAsyncGeneratorObject()694 bool JSValueRef::IsAsyncGeneratorObject()
695 {
696     return JSNApiHelper::ToJSTaggedValue(this).IsAsyncGeneratorObject();
697 }
698 
IsAsyncFunction()699 bool JSValueRef::IsAsyncFunction()
700 {
701     return JSNApiHelper::ToJSTaggedValue(this).IsJSAsyncFunction();
702 }
703 
IsArgumentsObject()704 bool JSValueRef::IsArgumentsObject()
705 {
706     return JSNApiHelper::ToJSTaggedValue(this).IsArguments();
707 }
708 
IsGeneratorFunction()709 bool JSValueRef::IsGeneratorFunction()
710 {
711     return JSNApiHelper::ToJSTaggedValue(this).IsGeneratorFunction();
712 }
713 
IsAsyncGeneratorFunction()714 bool JSValueRef::IsAsyncGeneratorFunction()
715 {
716     return JSNApiHelper::ToJSTaggedValue(this).IsAsyncGeneratorFunction();
717 }
718 
IsArrayList()719 bool JSValueRef::IsArrayList()
720 {
721     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIArrayList();
722 }
723 
IsDeque()724 bool JSValueRef::IsDeque()
725 {
726     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIDeque();
727 }
728 
IsHashMap()729 bool JSValueRef::IsHashMap()
730 {
731     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIHashMap();
732 }
733 
IsHashSet()734 bool JSValueRef::IsHashSet()
735 {
736     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIHashSet();
737 }
738 
IsLightWeightMap()739 bool JSValueRef::IsLightWeightMap()
740 {
741     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILightWeightMap();
742 }
743 
IsLightWeightSet()744 bool JSValueRef::IsLightWeightSet()
745 {
746     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILightWeightSet();
747 }
748 
IsLinkedList()749 bool JSValueRef::IsLinkedList()
750 {
751     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILinkedList();
752 }
753 
IsLinkedListIterator()754 bool JSValueRef::IsLinkedListIterator()
755 {
756     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILinkedListIterator();
757 }
758 
IsList()759 bool JSValueRef::IsList()
760 {
761     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIList();
762 }
763 
IsPlainArray()764 bool JSValueRef::IsPlainArray()
765 {
766     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIPlainArray();
767 }
768 
IsQueue()769 bool JSValueRef::IsQueue()
770 {
771     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIQueue();
772 }
773 
IsStack()774 bool JSValueRef::IsStack()
775 {
776     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIStack();
777 }
778 
IsTreeMap()779 bool JSValueRef::IsTreeMap()
780 {
781     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPITreeMap();
782 }
783 
IsTreeSet()784 bool JSValueRef::IsTreeSet()
785 {
786     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPITreeSet();
787 }
788 
IsVector()789 bool JSValueRef::IsVector()
790 {
791     return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIVector();
792 }
793 
IsSharedObject()794 bool JSValueRef::IsSharedObject()
795 {
796     return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedObject();
797 }
798 
799 // ---------------------------------- DataView -----------------------------------
New(const EcmaVM * vm,Local<ArrayBufferRef> arrayBuffer,uint32_t byteOffset,uint32_t byteLength)800 Local<DataViewRef> DataViewRef::New(
801     const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset, uint32_t byteLength)
802 {
803     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
804     ObjectFactory *factory = vm->GetFactory();
805 
806     JSHandle<JSArrayBuffer> buffer(JSNApiHelper::ToJSHandle(arrayBuffer));
807     JSHandle<JSDataView> dataView = factory->NewJSDataView(buffer, byteOffset, byteLength);
808     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
809     return JSNApiHelper::ToLocal<DataViewRef>(JSHandle<JSTaggedValue>(dataView));
810 }
811 
ByteLength()812 uint32_t DataViewRef::ByteLength()
813 {
814     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
815     JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
816     return dataView->GetByteLength();
817 }
818 
ByteOffset()819 uint32_t DataViewRef::ByteOffset()
820 {
821     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
822     JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
823     return dataView->GetByteOffset();
824 }
825 
GetArrayBuffer(const EcmaVM * vm)826 Local<ArrayBufferRef> DataViewRef::GetArrayBuffer(const EcmaVM *vm)
827 {
828     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
829     JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
830     LOG_IF_SPECIAL(dataView, FATAL);
831     JSHandle<JSTaggedValue> arrayBuffer(thread, dataView->GetViewedArrayBuffer());
832     return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
833 }
834 // ---------------------------------- DataView -----------------------------------
835 
836 // ----------------------------------- PritimitiveRef ---------------------------------------
GetValue(const EcmaVM * vm)837 Local<JSValueRef> PrimitiveRef::GetValue(const EcmaVM *vm)
838 {
839     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
840     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
841     LOG_IF_SPECIAL(obj, ERROR);
842     if (obj->IsJSPrimitiveRef()) {
843         JSTaggedValue primitiveValue = JSPrimitiveRef::Cast(obj->GetTaggedObject())->GetValue();
844         JSHandle<JSTaggedValue> value(thread, primitiveValue);
845         return JSNApiHelper::ToLocal<JSValueRef>(value);
846     }
847     return Local<JSValueRef>();
848 }
849 
850 // ----------------------------------- NumberRef ---------------------------------------
New(const EcmaVM * vm,double input)851 Local<NumberRef> NumberRef::New(const EcmaVM *vm, double input)
852 {
853     // Omit exception check because ark calls here may not
854     // cause side effect even pending exception exists.
855     CROSS_THREAD_CHECK(vm);
856     if (std::isnan(input)) {
857         input = ecmascript::base::NAN_VALUE;
858     }
859     JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
860     return JSNApiHelper::ToLocal<NumberRef>(number);
861 }
862 
New(const EcmaVM * vm,int32_t input)863 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int32_t input)
864 {
865     // Omit exception check because ark calls here may not
866     // cause side effect even pending exception exists.
867     CROSS_THREAD_CHECK(vm);
868     JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
869     return JSNApiHelper::ToLocal<NumberRef>(number);
870 }
871 
New(const EcmaVM * vm,uint32_t input)872 Local<NumberRef> NumberRef::New(const EcmaVM *vm, uint32_t input)
873 {
874     // Omit exception check because ark calls here may not
875     // cause side effect even pending exception exists.
876     CROSS_THREAD_CHECK(vm);
877     JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
878     return JSNApiHelper::ToLocal<NumberRef>(number);
879 }
880 
New(const EcmaVM * vm,int64_t input)881 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int64_t input)
882 {
883     // Omit exception check because ark calls here may not
884     // cause side effect even pending exception exists.
885     CROSS_THREAD_CHECK(vm);
886     JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
887     return JSNApiHelper::ToLocal<NumberRef>(number);
888 }
889 
Value()890 double NumberRef::Value()
891 {
892     // Omit exception check because ark calls here may not
893     // cause side effect even pending exception exists.
894     return JSTaggedNumber(JSNApiHelper::ToJSTaggedValue(this)).GetNumber();
895 }
896 
897 // ----------------------------------- MapRef ---------------------------------------
Get(const EcmaVM * vm,Local<JSValueRef> key)898 Local<JSValueRef> MapRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
899 {
900     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
901     JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
902     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread,
903                 map->Get(thread, JSNApiHelper::ToJSTaggedValue(*key))));
904 }
905 
Set(const EcmaVM * vm,Local<JSValueRef> key,Local<JSValueRef> value)906 void MapRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
907 {
908     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
909     JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
910     JSMap::Set(thread, map, JSNApiHelper::ToJSHandle(key), JSNApiHelper::ToJSHandle(value));
911 }
912 
New(const EcmaVM * vm)913 Local<MapRef> MapRef::New(const EcmaVM *vm)
914 {
915     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
916     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
917     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
918     JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
919     JSHandle<JSMap> map =
920         JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
921     JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
922     map->SetLinkedMap(thread, hashMap);
923     JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(map);
924     return JSNApiHelper::ToLocal<MapRef>(mapTag);
925 }
926 
GetSize()927 int32_t MapRef::GetSize()
928 {
929     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
930     JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
931     return map->GetSize();
932 }
933 
GetTotalElements()934 int32_t MapRef::GetTotalElements()
935 {
936     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
937     JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
938     return static_cast<int>((map->GetSize())) +
939         LinkedHashMap::Cast(map->GetLinkedMap().GetTaggedObject())->NumberOfDeletedElements();
940 }
941 
GetKey(const EcmaVM * vm,int entry)942 Local<JSValueRef> MapRef::GetKey(const EcmaVM *vm, int entry)
943 {
944     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
945     JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
946     LOG_IF_SPECIAL(map, FATAL);
947     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetKey(entry)));
948 }
949 
GetValue(const EcmaVM * vm,int entry)950 Local<JSValueRef> MapRef::GetValue(const EcmaVM *vm, int entry)
951 {
952     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
953     JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
954     LOG_IF_SPECIAL(map, FATAL);
955     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetValue(entry)));
956 }
957 
958 // ----------------------------------- MapIteratorRef ---------------------------------------
GetIndex()959 int32_t MapIteratorRef::GetIndex()
960 {
961     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, -1);
962     JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
963     return jsMapIter->GetNextIndex();
964 }
965 
GetKind(const EcmaVM * vm)966 Local<JSValueRef> MapIteratorRef::GetKind(const EcmaVM *vm)
967 {
968     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
969     JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
970     LOG_IF_SPECIAL(jsMapIter, FATAL);
971     IterationKind iterKind = jsMapIter->GetIterationKind();
972     Local<JSValueRef> result;
973     switch (iterKind) {
974         case IterationKind::KEY:
975             result = StringRef::NewFromUtf8(vm, "keys");
976             break;
977         case IterationKind::VALUE:
978             result = StringRef::NewFromUtf8(vm, "values");
979             break;
980         case IterationKind::KEY_AND_VALUE:
981             result = StringRef::NewFromUtf8(vm, "entries");
982             break;
983         default:
984             break;
985     }
986     return result;
987 }
988 
New(const EcmaVM * vm,Local<MapRef> map)989 Local<MapIteratorRef> MapIteratorRef::New(const EcmaVM *vm, Local<MapRef> map)
990 {
991     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
992     JSHandle<JSMap> jsMap(JSNApiHelper::ToJSHandle(map));
993     IterationKind iterKind = IterationKind::KEY_AND_VALUE;
994     JSHandle<JSTaggedValue> mapIteratorKeyAndValue =
995         JSMapIterator::CreateMapIterator(vm->GetJSThread(), JSHandle<JSTaggedValue>::Cast(jsMap), iterKind);
996     return JSNApiHelper::ToLocal<JSValueRef>(mapIteratorKeyAndValue);
997 }
998 
GetEcmaRuntimeCallInfo(const EcmaVM * vm)999 ecmascript::EcmaRuntimeCallInfo *MapIteratorRef::GetEcmaRuntimeCallInfo(const EcmaVM *vm)
1000 {
1001     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
1002     JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
1003     JSHandle<LinkedHashMap> linkedHashMap(vm->GetJSThread(), jsMapIter->GetIteratedMap());
1004     uint32_t size = linkedHashMap->GetLength();
1005     return ecmascript::EcmaInterpreter::NewRuntimeCallInfo(vm->GetJSThread(),
1006         JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Undefined()),
1007         JSHandle<JSTaggedValue>(vm->GetJSThread(), jsMapIter.GetTaggedValue()),
1008         JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Undefined()), size);
1009 }
1010 
Next(const EcmaVM * vm,ecmascript::EcmaRuntimeCallInfo * ecmaRuntimeCallInfo)1011 Local<ArrayRef> MapIteratorRef::Next(const EcmaVM *vm, ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
1012 {
1013     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1014     JSHandle<JSTaggedValue> nextTagValResult(vm->GetJSThread(), JSMapIterator::Next(ecmaRuntimeCallInfo));
1015     JSHandle<JSTaggedValue> iteratorVal(vm->GetJSThread(),
1016         JSIterator::IteratorValue(vm->GetJSThread(), nextTagValResult).GetTaggedValue());
1017     return JSNApiHelper::ToLocal<ArrayRef>(iteratorVal);
1018 }
1019 
1020 // ----------------------------------- SetIteratorRef ---------------------------------------
GetIndex()1021 int32_t SetIteratorRef::GetIndex()
1022 {
1023     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, -1);
1024     JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
1025     return jsSetIter->GetNextIndex();
1026 }
1027 
GetKind(const EcmaVM * vm)1028 Local<JSValueRef> SetIteratorRef::GetKind(const EcmaVM *vm)
1029 {
1030     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1031     JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
1032     LOG_IF_SPECIAL(jsSetIter, FATAL);
1033     IterationKind iterKind = jsSetIter->GetIterationKind();
1034     Local<JSValueRef> result;
1035     switch (iterKind) {
1036         case IterationKind::KEY:
1037             result = StringRef::NewFromUtf8(vm, "keys");
1038             break;
1039         case IterationKind::VALUE:
1040             result = StringRef::NewFromUtf8(vm, "values");
1041             break;
1042         case IterationKind::KEY_AND_VALUE:
1043             result = StringRef::NewFromUtf8(vm, "entries");
1044             break;
1045         default:
1046             break;
1047     }
1048     return result;
1049 }
1050 
New(const EcmaVM * vm,Local<SetRef> set)1051 Local<SetIteratorRef> SetIteratorRef::New(const EcmaVM *vm, Local<SetRef> set)
1052 {
1053     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1054     JSHandle<JSSet> jsSet(JSNApiHelper::ToJSHandle(set));
1055     IterationKind iterKind = IterationKind::KEY_AND_VALUE;
1056     JSHandle<JSTaggedValue> setIteratorKeyAndValue =
1057         JSSetIterator::CreateSetIterator(vm->GetJSThread(), JSHandle<JSTaggedValue>::Cast(jsSet), iterKind);
1058     return JSNApiHelper::ToLocal<JSValueRef>(setIteratorKeyAndValue);
1059 }
1060 
GetEcmaRuntimeCallInfo(const EcmaVM * vm)1061 ecmascript::EcmaRuntimeCallInfo *SetIteratorRef::GetEcmaRuntimeCallInfo(const EcmaVM *vm)
1062 {
1063     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
1064     JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
1065     JSHandle<LinkedHashSet> linkedHashSet(vm->GetJSThread(), jsSetIter->GetIteratedSet());
1066     uint32_t size = linkedHashSet->GetLength();
1067     return ecmascript::EcmaInterpreter::NewRuntimeCallInfo(vm->GetJSThread(),
1068         JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Undefined()),
1069         JSHandle<JSTaggedValue>(vm->GetJSThread(), jsSetIter.GetTaggedValue()),
1070         JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Undefined()), size);
1071 }
1072 
Next(const EcmaVM * vm,ecmascript::EcmaRuntimeCallInfo * ecmaRuntimeCallInfo)1073 Local<ArrayRef> SetIteratorRef::Next(const EcmaVM *vm, ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
1074 {
1075     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1076     JSHandle<JSTaggedValue> nextTagValResult(vm->GetJSThread(), JSSetIterator::Next(ecmaRuntimeCallInfo));
1077     JSHandle<JSTaggedValue> iteratorVal(vm->GetJSThread(),
1078         JSIterator::IteratorValue(vm->GetJSThread(), nextTagValResult).GetTaggedValue());
1079     return JSNApiHelper::ToLocal<ArrayRef>(iteratorVal);
1080 }
1081 
1082 // ---------------------------------- Buffer -----------------------------------
New(const EcmaVM * vm,int32_t length)1083 Local<BufferRef> BufferRef::New(const EcmaVM *vm, int32_t length)
1084 {
1085     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1086     ObjectFactory *factory = vm->GetFactory();
1087     JSHandle<JSArrayBuffer> arrayBuffer = JSHandle<JSArrayBuffer>::Cast(factory->NewJSArrayBuffer(length));
1088     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1089     JSHandle<JSFunction> current =
1090         factory->NewJSFunction(env, reinterpret_cast<void *>(BufferRef::BufferToStringCallback));
1091     Local<StringRef> key = StringRef::NewFromUtf8(vm, "toString");
1092     JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1093     JSHandle<JSTaggedValue> currentTaggedValue(current);
1094     JSHandle<JSTaggedValue> obj(arrayBuffer);
1095     bool result = JSTaggedValue::SetProperty(thread, obj, keyValue, currentTaggedValue);
1096     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1097     if (!result) {
1098         LOG_ECMA(ERROR) << "SetProperty failed ! ! !";
1099     }
1100     return JSNApiHelper::ToLocal<BufferRef>(obj);
1101 }
1102 
New(const EcmaVM * vm,void * buffer,int32_t length,const Deleter & deleter,void * data)1103 Local<BufferRef> BufferRef::New(
1104     const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter, void *data)
1105 {
1106     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1107     ObjectFactory *factory = vm->GetFactory();
1108     JSHandle<JSArrayBuffer> arrayBuffer =
1109         factory->NewJSArrayBuffer(buffer, length, reinterpret_cast<ecmascript::DeleteEntryPoint>(deleter), data);
1110 
1111     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1112     JSHandle<JSFunction> current =
1113         factory->NewJSFunction(env, reinterpret_cast<void *>(BufferRef::BufferToStringCallback));
1114     Local<StringRef> key = StringRef::NewFromUtf8(vm, "toString");
1115     JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1116     JSHandle<JSTaggedValue> currentTaggedValue(current);
1117     JSHandle<JSTaggedValue> obj(arrayBuffer);
1118     bool result = JSTaggedValue::SetProperty(thread, obj, keyValue, currentTaggedValue);
1119     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1120     if (!result) {
1121         LOG_ECMA(ERROR) << "SetProperty failed ! ! !";
1122     }
1123     return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
1124 }
1125 
ByteLength(const EcmaVM * vm)1126 int32_t BufferRef::ByteLength([[maybe_unused]] const EcmaVM *vm)
1127 {
1128     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1129     JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1130     return arrayBuffer->GetArrayBufferByteLength();
1131 }
1132 
GetBuffer()1133 void *BufferRef::GetBuffer()
1134 {
1135     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
1136     JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1137     JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData();
1138     if (!bufferData.IsJSNativePointer()) {
1139         return nullptr;
1140     }
1141     return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
1142 }
1143 
BufferToStringCallback(ecmascript::EcmaRuntimeCallInfo * ecmaRuntimeCallInfo)1144 JSTaggedValue BufferRef::BufferToStringCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
1145 {
1146     JSThread *thread = ecmaRuntimeCallInfo->GetThread();
1147     [[maybe_unused]] LocalScope scope(thread->GetEcmaVM());
1148     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1149     JSHandle<JSTaggedValue> arrayBuff = ecmaRuntimeCallInfo->GetThis();
1150     JSHandle<JSArrayBuffer> arrayBuffer(arrayBuff);
1151 
1152     uint32_t length = arrayBuffer->GetArrayBufferByteLength();
1153     JSTaggedValue data = arrayBuffer->GetArrayBufferData();
1154 
1155     ecmascript::CVector<uint16_t> valueTable;
1156     valueTable.reserve(length);
1157     for (uint32_t i = 0; i < length; i++) {
1158         void* rawData = reinterpret_cast<void *>(
1159             ToUintPtr(JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer()) + i);
1160         uint8_t *block = reinterpret_cast<uint8_t *>(rawData);
1161         uint16_t nextCv = static_cast<uint16_t>(*block);
1162         valueTable.emplace_back(nextCv);
1163     }
1164 
1165     auto *char16tData0 = reinterpret_cast<const char16_t *>(valueTable.data());
1166     std::u16string u16str(char16tData0, length);
1167 
1168     const char16_t *constChar16tData = u16str.data();
1169     auto *char16tData = const_cast<char16_t *>(constChar16tData);
1170     auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
1171     uint32_t u16strSize = u16str.size();
1172     JSTaggedValue rString = factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
1173     JSHandle<EcmaString> StringHandle = JSTaggedValue::ToString(thread, rString);
1174     RETURN_VALUE_IF_ABRUPT(thread, JSTaggedValue::Undefined());
1175     return StringHandle.GetTaggedValue();
1176 }
1177 
1178 // ---------------------------------- Promise --------------------------------------
New(const EcmaVM * vm)1179 Local<PromiseCapabilityRef> PromiseCapabilityRef::New(const EcmaVM *vm)
1180 {
1181     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1182     JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
1183     JSHandle<JSTaggedValue> constructor(globalEnv->GetPromiseFunction());
1184     JSHandle<JSTaggedValue> capability(JSPromise::NewPromiseCapability(thread, constructor));
1185     return JSNApiHelper::ToLocal<PromiseCapabilityRef>(capability);
1186 }
1187 
GetPromise(const EcmaVM * vm)1188 Local<PromiseRef> PromiseCapabilityRef::GetPromise(const EcmaVM *vm)
1189 {
1190     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1191     JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1192     LOG_IF_SPECIAL(capacity, FATAL);
1193     return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, capacity->GetPromise()));
1194 }
1195 
Resolve(const EcmaVM * vm,Local<JSValueRef> value)1196 bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value)
1197 {
1198     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1199     const GlobalEnvConstants *constants = thread->GlobalConstants();
1200 
1201     JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(value);
1202     JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1203     LOG_IF_SPECIAL(capacity, FATAL);
1204     JSHandle<JSTaggedValue> resolve(thread, capacity->GetResolve());
1205     JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
1206     EcmaRuntimeCallInfo *info =
1207         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1);
1208     RETURN_VALUE_IF_ABRUPT(thread, false);
1209     info->SetCallArg(arg.GetTaggedValue());
1210     JSFunction::Call(info);
1211     RETURN_VALUE_IF_ABRUPT(thread, false);
1212 
1213     thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
1214     RETURN_VALUE_IF_ABRUPT(thread, false);
1215     vm->GetHeap()->ClearKeptObjects();
1216     return true;
1217 }
1218 
Reject(const EcmaVM * vm,Local<JSValueRef> reason)1219 bool PromiseCapabilityRef::Reject(const EcmaVM *vm, Local<JSValueRef> reason)
1220 {
1221     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1222     const GlobalEnvConstants *constants = thread->GlobalConstants();
1223 
1224     JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(reason);
1225     JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1226     LOG_IF_SPECIAL(capacity, FATAL);
1227     JSHandle<JSTaggedValue> reject(thread, capacity->GetReject());
1228     JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
1229 
1230     EcmaRuntimeCallInfo *info =
1231         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);
1232     RETURN_VALUE_IF_ABRUPT(thread, false);
1233     info->SetCallArg(arg.GetTaggedValue());
1234     JSFunction::Call(info);
1235     RETURN_VALUE_IF_ABRUPT(thread, false);
1236 
1237     thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
1238     RETURN_VALUE_IF_ABRUPT(thread, false);
1239     vm->GetHeap()->ClearKeptObjects();
1240     return true;
1241 }
1242 
1243 // ----------------------------------- SymbolRef -----------------------------------------
New(const EcmaVM * vm,Local<StringRef> description)1244 Local<SymbolRef> SymbolRef::New(const EcmaVM *vm, Local<StringRef> description)
1245 {
1246     // Omit exception check because ark calls here may not
1247     // cause side effect even pending exception exists.
1248     CROSS_THREAD_CHECK(vm);
1249     ObjectFactory *factory = vm->GetFactory();
1250     JSHandle<JSSymbol> symbol = factory->NewJSSymbol();
1251     if (!description.IsEmpty()) {
1252         JSTaggedValue desc = JSNApiHelper::ToJSTaggedValue(*description);
1253         symbol->SetDescription(thread, desc);
1254     }
1255     return JSNApiHelper::ToLocal<SymbolRef>(JSHandle<JSTaggedValue>(symbol));
1256 }
1257 
GetDescription(const EcmaVM * vm)1258 Local<StringRef> SymbolRef::GetDescription(const EcmaVM *vm)
1259 {
1260     CROSS_THREAD_CHECK(vm);
1261     JSTaggedValue description = JSSymbol::Cast(
1262         JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetDescription();
1263     if (!description.IsString()) {
1264         auto constants = thread->GlobalConstants();
1265         return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
1266     }
1267     JSHandle<JSTaggedValue> descriptionHandle(thread, description);
1268     return JSNApiHelper::ToLocal<StringRef>(descriptionHandle);
1269 }
1270 
1271 // ----------------------------------- BooleanRef ---------------------------------------
New(const EcmaVM * vm,bool value)1272 Local<BooleanRef> BooleanRef::New(const EcmaVM *vm, bool value)
1273 {
1274     // Omit exception check because ark calls here may not
1275     // cause side effect even pending exception exists.
1276     CROSS_THREAD_CHECK(vm);
1277     JSHandle<JSTaggedValue> boolean(thread, JSTaggedValue(value));
1278     return JSNApiHelper::ToLocal<BooleanRef>(boolean);
1279 }
1280 
Value()1281 bool BooleanRef::Value()
1282 {
1283     // Omit exception check because ark calls here may not
1284     // cause side effect even pending exception exists.
1285     return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
1286 }
1287 
1288 // ----------------------------------- StringRef ----------------------------------------
NewFromUtf8(const EcmaVM * vm,const char * utf8,int length)1289 Local<StringRef> StringRef::NewFromUtf8(const EcmaVM *vm, const char *utf8, int length)
1290 {
1291     // Omit exception check because ark calls here may not
1292     // cause side effect even pending exception exists.
1293     CROSS_THREAD_CHECK(vm);
1294     ObjectFactory *factory = vm->GetFactory();
1295     if (length < 0) {
1296         JSHandle<JSTaggedValue> current(factory->NewFromUtf8(utf8));
1297         return JSNApiHelper::ToLocal<StringRef>(current);
1298     }
1299     JSHandle<JSTaggedValue> current(factory->NewFromUtf8(reinterpret_cast<const uint8_t *>(utf8), length));
1300     return JSNApiHelper::ToLocal<StringRef>(current);
1301 }
1302 
NewFromUtf16(const EcmaVM * vm,const char16_t * utf16,int length)1303 Local<StringRef> StringRef::NewFromUtf16(const EcmaVM *vm, const char16_t *utf16, int length)
1304 {
1305     // Omit exception check because ark calls here may not
1306     // cause side effect even pending exception exists.
1307     CROSS_THREAD_CHECK(vm);
1308     ObjectFactory *factory = vm->GetFactory();
1309     if (length < 0) {
1310         JSHandle<JSTaggedValue> current(factory->NewFromUtf16(utf16));
1311         return JSNApiHelper::ToLocal<StringRef>(current);
1312     }
1313     JSHandle<JSTaggedValue> current(factory->NewFromUtf16(reinterpret_cast<const uint16_t *>(utf16), length));
1314     return JSNApiHelper::ToLocal<StringRef>(current);
1315 }
1316 
ToString()1317 std::string StringRef::ToString()
1318 {
1319     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, "");
1320     return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).ToStdString();
1321 }
1322 
DebuggerToString()1323 std::string StringRef::DebuggerToString()
1324 {
1325     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, "");
1326     return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).DebuggerToStdString();
1327 }
1328 
Length()1329 uint32_t StringRef::Length()
1330 {
1331     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1332     return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).GetLength();
1333 }
1334 
Utf8Length(const EcmaVM * vm)1335 int32_t StringRef::Utf8Length(const EcmaVM *vm)
1336 {
1337     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1338     JSHandle<EcmaString> strHandle(vm->GetJSThread(), EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this)));
1339     return EcmaStringAccessor(EcmaStringAccessor::Flatten(vm, strHandle)).GetUtf8Length();
1340 }
1341 
WriteUtf8(char * buffer,int length,bool isWriteBuffer)1342 int StringRef::WriteUtf8(char *buffer, int length, bool isWriteBuffer)
1343 {
1344     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1345     return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
1346         .WriteToFlatUtf8(reinterpret_cast<uint8_t *>(buffer), length, isWriteBuffer);
1347 }
1348 
WriteUtf16(char16_t * buffer,int length)1349 int StringRef::WriteUtf16(char16_t *buffer, int length)
1350 {
1351     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1352     return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
1353         .WriteToUtf16(reinterpret_cast<uint16_t *>(buffer), length);
1354 }
1355 
WriteLatin1(char * buffer,int length)1356 int StringRef::WriteLatin1(char *buffer, int length)
1357 {
1358     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1359     return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
1360         .WriteToOneByte(reinterpret_cast<uint8_t *>(buffer), length);
1361 }
1362 
GetNapiWrapperString(const EcmaVM * vm)1363 Local<StringRef> StringRef::GetNapiWrapperString(const EcmaVM *vm)
1364 {
1365     CROSS_THREAD_CHECK(vm);
1366     JSHandle<JSTaggedValue> napiWapperString = thread->GlobalConstants()->GetHandledNapiWrapperString();
1367     return JSNApiHelper::ToLocal<StringRef>(napiWapperString);
1368 }
1369 
1370 // ---------------------------------- PromiseRejectInfo ---------------------------------
PromiseRejectInfo(Local<JSValueRef> promise,Local<JSValueRef> reason,PromiseRejectInfo::PROMISE_REJECTION_EVENT operation,void * data)1371 PromiseRejectInfo::PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason,
1372                                      PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data)
1373     : promise_(promise), reason_(reason), operation_(operation), data_(data) {}
1374 
GetPromise() const1375 Local<JSValueRef> PromiseRejectInfo::GetPromise() const
1376 {
1377     return promise_;
1378 }
1379 
GetReason() const1380 Local<JSValueRef> PromiseRejectInfo::GetReason() const
1381 {
1382     return reason_;
1383 }
1384 
GetOperation() const1385 PromiseRejectInfo::PROMISE_REJECTION_EVENT PromiseRejectInfo::GetOperation() const
1386 {
1387     return operation_;
1388 }
1389 
GetData() const1390 void* PromiseRejectInfo::GetData() const
1391 {
1392     return data_;
1393 }
1394 
1395 // ----------------------------------- BigIntRef ---------------------------------------
New(const EcmaVM * vm,uint64_t input)1396 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, uint64_t input)
1397 {
1398     // Omit exception check because ark calls here may not
1399     // cause side effect even pending exception exists.
1400     CROSS_THREAD_CHECK(vm);
1401     JSHandle<BigInt> big = BigInt::Uint64ToBigInt(thread, input);
1402     JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
1403     return JSNApiHelper::ToLocal<BigIntRef>(bigint);
1404 }
1405 
New(const EcmaVM * vm,int64_t input)1406 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, int64_t input)
1407 {
1408     // Omit exception check because ark calls here may not
1409     // cause side effect even pending exception exists.
1410     CROSS_THREAD_CHECK(vm);
1411     JSHandle<BigInt> big = BigInt::Int64ToBigInt(thread, input);
1412     JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
1413     return JSNApiHelper::ToLocal<BigIntRef>(bigint);
1414 }
1415 
CreateBigWords(const EcmaVM * vm,bool sign,uint32_t size,const uint64_t * words)1416 Local<JSValueRef> BigIntRef::CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words)
1417 {
1418     // Omit exception check because ark calls here may not
1419     // cause side effect even pending exception exists.
1420     CROSS_THREAD_CHECK(vm);
1421     JSHandle<BigInt> big = BigInt::CreateBigWords(thread, sign, size, words);
1422     JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
1423     return JSNApiHelper::ToLocal<JSValueRef>(bigint);
1424 }
1425 
BigIntToInt64(const EcmaVM * vm,int64_t * value,bool * lossless)1426 void BigIntRef::BigIntToInt64(const EcmaVM *vm, int64_t *value, bool *lossless)
1427 {
1428     // Omit exception check because ark calls here may not
1429     // cause side effect even pending exception exists.
1430     CROSS_THREAD_CHECK(vm);
1431     JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
1432     LOG_IF_SPECIAL(bigintVal, ERROR);
1433     BigInt::BigIntToInt64(thread, bigintVal, value, lossless);
1434 }
1435 
BigIntToUint64(const EcmaVM * vm,uint64_t * value,bool * lossless)1436 void BigIntRef::BigIntToUint64(const EcmaVM *vm, uint64_t *value, bool *lossless)
1437 {
1438     // Omit exception check because ark calls here may not
1439     // cause side effect even pending exception exists.
1440     CROSS_THREAD_CHECK(vm);
1441     JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
1442     LOG_IF_SPECIAL(bigintVal, ERROR);
1443     BigInt::BigIntToUint64(thread, bigintVal, value, lossless);
1444 }
1445 
GetWordsArray(bool * signBit,size_t wordCount,uint64_t * words)1446 void BigIntRef::GetWordsArray(bool* signBit, size_t wordCount, uint64_t* words)
1447 {
1448     DCHECK_SPECIAL_VALUE(this);
1449     JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
1450     uint32_t len = bigintVal->GetLength();
1451     uint32_t count = 0;
1452     uint32_t index = 0;
1453     for (; index < wordCount - 1; ++index) {
1454         words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
1455         words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits
1456     }
1457     if (len % 2 == 0) { // 2 : len is odd or even
1458         words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
1459         words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits
1460     } else {
1461         words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
1462     }
1463     *signBit = bigintVal->GetSign();
1464 }
1465 
GetWordsArraySize()1466 uint32_t BigIntRef::GetWordsArraySize()
1467 {
1468     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1469     JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
1470     uint32_t len = bigintVal->GetLength();
1471     return len % 2 != 0 ? len / 2 + 1 : len / 2; // 2 : len is odd or even
1472 }
1473 
1474 // ----------------------------------- HandleScope -------------------------------------
LocalScope(const EcmaVM * vm)1475 LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread())
1476 {
1477     auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext();
1478     prevNext_ = context->GetHandleScopeStorageNext();
1479     prevEnd_ = context->GetHandleScopeStorageEnd();
1480     prevHandleStorageIndex_ = context->GetCurrentHandleStorageIndex();
1481     context->HandleScopeCountAdd();
1482 }
1483 
LocalScope(const EcmaVM * vm,JSTaggedType value)1484 LocalScope::LocalScope(const EcmaVM *vm, JSTaggedType value) : thread_(vm->GetJSThread())
1485 {
1486     auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext();
1487     ecmascript::EcmaHandleScope::NewHandle(reinterpret_cast<JSThread *>(thread_), value);
1488     prevNext_ = context->GetHandleScopeStorageNext();
1489     prevEnd_ = context->GetHandleScopeStorageEnd();
1490     prevHandleStorageIndex_ = context->GetCurrentHandleStorageIndex();
1491     context->HandleScopeCountAdd();
1492 }
1493 
~LocalScope()1494 LocalScope::~LocalScope()
1495 {
1496     auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext();
1497     context->HandleScopeCountDec();
1498     context->SetHandleScopeStorageNext(static_cast<JSTaggedType *>(prevNext_));
1499     if (context->GetHandleScopeStorageEnd() != prevEnd_) {
1500         context->SetHandleScopeStorageEnd(static_cast<JSTaggedType *>(prevEnd_));
1501         context->ShrinkHandleStorage(prevHandleStorageIndex_);
1502     }
1503 }
1504 
1505 // ----------------------------------- EscapeLocalScope ------------------------------
EscapeLocalScope(const EcmaVM * vm)1506 EscapeLocalScope::EscapeLocalScope(const EcmaVM *vm) : LocalScope(vm, JSTaggedValue::Undefined().GetRawData())
1507 {
1508     auto thread = vm->GetJSThread();
1509     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1510     escapeHandle_ = ToUintPtr(thread->GetCurrentEcmaContext()->GetHandleScopeStorageNext() - 1);
1511 }
1512 
1513 // ----------------------------------- IntegerRef ---------------------------------------
New(const EcmaVM * vm,int input)1514 Local<IntegerRef> IntegerRef::New(const EcmaVM *vm, int input)
1515 {
1516     // Omit exception check because ark calls here may not
1517     // cause side effect even pending exception exists.
1518     CROSS_THREAD_CHECK(vm);
1519     JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
1520     return JSNApiHelper::ToLocal<IntegerRef>(integer);
1521 }
1522 
NewFromUnsigned(const EcmaVM * vm,unsigned int input)1523 Local<IntegerRef> IntegerRef::NewFromUnsigned(const EcmaVM *vm, unsigned int input)
1524 {
1525     // Omit exception check because ark calls here may not
1526     // cause side effect even pending exception exists.
1527     CROSS_THREAD_CHECK(vm);
1528     JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
1529     return JSNApiHelper::ToLocal<IntegerRef>(integer);
1530 }
1531 
Value()1532 int IntegerRef::Value()
1533 {
1534     // Omit exception check because ark calls here may not
1535     // cause side effect even pending exception exists.
1536     return JSNApiHelper::ToJSTaggedValue(this).GetInt();
1537 }
1538 
1539 // ----------------------------------- ObjectRef ----------------------------------------
New(const EcmaVM * vm)1540 Local<ObjectRef> ObjectRef::New(const EcmaVM *vm)
1541 {
1542     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1543     ObjectFactory *factory = vm->GetFactory();
1544     JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
1545     JSHandle<JSFunction> constructor(globalEnv->GetObjectFunction());
1546     JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(constructor));
1547     return JSNApiHelper::ToLocal<ObjectRef>(object);
1548 }
1549 
NewWithProperties(const EcmaVM * vm,size_t propertyCount,const Local<JSValueRef> * keys,const PropertyAttribute * attributes)1550 Local<ObjectRef> ObjectRef::NewWithProperties(const EcmaVM *vm, size_t propertyCount,
1551                                               const Local<JSValueRef> *keys,
1552                                               const PropertyAttribute *attributes)
1553 {
1554     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1555     EscapeLocalScope scope(vm);
1556     JSHandle<JSTaggedValue> obj;
1557     auto CreateObjImpl = [vm, propertyCount, keys, attributes] (uintptr_t head) -> JSHandle<JSTaggedValue> {
1558         JSThread *thread = vm->GetJSThread();
1559         const PropertyDescriptor *desc = reinterpret_cast<const PropertyDescriptor *>(head);
1560         for (size_t i = 0; i < propertyCount; ++i) {
1561             const PropertyAttribute &attr = attributes[i];
1562             new (reinterpret_cast<void *>(head)) PropertyDescriptor(thread,
1563                                                                     JSNApiHelper::ToJSHandle(attr.GetValue(vm)),
1564                                                                     attr.IsWritable(), attr.IsEnumerable(),
1565                                                                     attr.IsConfigurable());
1566             head += sizeof(PropertyDescriptor);
1567         }
1568         ObjectFactory *factory = vm->GetFactory();
1569         return factory->CreateJSObjectWithProperties(propertyCount, keys, desc);
1570     };
1571     if (propertyCount <= MAX_PROPERTIES_ON_STACK) {
1572         char desc[sizeof(PropertyDescriptor) * MAX_PROPERTIES_ON_STACK];
1573         obj = CreateObjImpl(reinterpret_cast<uintptr_t>(desc));
1574     } else {
1575         void *desc = malloc(sizeof(PropertyDescriptor) * propertyCount);
1576         obj = CreateObjImpl(reinterpret_cast<uintptr_t>(desc));
1577         free(desc);
1578     }
1579     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1580     return scope.Escape(JSNApiHelper::ToLocal<ObjectRef>(obj));
1581 }
1582 
NewWithNamedProperties(const EcmaVM * vm,size_t propertyCount,const char ** keys,const Local<JSValueRef> * values)1583 Local<ObjectRef> ObjectRef::NewWithNamedProperties(const EcmaVM *vm, size_t propertyCount,
1584                                                    const char **keys, const Local<JSValueRef> *values)
1585 {
1586     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1587     EscapeLocalScope scope(vm);
1588     ObjectFactory *factory = vm->GetFactory();
1589     JSHandle<JSTaggedValue> obj = factory->CreateJSObjectWithNamedProperties(propertyCount, keys, values);
1590     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1591     return scope.Escape(JSNApiHelper::ToLocal<ObjectRef>(obj));
1592 }
1593 
CreateAccessorData(const EcmaVM * vm,Local<FunctionRef> getter,Local<FunctionRef> setter)1594 Local<ObjectRef> ObjectRef::CreateAccessorData(const EcmaVM *vm,
1595                                                Local<FunctionRef> getter, Local<FunctionRef> setter)
1596 {
1597     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1598     JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter);
1599     JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter);
1600     JSHandle<AccessorData> accessor = thread->GetEcmaVM()->GetFactory()->NewAccessorData();
1601     accessor->SetGetter(thread, getterValue);
1602     accessor->SetSetter(thread, setterValue);
1603     return JSNApiHelper::ToLocal<ObjectRef>(JSHandle<JSTaggedValue>::Cast(accessor));
1604 }
1605 
ConvertToNativeBindingObject(const EcmaVM * vm,Local<NativePointerRef> value)1606 bool ObjectRef::ConvertToNativeBindingObject(const EcmaVM *vm, Local<NativePointerRef> value)
1607 {
1608     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1609     [[maybe_unused]] LocalScope scope(vm);
1610     JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
1611     LOG_IF_SPECIAL(object, ERROR);
1612     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1613     JSHandle<JSTaggedValue> keyValue = env->GetNativeBindingSymbol();
1614     JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value);
1615     bool result = JSTaggedValue::SetProperty(vm->GetJSThread(), object, keyValue, valueValue);
1616     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
1617     object->GetTaggedObject()->GetClass()->SetIsNativeBindingObject(true);
1618     return result;
1619 }
1620 
Set(const EcmaVM * vm,Local<JSValueRef> key,Local<JSValueRef> value)1621 bool ObjectRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
1622 {
1623     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1624     [[maybe_unused]] LocalScope scope(vm);
1625     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1626     LOG_IF_SPECIAL(obj, ERROR);
1627     JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1628     JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value);
1629     if (!obj->IsHeapObject()) {
1630         return JSTaggedValue::SetProperty(thread, obj, keyValue, valueValue);
1631     }
1632     return ObjectFastOperator::FastSetPropertyByValue(thread, obj.GetTaggedValue(),
1633                                                       keyValue.GetTaggedValue(),
1634                                                       valueValue.GetTaggedValue());
1635 }
1636 
Set(const EcmaVM * vm,uint32_t key,Local<JSValueRef> value)1637 bool ObjectRef::Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value)
1638 {
1639     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1640     [[maybe_unused]] LocalScope scope(vm);
1641     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1642     LOG_IF_SPECIAL(obj, ERROR);
1643     JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value);
1644     if (!obj->IsHeapObject()) {
1645         return JSTaggedValue::SetProperty(thread, obj, key, valueValue);
1646     }
1647     return ObjectFastOperator::FastSetPropertyByIndex(thread, obj.GetTaggedValue(),
1648                                                       key, valueValue.GetTaggedValue());
1649 }
1650 
SetAccessorProperty(const EcmaVM * vm,Local<JSValueRef> key,Local<FunctionRef> getter,Local<FunctionRef> setter,PropertyAttribute attribute)1651 bool ObjectRef::SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter,
1652     Local<FunctionRef> setter, PropertyAttribute attribute)
1653 {
1654     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1655     [[maybe_unused]] LocalScope scope(vm);
1656     JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter);
1657     JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter);
1658     PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
1659     desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
1660     desc.SetSetter(setterValue);
1661     desc.SetGetter(getterValue);
1662     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1663     LOG_IF_SPECIAL(obj, ERROR);
1664     JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1665     return JSTaggedValue::DefineOwnProperty(thread, obj, keyValue, desc);
1666 }
1667 
Get(const EcmaVM * vm,Local<JSValueRef> key)1668 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
1669 {
1670     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1671     EscapeLocalScope scope(vm);
1672     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1673     LOG_IF_SPECIAL(obj, ERROR);
1674     JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1675     if (!obj->IsHeapObject()) {
1676         OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue);
1677         RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1678         return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(ret.GetValue()));
1679     }
1680     JSTaggedValue ret = ObjectFastOperator::FastGetPropertyByValue(thread, obj.GetTaggedValue(),
1681                                                                    keyValue.GetTaggedValue());
1682     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1683     return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, ret)));
1684 }
1685 
Get(const EcmaVM * vm,int32_t key)1686 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, int32_t key)
1687 {
1688     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1689     EscapeLocalScope scope(vm);
1690     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1691     LOG_IF_SPECIAL(obj, ERROR);
1692     if (!obj->IsHeapObject()) {
1693         OperationResult ret = JSTaggedValue::GetProperty(thread, obj, key);
1694         RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1695         return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(ret.GetValue()));
1696     }
1697     JSTaggedValue ret = ObjectFastOperator::FastGetPropertyByIndex(thread, obj.GetTaggedValue(), key);
1698     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1699     return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, ret)));
1700 }
1701 
GetOwnProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute & property)1702 bool ObjectRef::GetOwnProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute &property)
1703 {
1704     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1705     JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1706     LOG_IF_SPECIAL(obj, ERROR);
1707     JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1708     PropertyDescriptor desc(thread);
1709     bool ret = JSObject::GetOwnProperty(thread, JSHandle<JSObject>(obj), keyValue, desc);
1710     if (!ret) {
1711         return false;
1712     }
1713     property.SetValue(JSNApiHelper::ToLocal<JSValueRef>(desc.GetValue()));
1714     if (desc.HasGetter()) {
1715         property.SetGetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetGetter()));
1716     }
1717     if (desc.HasSetter()) {
1718         property.SetSetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetSetter()));
1719     }
1720     if (desc.HasWritable()) {
1721         property.SetWritable(desc.IsWritable());
1722     }
1723     if (desc.HasEnumerable()) {
1724         property.SetEnumerable(desc.IsEnumerable());
1725     }
1726     if (desc.HasConfigurable()) {
1727         property.SetConfigurable(desc.IsConfigurable());
1728     }
1729 
1730     return true;
1731 }
1732 
GetOwnPropertyNames(const EcmaVM * vm)1733 Local<ArrayRef> ObjectRef::GetOwnPropertyNames(const EcmaVM *vm)
1734 {
1735     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1736     JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this));
1737     LOG_IF_SPECIAL(obj, ERROR);
1738     JSHandle<TaggedArray> array(JSTaggedValue::GetOwnPropertyKeys(thread, obj));
1739     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1740     JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
1741     return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
1742 }
1743 
GetAllPropertyNames(const EcmaVM * vm,uint32_t filter)1744 Local<ArrayRef> ObjectRef::GetAllPropertyNames(const EcmaVM *vm, uint32_t filter)
1745 {
1746     // This interface is only used by napi.
1747     // This interface currently only supports normal objects.
1748     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1749     JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this));
1750     LOG_IF_SPECIAL(obj, ERROR);
1751     JSHandle<TaggedArray> array(JSTaggedValue::GetAllPropertyKeys(thread, obj, filter));
1752     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1753     JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
1754     return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
1755 }
1756 
GetOwnEnumerablePropertyNames(const EcmaVM * vm)1757 Local<ArrayRef> ObjectRef::GetOwnEnumerablePropertyNames(const EcmaVM *vm)
1758 {
1759     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1760     JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(this));
1761     LOG_IF_SPECIAL(obj, ERROR);
1762     JSHandle<TaggedArray> array(JSObject::EnumerableOwnNames(thread, obj));
1763     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1764     JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
1765     return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
1766 }
1767 
GetPrototype(const EcmaVM * vm)1768 Local<JSValueRef> ObjectRef::GetPrototype(const EcmaVM *vm)
1769 {
1770     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1771     JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1772     LOG_IF_SPECIAL(object, ERROR);
1773     JSHandle<JSTaggedValue> prototype(thread, JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(object)));
1774     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1775     return JSNApiHelper::ToLocal<JSValueRef>(prototype);
1776 }
1777 
SetPrototype(const EcmaVM * vm,Local<ObjectRef> prototype)1778 bool ObjectRef::SetPrototype(const EcmaVM *vm, Local<ObjectRef> prototype)
1779 {
1780     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1781     JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1782     JSHandle<JSObject> proto(JSNApiHelper::ToJSHandle(prototype));
1783     return JSTaggedValue::SetPrototype(thread, JSHandle<JSTaggedValue>(object), JSHandle<JSTaggedValue>(proto));
1784 }
1785 
DefineProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute attribute)1786 bool ObjectRef::DefineProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute attribute)
1787 {
1788     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1789     JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1790     LOG_IF_SPECIAL(object, ERROR);
1791     JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
1792     PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
1793     desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
1794     return JSTaggedValue::DefinePropertyOrThrow(thread, object, keyValue, desc);
1795 }
1796 
Has(const EcmaVM * vm,Local<JSValueRef> key)1797 bool ObjectRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
1798 {
1799     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1800     JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1801     LOG_IF_SPECIAL(object, ERROR);
1802     JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
1803     return JSTaggedValue::HasProperty(thread, object, keyValue);
1804 }
1805 
Has(const EcmaVM * vm,uint32_t key)1806 bool ObjectRef::Has(const EcmaVM *vm, uint32_t key)
1807 {
1808     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1809     JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1810     LOG_IF_SPECIAL(object, ERROR);
1811     return JSTaggedValue::HasProperty(thread, object, key);
1812 }
1813 
Delete(const EcmaVM * vm,Local<JSValueRef> key)1814 bool ObjectRef::Delete(const EcmaVM *vm, Local<JSValueRef> key)
1815 {
1816     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1817     JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1818     LOG_IF_SPECIAL(object, ERROR);
1819     JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
1820     return JSTaggedValue::DeleteProperty(thread, object, keyValue);
1821 }
1822 
Delete(const EcmaVM * vm,uint32_t key)1823 bool ObjectRef::Delete(const EcmaVM *vm, uint32_t key)
1824 {
1825     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
1826     JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1827     LOG_IF_SPECIAL(object, ERROR);
1828     JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(key));
1829     return JSTaggedValue::DeleteProperty(thread, object, keyHandle);
1830 }
1831 
Freeze(const EcmaVM * vm)1832 Local<JSValueRef> ObjectRef::Freeze(const EcmaVM *vm)
1833 {
1834     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1835     EscapeLocalScope scope(vm);
1836     JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
1837     LOG_IF_SPECIAL(object, ERROR);
1838     JSHandle<JSObject> obj(object);
1839     bool status = JSObject::SetIntegrityLevel(thread, obj, ecmascript::IntegrityLevel::FROZEN);
1840     if (JSNApi::HasPendingException(vm)) {
1841         JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
1842         return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
1843     }
1844     if (!status) {
1845         LOG_ECMA(ERROR) << "Freeze: freeze failed";
1846         Local<StringRef> message = StringRef::NewFromUtf8(vm, "Freeze: freeze failed");
1847         Local<JSValueRef> error = Exception::Error(vm, message);
1848         JSNApi::ThrowException(vm, error);
1849         JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
1850         return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
1851     }
1852     JSHandle<JSTaggedValue> resultValue(obj);
1853     return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
1854 }
1855 
Seal(const EcmaVM * vm)1856 Local<JSValueRef> ObjectRef::Seal(const EcmaVM *vm)
1857 {
1858     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1859     EscapeLocalScope scope(vm);
1860     JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
1861     LOG_IF_SPECIAL(object, ERROR);
1862     JSHandle<JSObject> obj(object);
1863     bool status = JSObject::SetIntegrityLevel(thread, obj, ecmascript::IntegrityLevel::SEALED);
1864     if (JSNApi::HasPendingException(vm)) {
1865         JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
1866         return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
1867     }
1868     if (!status) {
1869         LOG_ECMA(ERROR) << "Seal: seal failed";
1870         Local<StringRef> message = StringRef::NewFromUtf8(vm, "Freeze: freeze failed");
1871         Local<JSValueRef> error = Exception::Error(vm, message);
1872         JSNApi::ThrowException(vm, error);
1873         JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
1874         return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
1875     }
1876     JSHandle<JSTaggedValue> resultValue(obj);
1877     return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
1878 }
1879 
SetNativePointerFieldCount(const EcmaVM * vm,int32_t count)1880 void ObjectRef::SetNativePointerFieldCount(const EcmaVM *vm, int32_t count)
1881 {
1882     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
1883     // ObjectRef::New may return special value if exception occurs.
1884     // So we need do special value check before use it.
1885     DCHECK_SPECIAL_VALUE(this);
1886     JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1887     object->SetNativePointerFieldCount(thread, count);
1888 }
1889 
GetNativePointerFieldCount()1890 int32_t ObjectRef::GetNativePointerFieldCount()
1891 {
1892     // ObjectRef::New may return special value if exception occurs.
1893     // So we need do special value check before use it.
1894     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
1895     JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1896     return object->GetNativePointerFieldCount();
1897 }
1898 
GetNativePointerField(int32_t index)1899 void *ObjectRef::GetNativePointerField(int32_t index)
1900 {
1901     // ObjectRef::New may return special value if exception occurs.
1902     // So we need do special value check before use it.
1903     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
1904     JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1905     return object->GetNativePointerField(index);
1906 }
1907 
SetNativePointerField(const EcmaVM * vm,int32_t index,void * nativePointer,NativePointerCallback callBack,void * data,size_t nativeBindingsize)1908 void ObjectRef::SetNativePointerField(const EcmaVM *vm, int32_t index, void *nativePointer,
1909     NativePointerCallback callBack, void *data, size_t nativeBindingsize)
1910 {
1911     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
1912     // ObjectRef::New may return special value if exception occurs.
1913     // So we need do special value check before use it.
1914     DCHECK_SPECIAL_VALUE(this);
1915     JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1916     object->SetNativePointerField(thread, index, nativePointer, callBack, data, nativeBindingsize);
1917 }
1918 
1919 // -------------------------------- NativePointerRef ------------------------------------
New(const EcmaVM * vm,void * nativePointer,size_t nativeBindingsize)1920 Local<NativePointerRef> NativePointerRef::New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize)
1921 {
1922     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1923     ObjectFactory *factory = vm->GetFactory();
1924     JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, nullptr, nullptr,
1925         false, nativeBindingsize);
1926     return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
1927 }
1928 
New(const EcmaVM * vm,void * nativePointer,NativePointerCallback callBack,void * data,size_t nativeBindingsize)1929 Local<NativePointerRef> NativePointerRef::New(
1930     const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize)
1931 {
1932     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1933     ObjectFactory *factory = vm->GetFactory();
1934     JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data,
1935         false, nativeBindingsize);
1936     return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
1937 }
1938 
Value()1939 void *NativePointerRef::Value()
1940 {
1941     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
1942     JSHandle<JSTaggedValue> nativePointer = JSNApiHelper::ToJSHandle(this);
1943     return JSHandle<JSNativePointer>(nativePointer)->GetExternalPointer();
1944 }
1945 
1946 // ---------------------------------- Buffer -----------------------------------
New(const EcmaVM * vm,int32_t length)1947 Local<ArrayBufferRef> ArrayBufferRef::New(const EcmaVM *vm, int32_t length)
1948 {
1949     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1950     ObjectFactory *factory = vm->GetFactory();
1951     JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(length);
1952     return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
1953 }
1954 
New(const EcmaVM * vm,void * buffer,int32_t length,const Deleter & deleter,void * data)1955 Local<ArrayBufferRef> ArrayBufferRef::New(
1956     const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter, void *data)
1957 {
1958     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
1959     ObjectFactory *factory = vm->GetFactory();
1960     JSHandle<JSArrayBuffer> arrayBuffer =
1961         factory->NewJSArrayBuffer(buffer, length, reinterpret_cast<ecmascript::DeleteEntryPoint>(deleter), data);
1962     return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
1963 }
1964 
ByteLength(const EcmaVM * vm)1965 int32_t ArrayBufferRef::ByteLength([[maybe_unused]] const EcmaVM *vm)
1966 {
1967     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
1968     JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1969     LOG_IF_SPECIAL(arrayBuffer, FATAL);
1970     return arrayBuffer->GetArrayBufferByteLength();
1971 }
1972 
GetBuffer()1973 void *ArrayBufferRef::GetBuffer()
1974 {
1975     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
1976     JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1977     JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData();
1978     if (!bufferData.IsJSNativePointer()) {
1979         return nullptr;
1980     }
1981     return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
1982 }
1983 
Detach(const EcmaVM * vm)1984 void ArrayBufferRef::Detach(const EcmaVM *vm)
1985 {
1986     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
1987     JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1988     arrayBuffer->Detach(thread);
1989 }
1990 
IsDetach()1991 bool ArrayBufferRef::IsDetach()
1992 {
1993     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
1994     JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1995     return arrayBuffer->IsDetach();
1996 }
1997 
1998 // ---------------------------------- DateRef -----------------------------------
New(const EcmaVM * vm,double time)1999 Local<DateRef> DateRef::New(const EcmaVM *vm, double time)
2000 {
2001     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2002     ObjectFactory *factory = vm->GetFactory();
2003     JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
2004     JSHandle<JSFunction> dateFunction(globalEnv->GetDateFunction());
2005     JSHandle<JSDate> dateObject(factory->NewJSObjectByConstructor(dateFunction));
2006     dateObject->SetTimeValue(thread, JSTaggedValue(time));
2007     return JSNApiHelper::ToLocal<DateRef>(JSHandle<JSTaggedValue>(dateObject));
2008 }
2009 
ToString(const EcmaVM * vm)2010 Local<StringRef> DateRef::ToString(const EcmaVM *vm)
2011 {
2012     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2013     JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
2014     LOG_IF_SPECIAL(date, ERROR);
2015     JSTaggedValue dateStr = date->ToString(thread);
2016     if (!dateStr.IsString()) {
2017         auto constants = thread->GlobalConstants();
2018         return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
2019     }
2020     JSHandle<JSTaggedValue> dateStrHandle(thread, dateStr);
2021     return JSNApiHelper::ToLocal<StringRef>(dateStrHandle);
2022 }
2023 
GetTime()2024 double DateRef::GetTime()
2025 {
2026     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0.0);
2027     JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
2028     if (!date->IsDate()) {
2029         LOG_ECMA(ERROR) << "Not a Date Object";
2030     }
2031     return date->GetTime().GetDouble();
2032 }
2033 
2034 // ---------------------------------- TypedArray -----------------------------------
ByteLength(const EcmaVM * vm)2035 uint32_t TypedArrayRef::ByteLength([[maybe_unused]] const EcmaVM *vm)
2036 {
2037     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
2038     JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
2039     LOG_IF_SPECIAL(typedArray, FATAL);
2040     return typedArray->GetByteLength();
2041 }
2042 
ByteOffset(const EcmaVM * vm)2043 uint32_t TypedArrayRef::ByteOffset([[maybe_unused]] const EcmaVM *vm)
2044 {
2045     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
2046     JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
2047     LOG_IF_SPECIAL(typedArray, FATAL);
2048     return typedArray->GetByteOffset();
2049 }
2050 
ArrayLength(const EcmaVM * vm)2051 uint32_t TypedArrayRef::ArrayLength([[maybe_unused]] const EcmaVM *vm)
2052 {
2053     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
2054     JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
2055     LOG_IF_SPECIAL(typedArray, FATAL);
2056     return typedArray->GetArrayLength();
2057 }
2058 
GetArrayBuffer(const EcmaVM * vm)2059 Local<ArrayBufferRef> TypedArrayRef::GetArrayBuffer(const EcmaVM *vm)
2060 {
2061     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2062     JSHandle<JSTypedArray> typeArray(JSNApiHelper::ToJSHandle(this));
2063     LOG_IF_SPECIAL(typeArray, ERROR);
2064     JSHandle<JSTaggedValue> arrayBuffer(thread, JSTypedArray::GetOffHeapBuffer(thread, typeArray));
2065     return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
2066 }
2067 
2068 // ----------------------------------- FunctionRef --------------------------------------
New(EcmaVM * vm,FunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)2069 Local<FunctionRef> FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc,
2070     Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
2071 {
2072     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2073     ObjectFactory *factory = vm->GetFactory();
2074     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
2075     JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback)));
2076     current->SetFunctionExtraInfo(thread, reinterpret_cast<void *>(nativeFunc), deleter, data, nativeBindingsize);
2077     current->SetCallNapi(callNapi);
2078     return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
2079 }
2080 
New(EcmaVM * vm,InternalFunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)2081 Local<FunctionRef> FunctionRef::New(EcmaVM *vm, InternalFunctionCallback nativeFunc,
2082     Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
2083 {
2084     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2085     ObjectFactory *factory = vm->GetFactory();
2086     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
2087     JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(nativeFunc)));
2088     current->SetFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize);
2089     current->SetCallNapi(callNapi);
2090     return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
2091 }
2092 
InitClassFunction(EcmaVM * vm,JSHandle<JSFunction> & func,bool callNapi)2093 static void InitClassFunction(EcmaVM *vm, JSHandle<JSFunction> &func, bool callNapi)
2094 {
2095     CROSS_THREAD_CHECK(vm);
2096     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
2097     auto globalConst = thread->GlobalConstants();
2098     JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor();
2099     func->SetPropertyInlinedProps(thread, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX,
2100                                   accessor.GetTaggedValue());
2101     accessor = globalConst->GetHandledFunctionLengthAccessor();
2102     func->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX,
2103                                   accessor.GetTaggedValue());
2104     JSHandle<JSObject> clsPrototype = JSFunction::NewJSFunctionPrototype(thread, func);
2105     clsPrototype->GetClass()->SetClassPrototype(true);
2106     func->SetClassConstructor(true);
2107     JSHandle<JSTaggedValue> parent = env->GetFunctionPrototype();
2108     JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(func), parent);
2109     func->SetHomeObject(thread, clsPrototype);
2110     func->SetCallNapi(callNapi);
2111 }
2112 
NewClassFunction(EcmaVM * vm,FunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)2113 Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, FunctionCallback nativeFunc,
2114     Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
2115 {
2116     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2117     EscapeLocalScope scope(vm);
2118     ObjectFactory *factory = vm->GetFactory();
2119     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
2120     JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName());
2121     JSHandle<JSFunction> current =
2122         factory->NewJSFunctionByHClass(reinterpret_cast<void *>(Callback::RegisterCallback),
2123         hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
2124     InitClassFunction(vm, current, callNapi);
2125     current->SetFunctionExtraInfo(thread, reinterpret_cast<void *>(nativeFunc), deleter, data, nativeBindingsize);
2126     Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
2127     return scope.Escape(result);
2128 }
2129 
NewClassFunction(EcmaVM * vm,InternalFunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)2130 Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, InternalFunctionCallback nativeFunc,
2131     Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
2132 {
2133     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2134     EscapeLocalScope scope(vm);
2135     ObjectFactory *factory = vm->GetFactory();
2136     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
2137     JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName());
2138     JSHandle<JSFunction> current =
2139         factory->NewJSFunctionByHClass(reinterpret_cast<void *>(nativeFunc),
2140         hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
2141     InitClassFunction(vm, current, callNapi);
2142     current->SetFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingsize);
2143     Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
2144     return scope.Escape(result);
2145 }
2146 
Call(const EcmaVM * vm,Local<JSValueRef> thisObj,const Local<JSValueRef> argv[],int32_t length)2147 Local<JSValueRef> FunctionRef::Call(const EcmaVM *vm, Local<JSValueRef> thisObj,
2148     const Local<JSValueRef> argv[],  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
2149     int32_t length)
2150 {
2151     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2152     EscapeLocalScope scope(vm);
2153     FunctionCallScope callScope(EcmaVM::ConstCast(vm));
2154     if (!IsFunction()) {
2155         return JSValueRef::Undefined(vm);
2156     }
2157     vm->GetJsDebuggerManager()->ClearSingleStepper();
2158     JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
2159     LOG_IF_SPECIAL(func, ERROR);
2160     JSHandle<JSTaggedValue> thisValue = JSNApiHelper::ToJSHandle(thisObj);
2161     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2162     EcmaRuntimeCallInfo *info =
2163         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, length);
2164     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2165     for (int32_t i = 0; i < length; i++) {
2166         JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]);
2167         info->SetCallArg(i, arg.GetTaggedValue());
2168     }
2169     JSTaggedValue result = JSFunction::Call(info);
2170     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2171     JSHandle<JSTaggedValue> resultValue(thread, result);
2172 
2173     vm->GetHeap()->ClearKeptObjects();
2174     vm->GetJsDebuggerManager()->NotifyReturnNative();
2175     return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
2176 }
2177 
CallForNapi(const EcmaVM * vm,JSValueRef * thisObj,JSValueRef * const argv[],int32_t length)2178 JSValueRef* FunctionRef::CallForNapi(const EcmaVM *vm, JSValueRef *thisObj,
2179     JSValueRef *const argv[],  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
2180     int32_t length)
2181 {
2182     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, *JSValueRef::Undefined(vm));
2183     JSTaggedValue result;
2184     FunctionCallScope callScope(EcmaVM::ConstCast(vm));
2185     ASSERT(IsFunction()); // IsFunction check has been done in napi.
2186     {
2187         LocalScope scope(vm);
2188         ecmascript::tooling::JsDebuggerManager *dm = vm->GetJsDebuggerManager();
2189         if (dm->IsDebugApp()) {
2190             dm->ClearSingleStepper();
2191         }
2192         JSTaggedValue func = *reinterpret_cast<JSTaggedValue *>(this);
2193         JSTaggedValue undefined = thread->GlobalConstants()->GetUndefined();
2194         JSTaggedValue thisValue = undefined;
2195         if (thisObj != nullptr) {
2196             thisValue = *reinterpret_cast<JSTaggedValue *>(thisObj);
2197         }
2198         EcmaRuntimeCallInfo *info =
2199             ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, length);
2200         RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
2201         for (int32_t i = 0; i < length; i++) {
2202             JSTaggedValue arg =
2203                 argv[i] == nullptr ? JSTaggedValue::Undefined() : JSNApiHelper::ToJSTaggedValue(argv[i]);
2204             info->SetCallArg(i, arg);
2205         }
2206         if (thread->IsAsmInterpreter()) {
2207             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread,
2208                 reinterpret_cast<JSValueRef *>(JSHandle<JSTaggedValue>(thread, thread->GetException()).GetAddress()));
2209             STACK_LIMIT_CHECK(thread,
2210                 reinterpret_cast<JSValueRef *>(JSHandle<JSTaggedValue>(thread, thread->GetException()).GetAddress()));
2211             auto *hclass = func.GetTaggedObject()->GetClass();
2212             if (hclass->IsClassConstructor()) {
2213                 RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
2214                 THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot call",
2215                     reinterpret_cast<JSValueRef *>(JSHandle<JSTaggedValue>(thread, undefined).GetAddress()));
2216             }
2217             result = ecmascript::InterpreterAssembly::Execute(info);
2218         } else {
2219             result = JSFunction::Call(info);
2220         }
2221         RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
2222         vm->GetHeap()->ClearKeptObjects();
2223         if (dm->IsMixedDebugEnabled()) {
2224             dm->NotifyReturnNative();
2225         }
2226     }
2227     JSHandle<JSTaggedValue> resultValue(thread, result);
2228     return reinterpret_cast<JSValueRef *>(resultValue.GetAddress());
2229 }
2230 
Constructor(const EcmaVM * vm,const Local<JSValueRef> argv[],int32_t length)2231 Local<JSValueRef> FunctionRef::Constructor(const EcmaVM *vm,
2232     const Local<JSValueRef> argv[],  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
2233     int32_t length)
2234 {
2235     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2236     FunctionCallScope callScope(EcmaVM::ConstCast(vm));
2237     if (!IsFunction()) {
2238         return JSValueRef::Undefined(vm);
2239     }
2240     JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
2241     LOG_IF_SPECIAL(func, ERROR);
2242     JSHandle<JSTaggedValue> newTarget = func;
2243     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2244     EcmaRuntimeCallInfo *info =
2245         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, newTarget, length);
2246     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2247     for (int32_t i = 0; i < length; i++) {
2248         JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]);
2249         info->SetCallArg(i, arg.GetTaggedValue());
2250     }
2251     JSTaggedValue result = JSFunction::Construct(info);
2252 
2253     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2254     JSHandle<JSTaggedValue> resultValue(thread, result);
2255     return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
2256 }
2257 
ConstructorOptimize(const EcmaVM * vm,JSValueRef * argv[],int32_t length)2258 JSValueRef* FunctionRef::ConstructorOptimize(const EcmaVM *vm,
2259     JSValueRef* argv[],  // NOLINTNEXTLINE(modernize-avoid-c-arrays)
2260     int32_t length)
2261 {
2262     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, *JSValueRef::Undefined(vm));
2263     JSTaggedValue result;
2264     FunctionCallScope callScope(EcmaVM::ConstCast(vm));
2265     ASSERT(IsFunction()); // IsFunction check has been done in napi.
2266     {
2267         LocalScope scope(vm);
2268         JSTaggedValue func = *reinterpret_cast<JSTaggedValue*>(this);
2269         JSTaggedValue newTarget = func;
2270         JSTaggedValue undefined = thread->GlobalConstants()->GetUndefined();
2271         EcmaRuntimeCallInfo *info =
2272             ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, newTarget, length);
2273         RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
2274         for (int32_t i = 0; i < length; ++i) {
2275             JSTaggedValue arg =
2276                 argv[i] == nullptr ? JSTaggedValue::Undefined() : JSNApiHelper::ToJSTaggedValue(argv[i]);
2277             info->SetCallArg(i, arg);
2278         }
2279         result = JSFunction::ConstructInternal(info);
2280         RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
2281     }
2282     JSHandle<JSTaggedValue> resultValue(thread, result);
2283     return reinterpret_cast<JSValueRef*>(resultValue.GetAddress());
2284 }
2285 
GetFunctionPrototype(const EcmaVM * vm)2286 Local<JSValueRef> FunctionRef::GetFunctionPrototype(const EcmaVM *vm)
2287 {
2288     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2289     JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
2290     LOG_IF_SPECIAL(func, FATAL);
2291     JSHandle<JSTaggedValue> prototype(thread, JSHandle<JSFunction>(func)->GetFunctionPrototype());
2292     return JSNApiHelper::ToLocal<JSValueRef>(prototype);
2293 }
2294 
Inherit(const EcmaVM * vm,Local<FunctionRef> parent)2295 bool FunctionRef::Inherit(const EcmaVM *vm, Local<FunctionRef> parent)
2296 {
2297     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
2298     [[maybe_unused]] LocalScope scope(vm);
2299     JSHandle<JSTaggedValue> parentValue = JSNApiHelper::ToJSHandle(parent);
2300     JSHandle<JSObject> parentHandle = JSHandle<JSObject>::Cast(parentValue);
2301     JSHandle<JSObject> thisHandle = JSHandle<JSObject>::Cast(JSNApiHelper::ToJSHandle(this));
2302     LOG_IF_SPECIAL(thisHandle, ERROR);
2303     // Set this.__proto__ to parent
2304     bool res = JSObject::SetPrototype(thread, thisHandle, parentValue);
2305     if (!res) {
2306         return false;
2307     }
2308     // Set this.Prototype.__proto__ to parent.Prototype
2309     JSHandle<JSTaggedValue> parentProtoType(thread, JSFunction::PrototypeGetter(thread, parentHandle));
2310     JSHandle<JSTaggedValue> thisProtoType(thread, JSFunction::PrototypeGetter(thread, thisHandle));
2311     return JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(thisProtoType), parentProtoType);
2312 }
2313 
SetName(const EcmaVM * vm,Local<StringRef> name)2314 void FunctionRef::SetName(const EcmaVM *vm, Local<StringRef> name)
2315 {
2316     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
2317     [[maybe_unused]] LocalScope scope(vm);
2318     JSFunction *func = JSFunction::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject());
2319     JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
2320     JSFunction::SetFunctionNameNoPrefix(thread, func, key);
2321 }
2322 
GetName(const EcmaVM * vm)2323 Local<StringRef> FunctionRef::GetName(const EcmaVM *vm)
2324 {
2325     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2326     EscapeLocalScope scope(vm);
2327     JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this));
2328     JSHandle<JSTaggedValue> name = JSFunctionBase::GetFunctionName(thread, func);
2329     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2330     return scope.Escape(JSNApiHelper::ToLocal<StringRef>(name));
2331 }
2332 
GetSourceCode(const EcmaVM * vm,int lineNumber)2333 Local<StringRef> FunctionRef::GetSourceCode(const EcmaVM *vm, int lineNumber)
2334 {
2335     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2336     EscapeLocalScope scope(vm);
2337     JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this));
2338     JSHandle<Method> method(thread, func->GetMethod());
2339     const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
2340     DebugInfoExtractor *debugExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile);
2341     ecmascript::CString entry = JSPandaFile::ENTRY_FUNCTION_NAME;
2342     if (!jsPandaFile->IsBundlePack()) {
2343         JSTaggedValue recordName = method->GetRecordName();
2344         ASSERT(!recordName.IsHole());
2345         entry = ConvertToString(recordName);
2346     }
2347 
2348     uint32_t mainMethodIndex = jsPandaFile->GetMainMethodIndex(entry);
2349     JSMutableHandle<JSTaggedValue> sourceCodeHandle(thread, BuiltinsBase::GetTaggedString(thread, ""));
2350     if (mainMethodIndex == 0) {
2351         return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
2352     }
2353 
2354     const std::string &allSourceCode = debugExtractor->GetSourceCode(panda_file::File::EntityId(mainMethodIndex));
2355     std::string sourceCode = StringHelper::GetSpecifiedLine(allSourceCode, lineNumber);
2356     uint32_t codeLen = sourceCode.length();
2357     if (codeLen == 0) {
2358         return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
2359     }
2360 
2361     if (sourceCode[codeLen - 1] == '\r') {
2362         sourceCode = sourceCode.substr(0, codeLen - 1);
2363     }
2364     sourceCodeHandle.Update(BuiltinsBase::GetTaggedString(thread, sourceCode.c_str()));
2365     return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
2366 }
2367 
IsNative(const EcmaVM * vm)2368 bool FunctionRef::IsNative(const EcmaVM *vm)
2369 {
2370     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
2371     JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this));
2372     JSHandle<Method> method(thread, func->GetMethod());
2373     return method->IsNativeWithCallField();
2374 }
2375 
SetData(const EcmaVM * vm,void * data,Deleter deleter,bool callNapi)2376 void FunctionRef::SetData(const EcmaVM *vm, void *data, Deleter deleter, bool callNapi)
2377 {
2378     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
2379     JSHandle<JSTaggedValue> funcValue = JSNApiHelper::ToJSHandle(this);
2380     JSHandle<JSFunction> function(funcValue);
2381     function->SetFunctionExtraInfo(thread, nullptr, deleter, data, 0);
2382     function->SetCallNapi(callNapi);
2383 }
2384 
GetData(const EcmaVM * vm)2385 void* FunctionRef::GetData(const EcmaVM *vm)
2386 {
2387     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
2388     JSHandle<JSTaggedValue> funcValue = JSNApiHelper::ToJSHandle(this);
2389     JSHandle<JSFunction> function(funcValue);
2390     if (!function->IsCallNapi()) {
2391         return nullptr;
2392     }
2393     JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo();
2394     if (!extraInfoValue.IsNativePointer()) {
2395         return nullptr;
2396     }
2397     JSHandle<JSNativePointer> extraInfo(thread, extraInfoValue);
2398     return extraInfo->GetData();
2399 }
2400 
2401 // ----------------------------------- ArrayRef ----------------------------------------
New(const EcmaVM * vm,uint32_t length)2402 Local<ArrayRef> ArrayRef::New(const EcmaVM *vm, uint32_t length)
2403 {
2404     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2405     JSTaggedNumber arrayLen(length);
2406     JSHandle<JSTaggedValue> array = JSArray::ArrayCreate(thread, arrayLen);
2407     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2408     return JSNApiHelper::ToLocal<ArrayRef>(array);
2409 }
2410 
Length(const EcmaVM * vm)2411 uint32_t ArrayRef::Length([[maybe_unused]] const EcmaVM *vm)
2412 {
2413     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
2414     return JSArray::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetArrayLength();
2415 }
2416 
GetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index)2417 Local<JSValueRef> ArrayRef::GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index)
2418 {
2419     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
2420     JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(obj);
2421     JSHandle<JSTaggedValue> result = JSArray::FastGetPropertyByValue(thread, object, index);
2422     return JSNApiHelper::ToLocal<JSValueRef>(result);
2423 }
2424 
SetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index,Local<JSValueRef> value)2425 bool ArrayRef::SetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value)
2426 {
2427     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
2428     JSHandle<JSTaggedValue> objectHandle = JSNApiHelper::ToJSHandle(obj);
2429     JSHandle<JSTaggedValue> valueHandle = JSNApiHelper::ToJSHandle(value);
2430     return JSArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle);
2431 }
2432 
2433 // ---------------------------------- Error ---------------------------------------
2434 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
2435 #define EXCEPTION_ERROR_NEW(name, type)                                                     \
2436     Local<JSValueRef> Exception::name(const EcmaVM *vm, Local<StringRef> message)           \
2437     {                                                                                       \
2438         CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));        \
2439         ObjectFactory *factory = vm->GetFactory();                                          \
2440                                                                                             \
2441         JSHandle<EcmaString> messageValue(JSNApiHelper::ToJSHandle(message));               \
2442         JSHandle<JSTaggedValue> result(factory->NewJSError(ErrorType::type, messageValue)); \
2443         return JSNApiHelper::ToLocal<JSValueRef>(result);                                   \
2444     }
2445 
EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)2446 EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)
2447 
2448 #undef EXCEPTION_ERROR_NEW
2449 // ---------------------------------- Error ---------------------------------------
2450 
2451 // ---------------------------------- FunctionCallScope ---------------------------------------
2452 FunctionCallScope::FunctionCallScope(EcmaVM *vm) : vm_(vm)
2453 {
2454     vm_->IncreaseCallDepth();
2455 }
2456 
~FunctionCallScope()2457 FunctionCallScope::~FunctionCallScope()
2458 {
2459     vm_->DecreaseCallDepth();
2460     if (vm_->IsTopLevelCallDepth()) {
2461         JSThread *thread = vm_->GetJSThread();
2462         thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
2463     }
2464 }
2465 
2466 // -------------------------------------  JSExecutionScope ------------------------------
JSExecutionScope(const EcmaVM * vm)2467 JSExecutionScope::JSExecutionScope([[maybe_unused]] const EcmaVM *vm)
2468 {
2469 }
2470 
~JSExecutionScope()2471 JSExecutionScope::~JSExecutionScope()
2472 {
2473     lastCurrentThread_ = nullptr;
2474     isRevert_ = false;
2475 }
2476 
2477 // ------------------------------------ JsiRuntimeCallInfo -----------------------------------------------
GetData()2478 void *JsiRuntimeCallInfo::GetData()
2479 {
2480     JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(reinterpret_cast<EcmaRuntimeCallInfo *>(this));
2481     if (!constructor->IsJSFunction()) {
2482         return nullptr;
2483     }
2484     JSHandle<JSFunction> function(constructor);
2485     JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo();
2486     if (!extraInfoValue.IsJSNativePointer()) {
2487         return nullptr;
2488     }
2489     JSHandle<JSNativePointer> extraInfo(thread_, extraInfoValue);
2490     return extraInfo->GetData();
2491 }
2492 
GetVM() const2493 EcmaVM *JsiRuntimeCallInfo::GetVM() const
2494 {
2495     return thread_->GetEcmaVM();
2496 }
2497 
2498 // ---------------------------------------JSNApi-------------------------------------------
LoadPatch(EcmaVM * vm,const std::string & patchFileName,const std::string & baseFileName)2499 PatchErrorCode JSNApi::LoadPatch(EcmaVM *vm, const std::string &patchFileName, const std::string &baseFileName)
2500 {
2501     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, PatchErrorCode::INTERNAL_ERROR);
2502     ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2503     return quickFixManager->LoadPatch(thread, patchFileName, baseFileName);
2504 }
2505 
LoadPatch(EcmaVM * vm,const std::string & patchFileName,const void * patchBuffer,size_t patchSize,const std::string & baseFileName,const void * baseBuffer,size_t baseSize)2506 PatchErrorCode JSNApi::LoadPatch(EcmaVM *vm,
2507                                  const std::string &patchFileName, const void *patchBuffer, size_t patchSize,
2508                                  const std::string &baseFileName, const void *baseBuffer, size_t baseSize)
2509 {
2510     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, PatchErrorCode::INTERNAL_ERROR);
2511     ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2512     return quickFixManager->LoadPatch(
2513         thread, patchFileName, patchBuffer, patchSize, baseFileName, baseBuffer, baseSize);
2514 }
2515 
UnloadPatch(EcmaVM * vm,const std::string & patchFileName)2516 PatchErrorCode JSNApi::UnloadPatch(EcmaVM *vm, const std::string &patchFileName)
2517 {
2518     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, PatchErrorCode::INTERNAL_ERROR);
2519     ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2520     return quickFixManager->UnloadPatch(thread, patchFileName);
2521 }
2522 
2523 /*
2524  * check whether the exception is caused by quickfix methods.
2525  */
IsQuickFixCausedException(EcmaVM * vm,Local<ObjectRef> exception,const std::string & patchFileName)2526 bool JSNApi::IsQuickFixCausedException(EcmaVM *vm, Local<ObjectRef> exception, const std::string &patchFileName)
2527 {
2528     if (exception.IsEmpty()) {
2529         return false;
2530     }
2531     CROSS_THREAD_CHECK(vm);
2532     ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2533     JSHandle<JSTaggedValue> exceptionInfo = JSNApiHelper::ToJSHandle(exception);
2534     return quickFixManager->IsQuickFixCausedException(thread, exceptionInfo, patchFileName);
2535 }
2536 
2537 /*
2538  * register quickfix query function.
2539  */
RegisterQuickFixQueryFunc(EcmaVM * vm,std::function<bool (std::string baseFileName,std::string & patchFileName,void ** patchBuffer,size_t & patchSize)> callBack)2540 void JSNApi::RegisterQuickFixQueryFunc(EcmaVM *vm, std::function<bool(std::string baseFileName,
2541                         std::string &patchFileName,
2542                         void **patchBuffer,
2543                         size_t &patchSize)> callBack)
2544 {
2545     CROSS_THREAD_CHECK(vm);
2546     ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2547     quickFixManager->RegisterQuickFixQueryFunc(callBack);
2548 }
2549 
IsBundle(EcmaVM * vm)2550 bool JSNApi::IsBundle(EcmaVM *vm)
2551 {
2552     return vm->IsBundlePack();
2553 }
2554 
SetBundle(EcmaVM * vm,bool value)2555 void JSNApi::SetBundle(EcmaVM *vm, bool value)
2556 {
2557     vm->SetIsBundlePack(value);
2558 }
2559 
SetModuleInfo(EcmaVM * vm,const std::string & assetPath,const std::string & entryPoint)2560 void JSNApi::SetModuleInfo(EcmaVM *vm, const std::string &assetPath, const std::string &entryPoint)
2561 {
2562     SetAssetPath(vm, assetPath);
2563     size_t pos = entryPoint.find_first_of("/");
2564     if (pos != std::string::npos) {
2565         SetBundleName(vm, entryPoint.substr(0, pos));
2566         ecmascript::CString moduleName = ModulePathHelper::GetModuleName(entryPoint.c_str());
2567         if (!moduleName.empty()) {
2568             SetModuleName(vm, moduleName.c_str());
2569             return;
2570         }
2571     }
2572     std::string errmsg = "SetModuleInfo: entryPoint:" + entryPoint + "is invalid.";
2573     LOG_ECMA(ERROR) << errmsg;
2574     Local<StringRef> message = StringRef::NewFromUtf8(vm, errmsg.c_str());
2575     Local<JSValueRef> error = Exception::Error(vm, message);
2576     JSNApi::ThrowException(vm, error);
2577 }
2578 
2579 // note: The function SetAssetPath is a generic interface for previewing and physical machines.
SetAssetPath(EcmaVM * vm,const std::string & assetPath)2580 void JSNApi::SetAssetPath(EcmaVM *vm, const std::string &assetPath)
2581 {
2582     ecmascript::CString path = assetPath.c_str();
2583     vm->SetAssetPath(path);
2584 }
2585 
SetLoop(EcmaVM * vm,void * loop)2586 void JSNApi::SetLoop(EcmaVM *vm, void *loop)
2587 {
2588     vm->SetLoop(loop);
2589 }
2590 
GetAssetPath(EcmaVM * vm)2591 std::string JSNApi::GetAssetPath(EcmaVM *vm)
2592 {
2593     return vm->GetAssetPath().c_str();
2594 }
2595 
SetMockModuleList(EcmaVM * vm,const std::map<std::string,std::string> & list)2596 void JSNApi::SetMockModuleList(EcmaVM *vm, const std::map<std::string, std::string> &list)
2597 {
2598     vm->SetMockModuleList(list);
2599 }
2600 
SetHmsModuleList(EcmaVM * vm,const std::vector<panda::HmsMap> & list)2601 void JSNApi::SetHmsModuleList(EcmaVM *vm, const std::vector<panda::HmsMap> &list)
2602 {
2603     vm->SetHmsModuleList(list);
2604 }
2605 
InitForConcurrentThread(EcmaVM * vm,ConcurrentCallback cb,void * data)2606 bool JSNApi::InitForConcurrentThread(EcmaVM *vm, ConcurrentCallback cb, void *data)
2607 {
2608     vm->SetConcurrentCallback(cb, data);
2609 
2610     return true;
2611 }
2612 
InitForConcurrentFunction(EcmaVM * vm,Local<JSValueRef> function,void * taskInfo)2613 bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local<JSValueRef> function, void *taskInfo)
2614 {
2615     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
2616     [[maybe_unused]] LocalScope scope(vm);
2617     JSHandle<JSTaggedValue> funcVal = JSNApiHelper::ToJSHandle(function);
2618     JSHandle<JSFunction> transFunc = JSHandle<JSFunction>::Cast(funcVal);
2619     if (transFunc->GetFunctionKind() != ecmascript::FunctionKind::CONCURRENT_FUNCTION) {
2620         LOG_ECMA(ERROR) << "Function is not concurrent";
2621         return false;
2622     }
2623     transFunc->SetFunctionExtraInfo(thread, nullptr, nullptr, taskInfo);
2624     transFunc->SetCallNapi(false);
2625     return true;
2626 }
2627 
GetCurrentTaskInfo(const EcmaVM * vm)2628 void* JSNApi::GetCurrentTaskInfo(const EcmaVM *vm)
2629 {
2630     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
2631     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
2632     ecmascript::FrameIterator it(current, thread);
2633     for (; !it.Done(); it.Advance<ecmascript::GCVisitedFlag::VISITED>()) {
2634         if (!it.IsJSFrame()) {
2635             continue;
2636         }
2637         auto method = it.CheckAndGetMethod();
2638         if (method == nullptr || method->IsNativeWithCallField() ||
2639             method->GetFunctionKind() != ecmascript::FunctionKind::CONCURRENT_FUNCTION) {
2640             continue;
2641         }
2642         auto functionObj = it.GetFunction();
2643         JSHandle<JSFunction> function(thread, functionObj);
2644         JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo();
2645         if (!extraInfoValue.IsJSNativePointer()) {
2646             LOG_ECMA(DEBUG) << "Concurrent function donnot have taskInfo";
2647             continue;
2648         }
2649         JSHandle<JSNativePointer> extraInfo(thread, extraInfoValue);
2650         return extraInfo->GetData();
2651     }
2652     LOG_ECMA(ERROR) << "TaskInfo is nullptr";
2653     return nullptr;
2654 }
2655 
SetBundleName(EcmaVM * vm,const std::string & bundleName)2656 void JSNApi::SetBundleName(EcmaVM *vm, const std::string &bundleName)
2657 {
2658     ecmascript::CString name = bundleName.c_str();
2659     vm->SetBundleName(name);
2660 }
2661 
GetBundleName(EcmaVM * vm)2662 std::string JSNApi::GetBundleName(EcmaVM *vm)
2663 {
2664     return vm->GetBundleName().c_str();
2665 }
2666 
SetModuleName(EcmaVM * vm,const std::string & moduleName)2667 void JSNApi::SetModuleName(EcmaVM *vm, const std::string &moduleName)
2668 {
2669     ecmascript::CString name = moduleName.c_str();
2670     ecmascript::pgo::PGOProfilerManager::GetInstance()->SetModuleName(moduleName);
2671     vm->SetModuleName(name);
2672 }
2673 
GetModuleName(EcmaVM * vm)2674 std::string JSNApi::GetModuleName(EcmaVM *vm)
2675 {
2676     return vm->GetModuleName().c_str();
2677 }
2678 
GetCurrentModuleInfo(EcmaVM * vm,bool needRecordName)2679 std::pair<std::string, std::string> JSNApi::GetCurrentModuleInfo(EcmaVM *vm, bool needRecordName)
2680 {
2681     return vm->GetCurrentModuleInfo(needRecordName);
2682 }
2683 
2684 // Enable cross thread execution.
AllowCrossThreadExecution(EcmaVM * vm)2685 void JSNApi::AllowCrossThreadExecution(EcmaVM *vm)
2686 {
2687     vm->GetAssociatedJSThread()->EnableCrossThreadExecution();
2688 }
2689 
SynchronizVMInfo(EcmaVM * vm,const EcmaVM * hostVM)2690 void JSNApi::SynchronizVMInfo(EcmaVM *vm, const EcmaVM *hostVM)
2691 {
2692     vm->SetBundleName(hostVM->GetBundleName());
2693     vm->SetModuleName(hostVM->GetModuleName());
2694     vm->SetAssetPath(hostVM->GetAssetPath());
2695     vm->SetIsBundlePack(hostVM->IsBundlePack());
2696 
2697     ecmascript::ModuleManager *vmModuleManager =
2698         vm->GetAssociatedJSThread()->GetCurrentEcmaContext()->GetModuleManager();
2699     ecmascript::ModuleManager *hostVMModuleManager =
2700         hostVM->GetAssociatedJSThread()->GetCurrentEcmaContext()->GetModuleManager();
2701     vmModuleManager->SetExecuteMode(hostVMModuleManager->GetExecuteMode());
2702     vm->SetResolveBufferCallback(hostVM->GetResolveBufferCallback());
2703 }
2704 
IsProfiling(EcmaVM * vm)2705 bool JSNApi::IsProfiling(EcmaVM *vm)
2706 {
2707     return vm->GetProfilerState();
2708 }
2709 
SetProfilerState(const EcmaVM * vm,bool value)2710 void JSNApi::SetProfilerState(const EcmaVM *vm, bool value)
2711 {
2712     const_cast<EcmaVM*>(vm)->SetProfilerState(value);
2713 }
2714 
SetSourceMapTranslateCallback(EcmaVM * vm,SourceMapTranslateCallback callback)2715 void JSNApi::SetSourceMapTranslateCallback(EcmaVM *vm, SourceMapTranslateCallback callback)
2716 {
2717     vm->SetSourceMapTranslateCallback(callback);
2718 }
2719 
SetSourceMapCallback(EcmaVM * vm,SourceMapCallback callback)2720 void JSNApi::SetSourceMapCallback(EcmaVM *vm, SourceMapCallback callback)
2721 {
2722     vm->SetSourceMapCallback(callback);
2723 }
2724 
GetStackBeforeCallNapiSuccess(EcmaVM * vm,bool & getStackBeforeCallNapiSuccess)2725 void JSNApi::GetStackBeforeCallNapiSuccess([[maybe_unused]] EcmaVM *vm,
2726                                            [[maybe_unused]] bool &getStackBeforeCallNapiSuccess)
2727 {
2728 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
2729     JSThread *thread = vm->GetJSThread();
2730     if (thread->GetIsProfiling()) {
2731         getStackBeforeCallNapiSuccess = vm->GetProfiler()->GetStackBeforeCallNapi(thread);
2732     }
2733 #endif
2734 }
2735 
GetStackAfterCallNapi(EcmaVM * vm)2736 void JSNApi::GetStackAfterCallNapi([[maybe_unused]] EcmaVM *vm)
2737 {
2738 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
2739     JSThread *thread = vm->GetJSThread();
2740     if (thread->GetIsProfiling()) {
2741         vm->GetProfiler()->GetStackAfterCallNapi(thread);
2742     }
2743 #endif
2744 }
2745 
CheckSecureMem(uintptr_t mem)2746 bool JSNApi::CheckSecureMem(uintptr_t mem)
2747 {
2748     static bool hasOpen = false;
2749     static uintptr_t secureMemStart = 0;
2750     static uintptr_t secureMemEnd = 0;
2751     if (!hasOpen) {
2752         int fd = open(PROC_SELF_XPM_REGION_PATH, O_RDONLY);
2753         if (fd < 0) {
2754             LOG_ECMA(ERROR) << "Can not open xpm proc file, do not check secure memory anymore.";
2755             // No verification is performed when a file fails to be opened.
2756             hasOpen = true;
2757             return true;
2758         }
2759 
2760         char xpmValidateRegion[XPM_PROC_LENGTH] = {0};
2761         int ret = read(fd, xpmValidateRegion, sizeof(xpmValidateRegion));
2762         if (ret <= 0) {
2763             LOG_ECMA(ERROR) << "Read xpm proc file failed";
2764             close(fd);
2765             return false;
2766         }
2767         close(fd);
2768 
2769         if (sscanf_s(xpmValidateRegion, "%lx-%lx", &secureMemStart, &secureMemEnd) <= 0) {
2770             LOG_ECMA(ERROR) << "sscanf_s xpm validate region failed";
2771             return false;
2772         }
2773         // The check is not performed when the file is already opened.
2774         hasOpen = true;
2775     }
2776 
2777     // xpm proc does not exist, the read value is 0, and the check is not performed.
2778     if (secureMemStart == 0 && secureMemEnd == 0) {
2779         LOG_ECMA(ERROR) << "Secure memory check: xpm proc does not exist, do not check secure memory anymore.";
2780         return true;
2781     }
2782 
2783     LOG_ECMA(DEBUG) << "Secure memory check in memory start: " << std::hex << secureMemStart
2784                    << " memory end: " << secureMemEnd;
2785     if (mem < secureMemStart || mem >= secureMemEnd) {
2786         LOG_ECMA(ERROR) << "Secure memory check failed, mem out of secure memory, mem: " << std::hex << mem;
2787         return false;
2788     }
2789     return true;
2790 }
2791 
CreateJSVM(const RuntimeOption & option)2792 EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option)
2793 {
2794     JSRuntimeOptions runtimeOptions;
2795     runtimeOptions.SetArkProperties(option.GetArkProperties());
2796     runtimeOptions.SetArkBundleName(option.GetArkBundleName());
2797     runtimeOptions.SetLongPauseTime(option.GetLongPauseTime());
2798     runtimeOptions.SetGcThreadNum(option.GetGcThreadNum());
2799     runtimeOptions.SetIsWorker(option.GetIsWorker());
2800     // Mem
2801     runtimeOptions.SetHeapSizeLimit(option.GetGcPoolSize());
2802 // Disable the asm-interpreter of ark-engine for ios-platform temporarily.
2803 #if !defined(PANDA_TARGET_IOS)
2804     // asmInterpreter
2805     runtimeOptions.SetEnableAsmInterpreter(option.GetEnableAsmInterpreter());
2806 #else
2807     runtimeOptions.SetEnableAsmInterpreter(false);
2808 #endif
2809     runtimeOptions.SetEnableBuiltinsLazy(option.GetEnableBuiltinsLazy());
2810     runtimeOptions.SetAsmOpcodeDisableRange(option.GetAsmOpcodeDisableRange());
2811     // aot
2812     runtimeOptions.SetEnableAOT(option.GetEnableAOT());
2813     runtimeOptions.SetEnablePGOProfiler(option.GetEnableProfile());
2814     runtimeOptions.SetPGOProfilerPath(option.GetProfileDir());
2815 
2816     // Dfx
2817     runtimeOptions.SetLogLevel(Log::LevelToString(Log::ConvertFromRuntime(option.GetLogLevel())));
2818     runtimeOptions.SetEnableArkTools(option.GetEnableArkTools());
2819     return CreateEcmaVM(runtimeOptions);
2820 }
2821 
CreateJSContext(EcmaVM * vm)2822 EcmaContext *JSNApi::CreateJSContext(EcmaVM *vm)
2823 {
2824     JSThread *thread = vm->GetJSThread();
2825     return EcmaContext::CreateAndInitialize(thread);
2826 }
2827 
SwitchCurrentContext(EcmaVM * vm,EcmaContext * context)2828 void JSNApi::SwitchCurrentContext(EcmaVM *vm, EcmaContext *context)
2829 {
2830     JSThread *thread = vm->GetJSThread();
2831     thread->SwitchCurrentContext(context);
2832 }
2833 
DestroyJSContext(EcmaVM * vm,EcmaContext * context)2834 void JSNApi::DestroyJSContext(EcmaVM *vm, EcmaContext *context)
2835 {
2836     JSThread *thread = vm->GetJSThread();
2837     EcmaContext::CheckAndDestroy(thread, context);
2838 }
2839 
CreateEcmaVM(const JSRuntimeOptions & options)2840 EcmaVM *JSNApi::CreateEcmaVM(const JSRuntimeOptions &options)
2841 {
2842     {
2843         LockHolder lock(*mutex);
2844         vmCount_++;
2845         if (!initialize_) {
2846             ecmascript::Log::Initialize(options);
2847             InitializeIcuData(options);
2848             InitializeMemMapAllocator();
2849             InitializePGOProfiler(options);
2850             initialize_ = true;
2851         }
2852     }
2853     auto config = ecmascript::EcmaParamConfiguration(options.IsWorker(),
2854         MemMapAllocator::GetInstance()->GetCapacity());
2855     LOG_ECMA(DEBUG) << " [NAPI]: CreateEcmaVM, isWorker = " << options.IsWorker() << ", vmCount = " << vmCount_;
2856     MemMapAllocator::GetInstance()->IncreaseAndCheckReserved(config.GetMaxHeapSize());
2857     return EcmaVM::Create(options, config);
2858 }
2859 
DestroyJSVM(EcmaVM * ecmaVm)2860 void JSNApi::DestroyJSVM(EcmaVM *ecmaVm)
2861 {
2862     LockHolder lock(*mutex);
2863     if (!initialize_) {
2864         return;
2865     }
2866     auto &config = ecmaVm->GetEcmaParamConfiguration();
2867     MemMapAllocator::GetInstance()->DecreaseReserved(config.GetMaxHeapSize());
2868     EcmaVM::Destroy(ecmaVm);
2869     vmCount_--;
2870     if (vmCount_ <= 0) {
2871         DestroyAnDataManager();
2872         DestroyMemMapAllocator();
2873         DestroyPGOProfiler();
2874         initialize_ = false;
2875     }
2876 }
2877 
RegisterUncatchableErrorHandler(EcmaVM * ecmaVm,const UncatchableErrorHandler & handler)2878 void JSNApi::RegisterUncatchableErrorHandler(EcmaVM *ecmaVm, const UncatchableErrorHandler &handler)
2879 {
2880     ecmaVm->RegisterUncatchableErrorHandler(handler);
2881 }
2882 
TriggerGC(const EcmaVM * vm,TRIGGER_GC_TYPE gcType)2883 void JSNApi::TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType)
2884 {
2885     CROSS_THREAD_CHECK(vm);
2886     if (thread != nullptr && vm->IsInitialized()) {
2887         switch (gcType) {
2888             case TRIGGER_GC_TYPE::SEMI_GC:
2889                 vm->CollectGarbage(vm->GetHeap()->SelectGCType(), ecmascript::GCReason::EXTERNAL_TRIGGER);
2890                 break;
2891             case TRIGGER_GC_TYPE::OLD_GC:
2892                 vm->CollectGarbage(ecmascript::TriggerGCType::OLD_GC, ecmascript::GCReason::EXTERNAL_TRIGGER);
2893                 break;
2894             case TRIGGER_GC_TYPE::FULL_GC:
2895                 vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC, ecmascript::GCReason::EXTERNAL_TRIGGER);
2896                 break;
2897             default:
2898                 break;
2899         }
2900     }
2901 }
2902 
ThrowException(const EcmaVM * vm,Local<JSValueRef> error)2903 void JSNApi::ThrowException(const EcmaVM *vm, Local<JSValueRef> error)
2904 {
2905     auto thread = vm->GetJSThread();
2906     if (thread->HasPendingException()) {
2907         LOG_ECMA(ERROR) << "An exception has already occurred before, keep old exception here.";
2908         return;
2909     }
2910     thread->SetException(JSNApiHelper::ToJSTaggedValue(*error));
2911 }
2912 
PrintExceptionInfo(const EcmaVM * vm)2913 void JSNApi::PrintExceptionInfo(const EcmaVM *vm)
2914 {
2915     JSThread* thread = vm->GetJSThread();
2916     [[maybe_unused]] ecmascript::EcmaHandleScope handleScope(thread);
2917 
2918     if (!HasPendingException(vm)) {
2919         return;
2920     }
2921     Local<ObjectRef> exception = GetAndClearUncaughtException(vm);
2922     JSHandle<JSTaggedValue> exceptionHandle = JSNApiHelper::ToJSHandle(exception);
2923     if (exceptionHandle->IsJSError()) {
2924         vm->PrintJSErrorInfo(exceptionHandle);
2925         ThrowException(vm, exception);
2926         return;
2927     }
2928     JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, exceptionHandle);
2929     ecmascript::CString string = ConvertToString(*result);
2930     LOG_ECMA(ERROR) << string;
2931     ThrowException(vm, exception);
2932 }
2933 
2934 // for previewer, cross platform and testcase debugger
StartDebugger(EcmaVM * vm,const DebugOption & option,int32_t instanceId,const DebuggerPostTask & debuggerPostTask)2935 bool JSNApi::StartDebugger([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] const DebugOption &option,
2936                            [[maybe_unused]] int32_t instanceId,
2937                            [[maybe_unused]] const DebuggerPostTask &debuggerPostTask)
2938 {
2939 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
2940 #if !defined(PANDA_TARGET_IOS)
2941     LOG_ECMA(INFO) << "JSNApi::StartDebugger, isDebugMode = " << option.isDebugMode
2942         << ", port = " << option.port << ", instanceId = " << instanceId;
2943     if (vm == nullptr) {
2944         return false;
2945     }
2946     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
2947     const auto &handler = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
2948     if (handler.IsValid()) {
2949         return false;
2950     }
2951 
2952     if (option.libraryPath == nullptr) {
2953         return false;
2954     }
2955     auto handle = panda::os::library_loader::Load(std::string(option.libraryPath));
2956     if (!handle) {
2957         LOG_ECMA(ERROR) << "[StartDebugger] Load library fail: " << option.libraryPath << " " << errno;
2958         return false;
2959     }
2960 
2961     using StartDebugger = bool (*)(
2962         const std::string &, EcmaVM *, bool, int32_t, const DebuggerPostTask &, int);
2963 
2964     auto sym = panda::os::library_loader::ResolveSymbol(handle.Value(), "StartDebug");
2965     if (!sym) {
2966         LOG_ECMA(ERROR) << "[StartDebugger] Resolve symbol fail: " << sym.Error().ToString();
2967         return false;
2968     }
2969 
2970     vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode);
2971     vm->GetJsDebuggerManager()->SetIsDebugApp(true);
2972     vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(handle.Value()));
2973     bool ret = reinterpret_cast<StartDebugger>(sym.Value())(
2974         "PandaDebugger", vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
2975     if (!ret) {
2976         // Reset the config
2977         vm->GetJsDebuggerManager()->SetDebugMode(false);
2978         panda::os::library_loader::LibraryHandle libraryHandle(nullptr);
2979         vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(libraryHandle));
2980     }
2981     return ret;
2982 #else
2983     if (vm == nullptr) {
2984         return false;
2985     }
2986     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
2987     vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode);
2988     bool ret = OHOS::ArkCompiler::Toolchain::StartDebug(
2989         DEBUGGER_NAME, vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
2990     if (!ret) {
2991         // Reset the config
2992         vm->GetJsDebuggerManager()->SetDebugMode(false);
2993     }
2994     return ret;
2995 #endif // PANDA_TARGET_IOS
2996 #else
2997     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
2998     return false;
2999 #endif // ECMASCRIPT_SUPPORT_DEBUGGER
3000 }
3001 
3002 // for old process.
StartDebuggerForOldProcess(EcmaVM * vm,const DebugOption & option,int32_t instanceId,const DebuggerPostTask & debuggerPostTask)3003 bool JSNApi::StartDebuggerForOldProcess([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] const DebugOption &option,
3004                                         [[maybe_unused]] int32_t instanceId,
3005                                         [[maybe_unused]] const DebuggerPostTask &debuggerPostTask)
3006 {
3007 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3008 #if !defined(PANDA_TARGET_IOS)
3009     LOG_ECMA(INFO) << "JSNApi::StartDebuggerForOldProcess, isDebugMode = " << option.isDebugMode
3010         << ", instanceId = " << instanceId;
3011     if (vm == nullptr) {
3012         return false;
3013     }
3014     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3015     const auto &handle = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
3016     if (!handle.IsValid()) {
3017         LOG_ECMA(ERROR) << "[StartDebuggerForOldProcess] Get library handle fail: " << option.libraryPath;
3018         return false;
3019     }
3020 
3021     using StartDebug = bool (*)(
3022         const std::string &, EcmaVM *, bool, int32_t, const DebuggerPostTask &, int);
3023 
3024     auto sym = panda::os::library_loader::ResolveSymbol(handle, "StartDebug");
3025     if (!sym) {
3026         LOG_ECMA(ERROR) << "[StartDebuggerForOldProcess] Resolve symbol fail: " << sym.Error().ToString();
3027         return false;
3028     }
3029 
3030     bool ret = reinterpret_cast<StartDebug>(sym.Value())(
3031         "PandaDebugger", vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
3032     if (!ret) {
3033         // Reset the config
3034         vm->GetJsDebuggerManager()->SetDebugMode(false);
3035         panda::os::library_loader::LibraryHandle libraryHandle(nullptr);
3036         vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(libraryHandle));
3037     }
3038     return ret;
3039 #else
3040     if (vm == nullptr) {
3041         return false;
3042     }
3043     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3044     vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode);
3045     bool ret = OHOS::ArkCompiler::Toolchain::StartDebug(
3046         DEBUGGER_NAME, vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
3047     if (!ret) {
3048         // Reset the config
3049         vm->GetJsDebuggerManager()->SetDebugMode(false);
3050     }
3051     return ret;
3052 #endif // PANDA_TARGET_IOS
3053 #else
3054     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3055     return false;
3056 #endif // ECMASCRIPT_SUPPORT_DEBUGGER
3057 }
3058 
3059 // for socketpair process in ohos platform.
StartDebuggerForSocketPair(int tid,int socketfd)3060 bool JSNApi::StartDebuggerForSocketPair([[maybe_unused]] int tid, [[maybe_unused]] int socketfd)
3061 {
3062 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3063     LOG_ECMA(INFO) << "JSNApi::StartDebuggerForSocketPair, tid = " << tid << ", socketfd = " << socketfd;
3064     JsDebuggerManager *jsDebuggerManager = JsDebuggerManager::GetJsDebuggerManager(tid);
3065     if (jsDebuggerManager == nullptr) {
3066         return false;
3067     }
3068     const auto &handle = jsDebuggerManager->GetDebugLibraryHandle();
3069     if (!handle.IsValid()) {
3070         LOG_ECMA(ERROR) << "[StartDebuggerForSocketPair] Get library handle fail";
3071         return false;
3072     }
3073 
3074     using StartDebugForSocketpair = bool (*)(int, int);
3075 
3076     auto sym = panda::os::library_loader::ResolveSymbol(handle, "StartDebugForSocketpair");
3077     if (!sym) {
3078         LOG_ECMA(ERROR) << "[StartDebuggerForSocketPair] Resolve symbol fail: " << sym.Error().ToString();
3079         return false;
3080     }
3081 
3082     bool ret = reinterpret_cast<StartDebugForSocketpair>(sym.Value())(tid, socketfd);
3083     if (!ret) {
3084         // Reset the config
3085         jsDebuggerManager->SetDebugMode(false);
3086         panda::os::library_loader::LibraryHandle libraryHandle(nullptr);
3087         jsDebuggerManager->SetDebugLibraryHandle(std::move(libraryHandle));
3088     }
3089     return ret;
3090 #else
3091     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3092     return false;
3093 #endif // ECMASCRIPT_SUPPORT_DEBUGGER
3094 }
3095 
3096 // release or debug hap : aa start
3097 //                        aa start -D
3098 //                        new worker
NotifyDebugMode(int tid,EcmaVM * vm,const DebugOption & option,int32_t instanceId,const DebuggerPostTask & debuggerPostTask,bool debugApp)3099 bool JSNApi::NotifyDebugMode([[maybe_unused]] int tid,
3100                              [[maybe_unused]] EcmaVM *vm,
3101                              [[maybe_unused]] const DebugOption &option,
3102                              [[maybe_unused]] int32_t instanceId,
3103                              [[maybe_unused]] const DebuggerPostTask &debuggerPostTask,
3104                              [[maybe_unused]] bool debugApp)
3105 {
3106 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3107     LOG_ECMA(INFO) << "JSNApi::NotifyDebugMode, tid = " << tid << ", debugApp = " << debugApp
3108         << ", isDebugMode = " << option.isDebugMode << ", instanceId = " << instanceId;
3109     if (vm == nullptr) {
3110         return false;
3111     }
3112     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3113 
3114     bool ret = false;
3115     if (!debugApp) {
3116         return false;
3117     }
3118     JsDebuggerManager *jsDebuggerManager = vm->GetJsDebuggerManager();
3119     auto handle = panda::os::library_loader::Load(std::string(option.libraryPath));
3120     if (!handle) {
3121         LOG_ECMA(ERROR) << "[NotifyDebugMode] Load library fail: " << option.libraryPath << " " << errno;
3122         return false;
3123     }
3124     JsDebuggerManager::AddJsDebuggerManager(tid, jsDebuggerManager);
3125     jsDebuggerManager->SetDebugLibraryHandle(std::move(handle.Value()));
3126     jsDebuggerManager->SetDebugMode(option.isDebugMode && debugApp);
3127     jsDebuggerManager->SetIsDebugApp(debugApp);
3128     ret = StartDebuggerForOldProcess(vm, option, instanceId, debuggerPostTask);
3129 
3130     // store debugger postTask in inspector.
3131     using StoreDebuggerInfo = void (*)(int, EcmaVM *, const DebuggerPostTask &);
3132     auto symOfStoreDebuggerInfo = panda::os::library_loader::ResolveSymbol(
3133         jsDebuggerManager->GetDebugLibraryHandle(), "StoreDebuggerInfo");
3134     if (!symOfStoreDebuggerInfo) {
3135         LOG_ECMA(ERROR) << "[NotifyDebugMode] Resolve StoreDebuggerInfo symbol fail: " <<
3136             symOfStoreDebuggerInfo.Error().ToString();
3137         return false;
3138     }
3139     reinterpret_cast<StoreDebuggerInfo>(symOfStoreDebuggerInfo.Value())(tid, vm, debuggerPostTask);
3140     if (option.isDebugMode) {
3141         using WaitForDebugger = void (*)(EcmaVM *);
3142         auto symOfWaitForDebugger = panda::os::library_loader::ResolveSymbol(
3143             jsDebuggerManager->GetDebugLibraryHandle(), "WaitForDebugger");
3144         if (!symOfWaitForDebugger) {
3145             LOG_ECMA(ERROR) << "[NotifyDebugMode] Resolve symbol WaitForDebugger fail: " <<
3146                 symOfWaitForDebugger.Error().ToString();
3147             return false;
3148         }
3149         reinterpret_cast<WaitForDebugger>(symOfWaitForDebugger.Value())(vm);
3150     }
3151     return ret;
3152 
3153 #else
3154     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3155     return false;
3156 #endif // ECMASCRIPT_SUPPORT_DEBUGGER
3157 }
3158 
StoreDebugInfo(int tid,EcmaVM * vm,const DebugOption & option,const DebuggerPostTask & debuggerPostTask,bool debugApp)3159 bool JSNApi::StoreDebugInfo([[maybe_unused]] int tid,
3160                             [[maybe_unused]] EcmaVM *vm,
3161                             [[maybe_unused]] const DebugOption &option,
3162                             [[maybe_unused]] const DebuggerPostTask &debuggerPostTask,
3163                             [[maybe_unused]] bool debugApp)
3164 {
3165 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3166     if (vm == nullptr) {
3167         return false;
3168     }
3169 
3170     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3171     JsDebuggerManager *jsDebuggerManager = vm->GetJsDebuggerManager();
3172     const auto &handler = jsDebuggerManager->GetDebugLibraryHandle();
3173     if (handler.IsValid()) {
3174         return false;
3175     }
3176 
3177     auto handle = panda::os::library_loader::Load(std::string(option.libraryPath));
3178     if (!handle) {
3179         LOG_ECMA(ERROR) << "[NotifyDebugMode] Load library fail: " << option.libraryPath << " " << errno;
3180         return false;
3181     }
3182     JsDebuggerManager::AddJsDebuggerManager(tid, jsDebuggerManager);
3183     jsDebuggerManager->SetDebugLibraryHandle(std::move(handle.Value()));
3184     jsDebuggerManager->SetDebugMode(option.isDebugMode && debugApp);
3185     jsDebuggerManager->SetIsDebugApp(debugApp);
3186     // store debugger postTask in inspector.
3187     using StoreDebuggerInfo = void (*)(int, EcmaVM *, const DebuggerPostTask &);
3188     auto symOfStoreDebuggerInfo = panda::os::library_loader::ResolveSymbol(
3189         jsDebuggerManager->GetDebugLibraryHandle(), "StoreDebuggerInfo");
3190     if (!symOfStoreDebuggerInfo) {
3191         LOG_ECMA(ERROR) << "[NotifyDebugMode] Resolve StoreDebuggerInfo symbol fail: " <<
3192             symOfStoreDebuggerInfo.Error().ToString();
3193         return false;
3194     }
3195     reinterpret_cast<StoreDebuggerInfo>(symOfStoreDebuggerInfo.Value())(tid, vm, debuggerPostTask);
3196     bool ret = false;
3197     using InitializeDebuggerForSocketpair = bool(*)(void*);
3198     auto sym = panda::os::library_loader::ResolveSymbol(handler, "InitializeDebuggerForSocketpair");
3199     if (!sym) {
3200         LOG_ECMA(ERROR) << "[InitializeDebuggerForSocketpair] Resolve symbol fail: " << sym.Error().ToString();
3201         return false;
3202     }
3203     ret = reinterpret_cast<InitializeDebuggerForSocketpair>(sym.Value())(vm);
3204     if (!ret) {
3205     // Reset the config
3206         vm->GetJsDebuggerManager()->SetDebugMode(false);
3207         return false;
3208     }
3209     return ret;
3210 #else
3211     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3212     return false;
3213 #endif // ECMASCRIPT_SUPPORT_DEBUGGER
3214 }
3215 
StopDebugger(EcmaVM * vm)3216 bool JSNApi::StopDebugger([[maybe_unused]] EcmaVM *vm)
3217 {
3218 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3219 #if !defined(PANDA_TARGET_IOS)
3220     LOG_ECMA(INFO) << "JSNApi::StopDebugger";
3221     if (vm == nullptr) {
3222         return false;
3223     }
3224     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3225 
3226     const auto &handle = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
3227 
3228     using StopDebug = void (*)(const std::string &);
3229 
3230     auto sym = panda::os::library_loader::ResolveSymbol(handle, "StopDebug");
3231     if (!sym) {
3232         LOG_ECMA(ERROR) << sym.Error().ToString();
3233         return false;
3234     }
3235 
3236     reinterpret_cast<StopDebug>(sym.Value())("PandaDebugger");
3237 
3238     vm->GetJsDebuggerManager()->SetDebugMode(false);
3239     return true;
3240 #else
3241     if (vm == nullptr) {
3242         return false;
3243     }
3244     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3245 
3246     OHOS::ArkCompiler::Toolchain::StopDebug(DEBUGGER_NAME);
3247     vm->GetJsDebuggerManager()->SetDebugMode(false);
3248     return true;
3249 #endif // PANDA_TARGET_IOS
3250 #else
3251     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3252     return false;
3253 #endif // ECMASCRIPT_SUPPORT_DEBUGGER
3254 }
3255 
StopDebugger(int tid)3256 bool JSNApi::StopDebugger([[maybe_unused]] int tid)
3257 {
3258 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3259     LOG_ECMA(INFO) << "JSNApi::StopDebugger, tid = " << tid;
3260     JsDebuggerManager *jsDebuggerManager = JsDebuggerManager::GetJsDebuggerManager(tid);
3261     if (jsDebuggerManager == nullptr) {
3262         return false;
3263     }
3264 
3265     const auto &handle = jsDebuggerManager->GetDebugLibraryHandle();
3266 
3267     using StopOldDebug = void (*)(int, const std::string &);
3268 
3269     auto sym = panda::os::library_loader::ResolveSymbol(handle, "StopOldDebug");
3270     if (!sym) {
3271         LOG_ECMA(ERROR) << sym.Error().ToString();
3272         return false;
3273     }
3274 
3275     reinterpret_cast<StopOldDebug>(sym.Value())(tid, "PandaDebugger");
3276 
3277     return true;
3278 #else
3279     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3280     return false;
3281 #endif // ECMASCRIPT_SUPPORT_DEBUGGER
3282 }
3283 
IsMixedDebugEnabled(const EcmaVM * vm)3284 bool JSNApi::IsMixedDebugEnabled([[maybe_unused]] const EcmaVM *vm)
3285 {
3286 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3287     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3288     return vm->GetJsDebuggerManager()->IsMixedDebugEnabled();
3289 #else
3290     return false;
3291 #endif
3292 }
3293 
NotifyNativeCalling(const EcmaVM * vm,const void * nativeAddress)3294 void JSNApi::NotifyNativeCalling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const void *nativeAddress)
3295 {
3296 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3297     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
3298     vm->GetJsDebuggerManager()->GetNotificationManager()->NativeCallingEvent(nativeAddress);
3299 #else
3300     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3301 #endif
3302 }
3303 
NotifyNativeReturn(const EcmaVM * vm,const void * nativeAddress)3304 void JSNApi::NotifyNativeReturn([[maybe_unused]] const EcmaVM *vm,  [[maybe_unused]] const void *nativeAddress)
3305 {
3306 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3307     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
3308     vm->GetJsDebuggerManager()->GetNotificationManager()->NativeReturnEvent(nativeAddress);
3309 #else
3310     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3311 #endif
3312 }
3313 
NotifyLoadModule(const EcmaVM * vm)3314 void JSNApi::NotifyLoadModule([[maybe_unused]] const EcmaVM *vm)
3315 {
3316 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
3317     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
3318     // if load module, it needs to check whether clear singlestepper_
3319     vm->GetJsDebuggerManager()->ClearSingleStepper();
3320 #else
3321     LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
3322 #endif
3323 }
3324 
SetDeviceDisconnectCallback(EcmaVM * vm,DeviceDisconnectCallback cb)3325 void JSNApi::SetDeviceDisconnectCallback(EcmaVM *vm, DeviceDisconnectCallback cb)
3326 {
3327     vm->SetDeviceDisconnectCallback(cb);
3328 }
3329 
LoadAotFile(EcmaVM * vm,const std::string & moduleName)3330 void JSNApi::LoadAotFile(EcmaVM *vm, const std::string &moduleName)
3331 {
3332     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
3333     if (!ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
3334         return;
3335     }
3336     std::string aotFileName;
3337     if (vm->GetJSOptions().WasAOTOutputFileSet()) {
3338         aotFileName = vm->GetJSOptions().GetAOTOutputFile();
3339     }  else {
3340         aotFileName = ecmascript::AnFileDataManager::GetInstance()->GetDir() + moduleName;
3341     }
3342     if (ecmascript::pgo::PGOProfilerManager::GetInstance()->IsDisableAot()) {
3343         LOG_ECMA(INFO) << "can't load disable aot file: " << aotFileName;
3344         return;
3345     }
3346     LOG_ECMA(INFO) << "start to load aot file: " << aotFileName;
3347     thread->GetCurrentEcmaContext()->LoadAOTFiles(aotFileName);
3348 }
3349 
ExecuteInContext(EcmaVM * vm,const std::string & fileName,const std::string & entry,bool needUpdate)3350 bool JSNApi::ExecuteInContext(EcmaVM *vm, const std::string &fileName, const std::string &entry, bool needUpdate)
3351 {
3352     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3353     LOG_ECMA(DEBUG) << "start to execute ark file in context: " << fileName;
3354     EcmaContext::MountContext(thread);
3355     if (!ecmascript::JSPandaFileExecutor::ExecuteFromAbcFile(thread, fileName.c_str(), entry, needUpdate)) {
3356         LOG_ECMA(ERROR) << "Cannot execute ark file '" << fileName
3357                         << "' with entry '" << entry << "'" << std::endl;
3358         return false;
3359     }
3360     EcmaContext::UnmountContext(thread);
3361     return true;
3362 }
3363 
Execute(EcmaVM * vm,const std::string & fileName,const std::string & entry,bool needUpdate)3364 bool JSNApi::Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry, bool needUpdate)
3365 {
3366     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3367     LOG_ECMA(DEBUG) << "start to execute ark file: " << fileName;
3368     if (!ecmascript::JSPandaFileExecutor::ExecuteFromAbcFile(thread, fileName.c_str(), entry, needUpdate)) {
3369         LOG_ECMA(ERROR) << "Cannot execute ark file '" << fileName
3370                         << "' with entry '" << entry << "'" << std::endl;
3371         return false;
3372     }
3373     return true;
3374 }
3375 
3376 // The security interface needs to be modified accordingly.
Execute(EcmaVM * vm,const uint8_t * data,int32_t size,const std::string & entry,const std::string & filename,bool needUpdate)3377 bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry,
3378                      const std::string &filename, bool needUpdate)
3379 {
3380     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3381     LOG_ECMA(DEBUG) << "start to execute ark buffer: " << filename;
3382     if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(thread, data, size, entry, filename.c_str(), needUpdate)) {
3383         LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename
3384                         << "' with entry '" << entry << "'" << std::endl;
3385         return false;
3386     }
3387     return true;
3388 }
3389 
3390 // The security interface needs to be modified accordingly.
ExecuteModuleBuffer(EcmaVM * vm,const uint8_t * data,int32_t size,const std::string & filename,bool needUpdate)3391 bool JSNApi::ExecuteModuleBuffer(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &filename,
3392                                  bool needUpdate)
3393 {
3394     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3395     LOG_ECMA(DEBUG) << "start to execute module buffer: " << filename;
3396     if (!ecmascript::JSPandaFileExecutor::ExecuteModuleBuffer(thread, data, size, filename.c_str(), needUpdate)) {
3397         LOG_ECMA(ERROR) << "Cannot execute module buffer file '" << filename;
3398         return false;
3399     }
3400     return true;
3401 }
3402 
ExecuteSecure(EcmaVM * vm,uint8_t * data,int32_t size,const std::string & entry,const std::string & filename,bool needUpdate)3403 bool JSNApi::ExecuteSecure(EcmaVM *vm, uint8_t *data, int32_t size, const std::string &entry,
3404                            const std::string &filename, bool needUpdate)
3405 {
3406     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3407     LOG_ECMA(INFO) << "start to execute ark buffer with secure memory: " << filename;
3408     if (!CheckSecureMem(reinterpret_cast<uintptr_t>(data))) {
3409         LOG_ECMA(ERROR) << "Secure memory check failed, please execute in srcure memory.";
3410         return false;
3411     }
3412     if (!ecmascript::JSPandaFileExecutor::ExecuteFromBufferSecure(thread, data, size, entry, filename.c_str(),
3413                                                                   needUpdate)) {
3414         LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename
3415                         << "' with entry '" << entry << "'" << std::endl;
3416         return false;
3417     }
3418     return true;
3419 }
3420 
ExecuteModuleBufferSecure(EcmaVM * vm,uint8_t * data,int32_t size,const std::string & filename,bool needUpdate)3421 bool JSNApi::ExecuteModuleBufferSecure(EcmaVM *vm, uint8_t* data, int32_t size, const std::string &filename,
3422                                        bool needUpdate)
3423 {
3424     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3425     LOG_ECMA(INFO) << "start to execute module buffer with secure memory: " << filename;
3426     if (!CheckSecureMem(reinterpret_cast<uintptr_t>(data))) {
3427         LOG_ECMA(ERROR) << "Secure memory check failed, please execute in srcure memory.";
3428         return false;
3429     }
3430     if (!ecmascript::JSPandaFileExecutor::ExecuteModuleBufferSecure(thread, data, size, filename.c_str(),
3431                                                                     needUpdate)) {
3432         LOG_ECMA(ERROR) << "Cannot execute module buffer file '" << filename;
3433         return false;
3434     }
3435     return true;
3436 }
3437 
PreFork(EcmaVM * vm)3438 void JSNApi::PreFork(EcmaVM *vm)
3439 {
3440     vm->PreFork();
3441 }
3442 
PostFork(EcmaVM * vm,const RuntimeOption & option)3443 void JSNApi::PostFork(EcmaVM *vm, const RuntimeOption &option)
3444 {
3445     JSRuntimeOptions &jsOption = vm->GetJSOptions();
3446     LOG_ECMA(INFO) << "asmint: " << jsOption.GetEnableAsmInterpreter()
3447                     << ", aot: " << jsOption.GetEnableAOT()
3448                     << ", bundle name: " <<  option.GetBundleName();
3449     jsOption.SetEnablePGOProfiler(option.GetEnableProfile());
3450     ecmascript::pgo::PGOProfilerManager::GetInstance()->SetBundleName(option.GetBundleName());
3451     JSRuntimeOptions runtimeOptions;
3452     runtimeOptions.SetLogLevel(Log::LevelToString(Log::ConvertFromRuntime(option.GetLogLevel())));
3453     Log::Initialize(runtimeOptions);
3454 
3455     if (jsOption.GetEnableAOT() && option.GetAnDir().size()) {
3456         ecmascript::AnFileDataManager::GetInstance()->SetDir(option.GetAnDir());
3457         ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
3458     }
3459 
3460     vm->PostFork();
3461 }
3462 
AddWorker(EcmaVM * hostVm,EcmaVM * workerVm)3463 void JSNApi::AddWorker(EcmaVM *hostVm, EcmaVM *workerVm)
3464 {
3465     if (hostVm != nullptr && workerVm != nullptr) {
3466         hostVm->WorkersetInfo(workerVm);
3467         workerVm->SetBundleName(hostVm->GetBundleName());
3468     }
3469 }
3470 
DeleteWorker(EcmaVM * hostVm,EcmaVM * workerVm)3471 bool JSNApi::DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm)
3472 {
3473     if (hostVm != nullptr && workerVm != nullptr) {
3474         return hostVm->DeleteWorker(workerVm);
3475     }
3476     return false;
3477 }
3478 
GetUncaughtException(const EcmaVM * vm)3479 Local<ObjectRef> JSNApi::GetUncaughtException(const EcmaVM *vm)
3480 {
3481     return JSNApiHelper::ToLocal<ObjectRef>(vm->GetEcmaUncaughtException());
3482 }
3483 
GetAndClearUncaughtException(const EcmaVM * vm)3484 Local<ObjectRef> JSNApi::GetAndClearUncaughtException(const EcmaVM *vm)
3485 {
3486     return JSNApiHelper::ToLocal<ObjectRef>(vm->GetAndClearEcmaUncaughtException());
3487 }
3488 
HasPendingException(const EcmaVM * vm)3489 bool JSNApi::HasPendingException(const EcmaVM *vm)
3490 {
3491     return vm->GetJSThread()->HasPendingException();
3492 }
3493 
IsExecutingPendingJob(const EcmaVM * vm)3494 bool JSNApi::IsExecutingPendingJob(const EcmaVM *vm)
3495 {
3496     return vm->GetAssociatedJSThread()->GetCurrentEcmaContext()->IsExecutingPendingJob();
3497 }
3498 
HasPendingJob(const EcmaVM * vm)3499 bool JSNApi::HasPendingJob(const EcmaVM *vm)
3500 {
3501     return vm->GetAssociatedJSThread()->GetCurrentEcmaContext()->HasPendingJob();
3502 }
3503 
EnableUserUncaughtErrorHandler(EcmaVM * vm)3504 void JSNApi::EnableUserUncaughtErrorHandler(EcmaVM *vm)
3505 {
3506     return vm->GetJSThread()->GetCurrentEcmaContext()->EnableUserUncaughtErrorHandler();
3507 }
3508 
GetGlobalObject(const EcmaVM * vm)3509 Local<ObjectRef> JSNApi::GetGlobalObject(const EcmaVM *vm)
3510 {
3511     JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
3512     JSHandle<JSTaggedValue> global(vm->GetJSThread(), globalEnv->GetGlobalObject());
3513     return JSNApiHelper::ToLocal<ObjectRef>(global);
3514 }
3515 
ExecutePendingJob(const EcmaVM * vm)3516 void JSNApi::ExecutePendingJob(const EcmaVM *vm)
3517 {
3518     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
3519     EcmaVM::ConstCast(vm)->GetJSThread()->GetCurrentEcmaContext()->ExecutePromisePendingJob();
3520 }
3521 
GetHandleAddr(const EcmaVM * vm,uintptr_t localAddress)3522 uintptr_t JSNApi::GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
3523 {
3524     if (localAddress == 0) {
3525         return 0;
3526     }
3527     CROSS_THREAD_CHECK(vm);
3528     JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
3529     return ecmascript::EcmaHandleScope::NewHandle(thread, value);
3530 }
3531 
GetGlobalHandleAddr(const EcmaVM * vm,uintptr_t localAddress)3532 uintptr_t JSNApi::GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
3533 {
3534     if (localAddress == 0) {
3535         return 0;
3536     }
3537     CROSS_THREAD_CHECK(vm);
3538     JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
3539     return thread->NewGlobalHandle(value);
3540 }
3541 
SetWeak(const EcmaVM * vm,uintptr_t localAddress)3542 uintptr_t JSNApi::SetWeak(const EcmaVM *vm, uintptr_t localAddress)
3543 {
3544     if (localAddress == 0) {
3545         return 0;
3546     }
3547     CROSS_THREAD_CHECK(vm);
3548     return thread->SetWeak(localAddress);
3549 }
3550 
SetWeakCallback(const EcmaVM * vm,uintptr_t localAddress,void * ref,WeakRefClearCallBack freeGlobalCallBack,WeakRefClearCallBack nativeFinalizeCallback)3551 uintptr_t JSNApi::SetWeakCallback(const EcmaVM *vm, uintptr_t localAddress, void *ref,
3552                                   WeakRefClearCallBack freeGlobalCallBack, WeakRefClearCallBack nativeFinalizeCallback)
3553 {
3554     if (localAddress == 0) {
3555         return 0;
3556     }
3557     CROSS_THREAD_CHECK(vm);
3558     return thread->SetWeak(localAddress, ref, freeGlobalCallBack, nativeFinalizeCallback);
3559 }
3560 
ClearWeak(const EcmaVM * vm,uintptr_t localAddress)3561 uintptr_t JSNApi::ClearWeak(const EcmaVM *vm, uintptr_t localAddress)
3562 {
3563     if (localAddress == 0) {
3564         return 0;
3565     }
3566     if (JSTaggedValue(reinterpret_cast<ecmascript::Node *>(localAddress)->GetObject())
3567         .IsUndefined()) {
3568         LOG_ECMA(ERROR) << "The object of weak reference has been recycled!";
3569         return 0;
3570     }
3571     CROSS_THREAD_CHECK(vm);
3572     return thread->ClearWeak(localAddress);
3573 }
3574 
IsWeak(const EcmaVM * vm,uintptr_t localAddress)3575 bool JSNApi::IsWeak(const EcmaVM *vm, uintptr_t localAddress)
3576 {
3577     if (localAddress == 0) {
3578         return false;
3579     }
3580     CROSS_THREAD_CHECK(vm);
3581     return thread->IsWeak(localAddress);
3582 }
3583 
DisposeGlobalHandleAddr(const EcmaVM * vm,uintptr_t addr)3584 void JSNApi::DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr)
3585 {
3586     if (addr == 0 || !reinterpret_cast<ecmascript::Node *>(addr)->IsUsing()) {
3587         return;
3588     }
3589     CROSS_THREAD_CHECK(vm);
3590     thread->DisposeGlobalHandle(addr);
3591 }
3592 
SerializeValue(const EcmaVM * vm,Local<JSValueRef> value,Local<JSValueRef> transfer,Local<JSValueRef> cloneList,bool defaultTransfer,bool defaultCloneShared)3593 void *JSNApi::SerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer,
3594                              Local<JSValueRef> cloneList, bool defaultTransfer, bool defaultCloneShared)
3595 {
3596     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
3597     JSHandle<JSTaggedValue> arkValue = JSNApiHelper::ToJSHandle(value);
3598     JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer);
3599     JSHandle<JSTaggedValue> arkCloneList = JSNApiHelper::ToJSHandle(cloneList);
3600 #if ECMASCRIPT_ENABLE_VALUE_SERIALIZER
3601     ecmascript::ValueSerializer serializer(thread, defaultTransfer, defaultCloneShared);
3602     std::unique_ptr<ecmascript::SerializeData> data;
3603     if (serializer.WriteValue(thread, arkValue, arkTransfer, arkCloneList)) {
3604         data = serializer.Release();
3605     }
3606     if (data == nullptr) {
3607         return nullptr;
3608     } else {
3609         return reinterpret_cast<void *>(data.release());
3610     }
3611 #else
3612     ecmascript::Serializer serializer(thread);
3613     std::unique_ptr<ecmascript::SerializationData> data;
3614     if (serializer.WriteValue(thread, arkValue, arkTransfer)) {
3615         data = serializer.Release();
3616     }
3617     if (data == nullptr) {
3618         return nullptr;
3619     } else {
3620         return reinterpret_cast<void *>(data.release());
3621     }
3622 #endif
3623 }
3624 
DeserializeValue(const EcmaVM * vm,void * recoder,void * hint)3625 Local<JSValueRef> JSNApi::DeserializeValue(const EcmaVM *vm, void *recoder, void *hint)
3626 {
3627     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3628 #if ECMASCRIPT_ENABLE_VALUE_SERIALIZER
3629     std::unique_ptr<ecmascript::SerializeData> data(reinterpret_cast<ecmascript::SerializeData *>(recoder));
3630     ecmascript::BaseDeserializer deserializer(thread, data.release(), hint);
3631     JSHandle<JSTaggedValue> result = deserializer.ReadValue();
3632     return JSNApiHelper::ToLocal<ObjectRef>(result);
3633 #else
3634     std::unique_ptr<ecmascript::SerializationData> data(reinterpret_cast<ecmascript::SerializationData *>(recoder));
3635     ecmascript::Deserializer deserializer(thread, data.release(), hint);
3636     JSHandle<JSTaggedValue> result = deserializer.ReadValue();
3637     return JSNApiHelper::ToLocal<ObjectRef>(result);
3638 #endif
3639 }
3640 
DeleteSerializationData(void * data)3641 void JSNApi::DeleteSerializationData(void *data)
3642 {
3643 #if ECMASCRIPT_ENABLE_VALUE_SERIALIZER
3644     ecmascript::SerializeData *value = reinterpret_cast<ecmascript::SerializeData *>(data);
3645     delete value;
3646     value = nullptr;
3647 #else
3648     ecmascript::SerializationData *value = reinterpret_cast<ecmascript::SerializationData *>(data);
3649     delete value;
3650     value = nullptr;
3651 #endif
3652 }
3653 
HostPromiseRejectionTracker(const EcmaVM * vm,const JSHandle<JSPromise> promise,const JSHandle<JSTaggedValue> reason,const ecmascript::PromiseRejectionEvent operation,void * data)3654 void HostPromiseRejectionTracker(const EcmaVM *vm,
3655                                  const JSHandle<JSPromise> promise,
3656                                  const JSHandle<JSTaggedValue> reason,
3657                                  const ecmascript::PromiseRejectionEvent operation,
3658                                  void* data)
3659 {
3660     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
3661     ecmascript::PromiseRejectCallback promiseRejectCallback =
3662         thread->GetCurrentEcmaContext()->GetPromiseRejectCallback();
3663     if (promiseRejectCallback != nullptr) {
3664         Local<JSValueRef> promiseVal = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>::Cast(promise));
3665         PromiseRejectInfo promiseRejectInfo(promiseVal, JSNApiHelper::ToLocal<JSValueRef>(reason),
3666                               static_cast<PromiseRejectInfo::PROMISE_REJECTION_EVENT>(operation), data);
3667         promiseRejectCallback(reinterpret_cast<void*>(&promiseRejectInfo));
3668     }
3669 }
3670 
SetHostPromiseRejectionTracker(EcmaVM * vm,void * cb,void * data)3671 void JSNApi::SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data)
3672 {
3673     CROSS_THREAD_CHECK(vm);
3674     thread->GetCurrentEcmaContext()->SetHostPromiseRejectionTracker(HostPromiseRejectionTracker);
3675     thread->GetCurrentEcmaContext()->SetPromiseRejectCallback(
3676         reinterpret_cast<ecmascript::PromiseRejectCallback>(cb));
3677     thread->GetCurrentEcmaContext()->SetData(data);
3678 }
3679 
SetHostResolveBufferTracker(EcmaVM * vm,std::function<bool (std::string dirPath,uint8_t ** buff,size_t * buffSize)> cb)3680 void JSNApi::SetHostResolveBufferTracker(EcmaVM *vm,
3681     std::function<bool(std::string dirPath, uint8_t **buff, size_t *buffSize)> cb)
3682 {
3683     vm->SetResolveBufferCallback(cb);
3684 }
3685 
SetSearchHapPathTracker(EcmaVM * vm,std::function<bool (const std::string moduleName,std::string & hapPath)> cb)3686 void JSNApi::SetSearchHapPathTracker(EcmaVM *vm,
3687     std::function<bool(const std::string moduleName, std::string &hapPath)> cb)
3688 {
3689     vm->SetSearchHapPathCallBack(cb);
3690 }
3691 
SetRequestAotCallback(EcmaVM * vm,const std::function<int32_t (const std::string & bundleName,const std::string & moduleName,int32_t triggerMode)> & cb)3692 void JSNApi::SetRequestAotCallback([[maybe_unused]] EcmaVM *vm, const std::function<int32_t
3693     (const std::string &bundleName, const std::string &moduleName, int32_t triggerMode)> &cb)
3694 {
3695     ecmascript::pgo::PGOProfilerManager::GetInstance()->SetRequestAotCallback(cb);
3696 }
3697 
SetUnloadNativeModuleCallback(EcmaVM * vm,const std::function<bool (const std::string & moduleKey)> & cb)3698 void JSNApi::SetUnloadNativeModuleCallback(EcmaVM *vm, const std::function<bool(const std::string &moduleKey)> &cb)
3699 {
3700     vm->SetUnloadNativeModuleCallback(cb);
3701 }
3702 
SetNativePtrGetter(EcmaVM * vm,void * cb)3703 void JSNApi::SetNativePtrGetter(EcmaVM *vm, void* cb)
3704 {
3705     vm->SetNativePtrGetter(reinterpret_cast<ecmascript::NativePtrGetter>(cb));
3706 }
3707 
SetHostEnqueueJob(const EcmaVM * vm,Local<JSValueRef> cb)3708 void JSNApi::SetHostEnqueueJob(const EcmaVM *vm, Local<JSValueRef> cb)
3709 {
3710     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
3711     JSHandle<JSFunction> fun = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(cb));
3712     JSHandle<TaggedArray> array = vm->GetFactory()->EmptyArray();
3713     JSHandle<MicroJobQueue> job = thread->GetCurrentEcmaContext()->GetMicroJobQueue();
3714     MicroJobQueue::EnqueueJob(thread, job, QueueType::QUEUE_PROMISE, fun, array);
3715 }
3716 
ExecuteModuleFromBuffer(EcmaVM * vm,const void * data,int32_t size,const std::string & file)3717 bool JSNApi::ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file)
3718 {
3719     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
3720     if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(thread, data, size, ENTRY_POINTER, file.c_str())) {
3721         std::cerr << "Cannot execute panda file from memory" << std::endl;
3722         return false;
3723     }
3724     return true;
3725 }
3726 
GetExportObject(EcmaVM * vm,const std::string & file,const std::string & key)3727 Local<ObjectRef> JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, const std::string &key)
3728 {
3729     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3730     ecmascript::CString entry = file.c_str();
3731     ecmascript::CString name = vm->GetAssetPath();
3732     if (!vm->IsBundlePack()) {
3733         ModulePathHelper::ParseOhmUrl(vm, entry, name, entry);
3734         std::shared_ptr<JSPandaFile> jsPandaFile =
3735             JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry.c_str(), false);
3736         if (jsPandaFile == nullptr) {
3737             JSHandle<JSTaggedValue> exportObj(thread, JSTaggedValue::Null());
3738             return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
3739         }
3740         if (!jsPandaFile->IsRecordWithBundleName()) {
3741             PathHelper::AdaptOldIsaRecord(entry);
3742         }
3743     }
3744     ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
3745     JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(entry);
3746     if (ecmaModule->GetIsNewBcVersion()) {
3747         int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key);
3748         JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
3749         JSHandle<JSTaggedValue> exportObj(thread, result);
3750         return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
3751     }
3752     ObjectFactory *factory = vm->GetFactory();
3753     JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
3754 
3755     JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
3756     JSHandle<JSTaggedValue> exportObj(thread, result);
3757     return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
3758 }
3759 
GetExportObjectFromBuffer(EcmaVM * vm,const std::string & file,const std::string & key)3760 Local<ObjectRef> JSNApi::GetExportObjectFromBuffer(EcmaVM *vm, const std::string &file,
3761                                                    const std::string &key)
3762 {
3763     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3764     ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
3765     JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(file.c_str());
3766 
3767     if (ecmaModule->GetIsNewBcVersion()) {
3768         int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key);
3769         JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
3770         JSHandle<JSTaggedValue> exportObj(thread, result);
3771         return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
3772     }
3773 
3774     ObjectFactory *factory = vm->GetFactory();
3775     JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
3776     JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
3777     JSHandle<JSTaggedValue> exportObj(thread, result);
3778     return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
3779 }
3780 
ExecuteNativeModule(EcmaVM * vm,const std::string & key)3781 Local<ObjectRef> JSNApi::ExecuteNativeModule(EcmaVM *vm, const std::string &key)
3782 {
3783     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3784     ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
3785     JSHandle<JSTaggedValue> exportObj = moduleManager->LoadNativeModule(thread, key);
3786     return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
3787 }
3788 
3789  // Initialize IcuData Path
InitializeIcuData(const JSRuntimeOptions & options)3790 void JSNApi::InitializeIcuData(const JSRuntimeOptions &options)
3791 {
3792     std::string icuPath = options.GetIcuDataPath();
3793     if (icuPath == "default") {
3794 #if !WIN_OR_MAC_OR_IOS_PLATFORM && !defined(PANDA_TARGET_LINUX)
3795         SetHwIcuDirectory();
3796 #endif
3797     } else {
3798         std::string absPath;
3799         if (ecmascript::RealPath(icuPath, absPath)) {
3800             u_setDataDirectory(absPath.c_str());
3801         }
3802     }
3803 }
3804 
InitializeMemMapAllocator()3805 void JSNApi::InitializeMemMapAllocator()
3806 {
3807     MemMapAllocator::GetInstance()->Initialize(ecmascript::DEFAULT_REGION_SIZE);
3808 }
3809 
DestroyMemMapAllocator()3810 void JSNApi::DestroyMemMapAllocator()
3811 {
3812     MemMapAllocator::GetInstance()->Finalize();
3813 }
3814 
InitializePGOProfiler(const ecmascript::JSRuntimeOptions & options)3815 void JSNApi::InitializePGOProfiler(const ecmascript::JSRuntimeOptions &options)
3816 {
3817     ecmascript::pgo::PGOProfilerManager::GetInstance()->Initialize(
3818         options.GetPGOProfilerPath(), options.GetPGOHotnessThreshold());
3819 }
3820 
DestroyPGOProfiler()3821 void JSNApi::DestroyPGOProfiler()
3822 {
3823     ecmascript::pgo::PGOProfilerManager::GetInstance()->Destroy();
3824 }
3825 
DestroyAnDataManager()3826 void JSNApi::DestroyAnDataManager()
3827 {
3828     ecmascript::AnFileDataManager::GetInstance()->SafeDestroyAllData();
3829 }
3830 
3831 // ---------------------------------- Promise -------------------------------------
Catch(const EcmaVM * vm,Local<FunctionRef> handler)3832 Local<PromiseRef> PromiseRef::Catch(const EcmaVM *vm, Local<FunctionRef> handler)
3833 {
3834     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3835     const GlobalEnvConstants *constants = thread->GlobalConstants();
3836 
3837     JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
3838     LOG_IF_SPECIAL(promise, ERROR);
3839     JSHandle<JSTaggedValue> catchKey(thread, constants->GetPromiseCatchString());
3840     JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(handler);
3841     JSHandle<JSTaggedValue> undefined = constants->GetHandledUndefined();
3842     EcmaRuntimeCallInfo *info =
3843         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 1);
3844     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3845     info->SetCallArg(reject.GetTaggedValue());
3846     JSTaggedValue result = JSFunction::Invoke(info, catchKey);
3847 
3848     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3849     return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
3850 }
3851 
Finally(const EcmaVM * vm,Local<FunctionRef> handler)3852 Local<PromiseRef> PromiseRef::Finally(const EcmaVM *vm, Local<FunctionRef> handler)
3853 {
3854     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3855     const GlobalEnvConstants *constants = thread->GlobalConstants();
3856 
3857     JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
3858     LOG_IF_SPECIAL(promise, ERROR);
3859     JSHandle<JSTaggedValue> finallyKey = constants->GetHandledPromiseFinallyString();
3860     JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler);
3861     JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
3862     EcmaRuntimeCallInfo *info =
3863         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args
3864     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3865     info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue());
3866     JSTaggedValue result = JSFunction::Invoke(info, finallyKey);
3867 
3868     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3869     return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
3870 }
3871 
Then(const EcmaVM * vm,Local<FunctionRef> handler)3872 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> handler)
3873 {
3874     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3875     const GlobalEnvConstants *constants = thread->GlobalConstants();
3876 
3877     JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
3878     LOG_IF_SPECIAL(promise, ERROR);
3879     JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
3880     JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler);
3881     JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
3882     EcmaRuntimeCallInfo *info =
3883         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args
3884     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3885     info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue());
3886     JSTaggedValue result = JSFunction::Invoke(info, thenKey);
3887 
3888     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3889     return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
3890 }
3891 
Then(const EcmaVM * vm,Local<FunctionRef> onFulfilled,Local<FunctionRef> onRejected)3892 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> onFulfilled, Local<FunctionRef> onRejected)
3893 {
3894     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3895     const GlobalEnvConstants *constants = thread->GlobalConstants();
3896 
3897     JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
3898     LOG_IF_SPECIAL(promise, ERROR);
3899     JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
3900     JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(onFulfilled);
3901     JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(onRejected);
3902     JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
3903     EcmaRuntimeCallInfo *info =
3904         ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args
3905     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3906     info->SetCallArg(resolver.GetTaggedValue(), reject.GetTaggedValue());
3907     JSTaggedValue result = JSFunction::Invoke(info, thenKey);
3908 
3909     RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
3910     return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
3911 }
3912 
GetPromiseState(const EcmaVM * vm)3913 Local<JSValueRef> PromiseRef::GetPromiseState(const EcmaVM *vm)
3914 {
3915     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3916     JSHandle<JSPromise> promise(JSNApiHelper::ToJSHandle(this));
3917     LOG_IF_SPECIAL(promise, ERROR);
3918 
3919     ecmascript::PromiseState state = promise->GetPromiseState();
3920     std::string promiseStateStr;
3921     switch (state) {
3922         case ecmascript::PromiseState::PENDING:
3923             promiseStateStr = "Pending";
3924             break;
3925         case ecmascript::PromiseState::FULFILLED:
3926             promiseStateStr = "Fulfilled";
3927             break;
3928         case ecmascript::PromiseState::REJECTED:
3929             promiseStateStr = "Rejected";
3930             break;
3931     }
3932 
3933     ObjectFactory *factory = vm->GetFactory();
3934     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(factory->NewFromStdString(promiseStateStr)));
3935 }
3936 
GetPromiseResult(const EcmaVM * vm)3937 Local<JSValueRef> PromiseRef::GetPromiseResult(const EcmaVM *vm)
3938 {
3939     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3940     JSHandle<JSPromise> promise(JSNApiHelper::ToJSHandle(this));
3941     LOG_IF_SPECIAL(promise, ERROR);
3942 
3943     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), promise->GetPromiseResult()));
3944 }
3945 // ---------------------------------- ProxyRef -----------------------------------------
GetHandler(const EcmaVM * vm)3946 Local<JSValueRef> ProxyRef::GetHandler(const EcmaVM *vm)
3947 {
3948     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3949     JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this));
3950     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, jsProxy->GetHandler()));
3951 }
3952 
GetTarget(const EcmaVM * vm)3953 Local<JSValueRef> ProxyRef::GetTarget(const EcmaVM *vm)
3954 {
3955     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3956     JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this));
3957     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, jsProxy->GetTarget()));
3958 }
3959 
IsRevoked()3960 bool ProxyRef::IsRevoked()
3961 {
3962     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
3963     JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this));
3964     return jsProxy->GetIsRevoked();
3965 }
3966 
3967 // ---------------------------------- SetRef --------------------------------------
GetSize()3968 int32_t SetRef::GetSize()
3969 {
3970     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
3971     JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
3972     return set->GetSize();
3973 }
3974 
GetTotalElements()3975 int32_t SetRef::GetTotalElements()
3976 {
3977     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
3978     JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
3979     return static_cast<int>(set->GetSize()) +
3980         LinkedHashSet::Cast(set->GetLinkedSet().GetTaggedObject())->NumberOfDeletedElements();
3981 }
3982 
GetValue(const EcmaVM * vm,int entry)3983 Local<JSValueRef> SetRef::GetValue(const EcmaVM *vm, int entry)
3984 {
3985     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3986     JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
3987     LOG_IF_SPECIAL(set, FATAL);
3988     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, set->GetValue(entry)));
3989 }
3990 
New(const EcmaVM * vm)3991 Local<SetRef> SetRef::New(const EcmaVM *vm)
3992 {
3993     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
3994     ObjectFactory *factory = vm->GetJSThread()->GetEcmaVM()->GetFactory();
3995     JSHandle<GlobalEnv> env = vm->GetJSThread()->GetEcmaVM()->GetGlobalEnv();
3996     JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
3997     JSHandle<JSSet> set =
3998         JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
3999     JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(vm->GetJSThread());
4000     set->SetLinkedSet(vm->GetJSThread(), hashSet);
4001     JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(set);
4002     return JSNApiHelper::ToLocal<SetRef>(setTag);
4003 }
4004 
Add(const EcmaVM * vm,Local<JSValueRef> value)4005 void SetRef::Add(const EcmaVM *vm, Local<JSValueRef> value)
4006 {
4007     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
4008     JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
4009     LOG_IF_SPECIAL(set, ERROR);
4010     JSSet::Add(vm->GetJSThread(), set, JSNApiHelper::ToJSHandle(value));
4011 }
4012 
4013 // ---------------------------------- WeakMapRef --------------------------------------
GetSize()4014 int32_t WeakMapRef::GetSize()
4015 {
4016     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
4017     JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
4018     return weakMap->GetSize();
4019 }
4020 
GetTotalElements()4021 int32_t WeakMapRef::GetTotalElements()
4022 {
4023     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
4024     JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
4025     return weakMap->GetSize() +
4026                 LinkedHashMap::Cast(weakMap->GetLinkedMap().GetTaggedObject())->NumberOfDeletedElements();
4027 }
4028 
GetKey(const EcmaVM * vm,int entry)4029 Local<JSValueRef> WeakMapRef::GetKey(const EcmaVM *vm, int entry)
4030 {
4031     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
4032     JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
4033     LOG_IF_SPECIAL(weakMap, FATAL);
4034     JSTaggedValue key = weakMap->GetKey(entry);
4035     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, key.GetWeakRawValue()));
4036 }
4037 
GetValue(const EcmaVM * vm,int entry)4038 Local<JSValueRef> WeakMapRef::GetValue(const EcmaVM *vm, int entry)
4039 {
4040     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
4041     JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
4042     LOG_IF_SPECIAL(weakMap, FATAL);
4043     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, weakMap->GetValue(entry)));
4044 }
4045 
New(const EcmaVM * vm)4046 Local<WeakMapRef> WeakMapRef::New(const EcmaVM *vm)
4047 {
4048     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
4049     ObjectFactory *factory = vm->GetJSThread()->GetEcmaVM()->GetFactory();
4050     JSHandle<GlobalEnv> env = vm->GetJSThread()->GetEcmaVM()->GetGlobalEnv();
4051     JSHandle<JSTaggedValue> constructor = env->GetBuiltinsWeakMapFunction();
4052     JSHandle<JSWeakMap> weakMap =
4053         JSHandle<JSWeakMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
4054     JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(vm->GetJSThread());
4055     weakMap->SetLinkedMap(vm->GetJSThread(), hashMap);
4056     JSHandle<JSTaggedValue> weakMapTag = JSHandle<JSTaggedValue>::Cast(weakMap);
4057     return JSNApiHelper::ToLocal<WeakMapRef>(weakMapTag);
4058 }
4059 
Set(const EcmaVM * vm,const Local<JSValueRef> & key,const Local<JSValueRef> & value)4060 void WeakMapRef::Set(const EcmaVM *vm, const Local<JSValueRef> &key, const Local<JSValueRef> &value)
4061 {
4062     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
4063     JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
4064     LOG_IF_SPECIAL(weakMap, FATAL);
4065     JSWeakMap::Set(vm->GetJSThread(), weakMap, JSNApiHelper::ToJSHandle(key), JSNApiHelper::ToJSHandle(value));
4066 }
4067 
Has(const EcmaVM * vm,Local<JSValueRef> key)4068 bool WeakMapRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
4069 {
4070     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
4071     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
4072     JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
4073     return weakMap->Has(thread, JSNApiHelper::ToJSTaggedValue(*key));
4074 }
4075 
4076 // ---------------------------------- WeakSetRef --------------------------------------
GetSize()4077 int32_t WeakSetRef::GetSize()
4078 {
4079     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
4080     JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
4081     return weakSet->GetSize();
4082 }
4083 
GetTotalElements()4084 int32_t WeakSetRef::GetTotalElements()
4085 {
4086     DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
4087     JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
4088     return weakSet->GetSize() +
4089                 LinkedHashSet::Cast(weakSet->GetLinkedSet().GetTaggedObject())->NumberOfDeletedElements();
4090 }
4091 
GetValue(const EcmaVM * vm,int entry)4092 Local<JSValueRef> WeakSetRef::GetValue(const EcmaVM *vm, int entry)
4093 {
4094     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
4095     JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
4096     LOG_IF_SPECIAL(weakSet, FATAL);
4097     JSTaggedValue value = weakSet->GetValue(entry);
4098     return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, value.GetWeakRawValue()));
4099 }
4100 
New(const EcmaVM * vm)4101 Local<WeakSetRef> WeakSetRef::New(const EcmaVM *vm)
4102 {
4103     CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
4104     ObjectFactory *factory = vm->GetJSThread()->GetEcmaVM()->GetFactory();
4105     JSHandle<GlobalEnv> env = vm->GetJSThread()->GetEcmaVM()->GetGlobalEnv();
4106     JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
4107     JSHandle<JSWeakSet> weakSet =
4108         JSHandle<JSWeakSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
4109     JSHandle<LinkedHashSet> hashWeakSet = LinkedHashSet::Create(vm->GetJSThread());
4110     weakSet->SetLinkedSet(vm->GetJSThread(), hashWeakSet);
4111     JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(weakSet);
4112     return JSNApiHelper::ToLocal<WeakSetRef>(setTag);
4113 }
4114 
Add(const EcmaVM * vm,Local<JSValueRef> value)4115 void WeakSetRef::Add(const EcmaVM *vm, Local<JSValueRef> value)
4116 {
4117     CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
4118     JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
4119     LOG_IF_SPECIAL(weakSet, ERROR);
4120     JSWeakSet::Add(vm->GetJSThread(), weakSet, JSNApiHelper::ToJSHandle(value));
4121 }
4122 
~TryCatch()4123 TryCatch::~TryCatch() {}
4124 
HasCaught() const4125 bool TryCatch::HasCaught() const
4126 {
4127     return ecmaVm_->GetJSThread()->HasPendingException();
4128 }
4129 
Rethrow()4130 void TryCatch::Rethrow()
4131 {
4132     rethrow_ = true;
4133 }
4134 
GetAndClearException()4135 Local<ObjectRef> TryCatch::GetAndClearException()
4136 {
4137     return JSNApiHelper::ToLocal<ObjectRef>(ecmaVm_->GetAndClearEcmaUncaughtException());
4138 }
4139 
GetException()4140 Local<ObjectRef> TryCatch::GetException()
4141 {
4142     return JSNApiHelper::ToLocal<ObjectRef>(ecmaVm_->GetEcmaUncaughtException());
4143 }
4144 
ClearException()4145 void TryCatch::ClearException()
4146 {
4147     ecmaVm_->GetJSThread()->ClearException();
4148 }
4149 
4150 } // namespace panda
4151