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