1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "jsnapi_helper.h"
17
18 #include <array>
19 #include <cstdint>
20
21 #include "ecmascript/base/builtins_base.h"
22 #include "ecmascript/base/json_parser.h"
23 #include "ecmascript/base/json_stringifier.h"
24 #include "ecmascript/base/path_helper.h"
25 #include "ecmascript/base/string_helper.h"
26 #include "ecmascript/base/typed_array_helper-inl.h"
27 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
28 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
29 #endif
30 #include "ecmascript/debugger/js_debugger_manager.h"
31 #include "ecmascript/ecma_global_storage.h"
32 #include "ecmascript/ecma_runtime_call_info.h"
33 #include "ecmascript/ecma_string.h"
34 #include "ecmascript/ecma_vm.h"
35 #include "ecmascript/aot_file_manager.h"
36 #include "ecmascript/global_env.h"
37 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
38 #include "ecmascript/jobs/micro_job_queue.h"
39 #include "ecmascript/jspandafile/debug_info_extractor.h"
40 #include "ecmascript/jspandafile/js_pandafile_executor.h"
41 #include "ecmascript/jspandafile/js_pandafile_manager.h"
42 #include "ecmascript/jspandafile/quick_fix_manager.h"
43 #include "ecmascript/js_array.h"
44 #include "ecmascript/js_arraybuffer.h"
45 #include "ecmascript/js_bigint.h"
46 #include "ecmascript/js_collator.h"
47 #include "ecmascript/js_dataview.h"
48 #include "ecmascript/byte_array.h"
49 #include "ecmascript/js_date_time_format.h"
50 #include "ecmascript/js_file_path.h"
51 #include "ecmascript/js_function.h"
52 #include "ecmascript/js_generator_object.h"
53 #include "ecmascript/js_iterator.h"
54 #include "ecmascript/js_map.h"
55 #include "ecmascript/js_map_iterator.h"
56 #include "ecmascript/js_number_format.h"
57 #include "ecmascript/js_primitive_ref.h"
58 #include "ecmascript/js_promise.h"
59 #include "ecmascript/js_regexp.h"
60 #include "ecmascript/js_runtime_options.h"
61 #include "ecmascript/js_serializer.h"
62 #include "ecmascript/js_set.h"
63 #include "ecmascript/js_set_iterator.h"
64 #include "ecmascript/js_tagged_number.h"
65 #include "ecmascript/js_thread.h"
66 #include "ecmascript/js_typed_array.h"
67 #include "ecmascript/linked_hash_table.h"
68 #include "ecmascript/log.h"
69 #include "ecmascript/mem/mem.h"
70 #include "ecmascript/mem/mem_map_allocator.h"
71 #include "ecmascript/mem/region.h"
72 #include "ecmascript/module/js_module_manager.h"
73 #include "ecmascript/module/js_module_source_text.h"
74 #include "ecmascript/object_factory.h"
75 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
76 #include "ecmascript/platform/file.h"
77 #include "ecmascript/tagged_array.h"
78 #include "ecmascript/regexp/regexp_parser.h"
79
80 #include "ohos/init_data.h"
81
82 #include "os/mutex.h"
83
84 #if defined(PANDA_TARGET_IOS)
85 namespace OHOS::ArkCompiler::Toolchain {
86 using DebuggerPostTask = std::function<void(std::function<void()> &&)>;
87 extern "C" {
88 bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, int32_t instanceId,
89 const DebuggerPostTask& debuggerPostTask);
90 void StopDebug(const std::string& componentName);
91 }
92 } // namespace OHOS::ArkCompiler::Toolchain
93 const std::string DEBUGGER_NAME = "PandaDebugger";
94 #endif
95
96 namespace panda {
97 using ecmascript::ECMAObject;
98 using ecmascript::EcmaString;
99 using ecmascript::EcmaStringAccessor;
100 using ecmascript::ErrorType;
101 using ecmascript::FastRuntimeStub;
102 using ecmascript::GlobalEnv;
103 using ecmascript::GlobalEnvConstants;
104 using ecmascript::EcmaRuntimeCallInfo;
105 using ecmascript::JSArray;
106 using ecmascript::JSArrayBuffer;
107 using ecmascript::JSDataView;
108 using ecmascript::ByteArray;
109 using ecmascript::JSDate;
110 using ecmascript::JSFunction;
111 using ecmascript::JSFunctionBase;
112 using ecmascript::JSHClass;
113 using ecmascript::JSMap;
114 using ecmascript::Method;
115 using ecmascript::JSNativePointer;
116 using ecmascript::JSObject;
117 using ecmascript::JSPandaFile;
118 using ecmascript::JSPandaFileManager;
119 using ecmascript::JSPrimitiveRef;
120 using ecmascript::JSPromise;
121 using ecmascript::JSRegExp;
122 using ecmascript::JSSerializer;
123 using ecmascript::JSSet;
124 using ecmascript::JSSymbol;
125 using ecmascript::JSTaggedNumber;
126 using ecmascript::JSTaggedType;
127 using ecmascript::JSTaggedValue;
128 using ecmascript::JSThread;
129 using ecmascript::LinkedHashMap;
130 using ecmascript::LinkedHashSet;
131 using ecmascript::ObjectFactory;
132 using ecmascript::PromiseCapability;
133 using ecmascript::PropertyDescriptor;
134 using ecmascript::OperationResult;
135 using ecmascript::Region;
136 using ecmascript::TaggedArray;
137 using ecmascript::JSTypedArray;
138 using ecmascript::base::BuiltinsBase;
139 using ecmascript::base::JsonParser;
140 using ecmascript::base::JsonStringifier;
141 using ecmascript::base::StringHelper;
142 using ecmascript::base::TypedArrayHelper;
143 using ecmascript::job::MicroJobQueue;
144 using ecmascript::job::QueueType;
145 using ecmascript::JSRuntimeOptions;
146 using ecmascript::BigInt;
147 using ecmascript::MemMapAllocator;
148 using ecmascript::JSMapIterator;
149 using ecmascript::JSSetIterator;
150 using ecmascript::IterationKind;
151 using ecmascript::JSGeneratorState;
152 using ecmascript::JSIterator;
153 using ecmascript::JSGeneratorFunction;
154 using ecmascript::JSGeneratorObject;
155 using ecmascript::GeneratorContext;
156 using ecmascript::JSCollator;
157 using ecmascript::JSDateTimeFormat;
158 using ecmascript::JSNumberFormat;
159 using ecmascript::RegExpParser;
160 using ecmascript::DebugInfoExtractor;
161 using ecmascript::base::NumberHelper;
162 template<typename T>
163 using JSHandle = ecmascript::JSHandle<T>;
164
165 template<typename T>
166 using JSMutableHandle = ecmascript::JSMutableHandle<T>;
167
168 using PathHelper = ecmascript::base::PathHelper;
169 namespace {
170 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
171 constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0";
172 }
173 int JSNApi::vmCount_ = 0;
174 bool JSNApi::initialize_ = false;
175 static os::memory::Mutex mutex;
176
177 // ------------------------------------ Panda -----------------------------------------------
CreateJSVM(const RuntimeOption & option)178 EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option)
179 {
180 JSRuntimeOptions runtimeOptions;
181 runtimeOptions.SetArkProperties(option.GetArkProperties());
182 runtimeOptions.SetArkBundleName(option.GetArkBundleName());
183 runtimeOptions.SetLongPauseTime(option.GetLongPauseTime());
184 runtimeOptions.SetGcThreadNum(option.GetGcThreadNum());
185 runtimeOptions.SetIsWorker(option.GetIsWorker());
186 // Mem
187 runtimeOptions.SetHeapSizeLimit(option.GetGcPoolSize());
188 // Disable the asm-interpreter of ark-engine for ios-platform temporarily.
189 #if !defined(PANDA_TARGET_IOS) && !defined(DISABLE_ASM_INTERPRETER)
190 // asmInterpreter
191 runtimeOptions.SetEnableAsmInterpreter(option.GetEnableAsmInterpreter());
192 #else
193 runtimeOptions.SetEnableAsmInterpreter(false);
194 #endif
195 runtimeOptions.SetAsmOpcodeDisableRange(option.GetAsmOpcodeDisableRange());
196 // aot
197 runtimeOptions.SetEnableAOT(option.GetEnableAOT());
198 runtimeOptions.SetEnablePGOProfiler(option.GetEnableProfile());
199 runtimeOptions.SetPGOProfilerPath(option.GetProfileDir());
200
201 // Dfx
202 runtimeOptions.SetLogLevel(option.GetLogLevel());
203 runtimeOptions.SetEnableArkTools(option.GetEnableArkTools());
204 return CreateEcmaVM(runtimeOptions);
205 }
206
CreateEcmaVM(const JSRuntimeOptions & options)207 EcmaVM *JSNApi::CreateEcmaVM(const JSRuntimeOptions &options)
208 {
209 {
210 os::memory::LockHolder lock(mutex);
211 vmCount_++;
212 if (!initialize_) {
213 ecmascript::Log::Initialize(options);
214 InitializeIcuData(options);
215 InitializeMemMapAllocator();
216 InitializePGOProfiler(options);
217 initialize_ = true;
218 }
219 }
220 auto config = ecmascript::EcmaParamConfiguration(options.IsWorker(),
221 MemMapAllocator::GetInstance()->GetCapacity());
222 LOG_ECMA(INFO) << " [NAPI]: CreateEcmaVM, isWorker = " << options.IsWorker() << ", vmCount = " << vmCount_;
223 MemMapAllocator::GetInstance()->IncreaseAndCheckReserved(config.GetMaxHeapSize());
224 return EcmaVM::Create(options, config);
225 }
226
DestroyJSVM(EcmaVM * ecmaVm)227 void JSNApi::DestroyJSVM(EcmaVM *ecmaVm)
228 {
229 os::memory::LockHolder lock(mutex);
230 if (!initialize_) {
231 return;
232 }
233 auto &config = ecmaVm->GetEcmaParamConfiguration();
234 MemMapAllocator::GetInstance()->DecreaseReserved(config.GetMaxHeapSize());
235 EcmaVM::Destroy(ecmaVm);
236 vmCount_--;
237 if (vmCount_ <= 0) {
238 DestoryAnDataManager();
239 DestroyMemMapAllocator();
240 DestroyPGOProfiler();
241 initialize_ = false;
242 }
243 }
244
CleanJSVMCache()245 void JSNApi::CleanJSVMCache()
246 {
247 JSPandaFileManager::GetInstance()->ClearCache();
248 }
249
TriggerGC(const EcmaVM * vm,TRIGGER_GC_TYPE gcType)250 void JSNApi::TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType)
251 {
252 if (vm->GetJSThread() != nullptr && vm->IsInitialized()) {
253 switch (gcType) {
254 case TRIGGER_GC_TYPE::SEMI_GC:
255 vm->CollectGarbage(ecmascript::TriggerGCType::YOUNG_GC);
256 break;
257 case TRIGGER_GC_TYPE::OLD_GC:
258 vm->CollectGarbage(ecmascript::TriggerGCType::OLD_GC);
259 break;
260 case TRIGGER_GC_TYPE::FULL_GC:
261 vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC);
262 break;
263 default:
264 break;
265 }
266 }
267 }
268
ThrowException(const EcmaVM * vm,Local<JSValueRef> error)269 void JSNApi::ThrowException(const EcmaVM *vm, Local<JSValueRef> error)
270 {
271 auto thread = vm->GetJSThread();
272 thread->SetException(JSNApiHelper::ToJSTaggedValue(*error));
273 }
274
275 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
276 #if !defined(PANDA_TARGET_IOS)
StartDebugger(const char * libraryPath,EcmaVM * vm,bool isDebugMode,int32_t instanceId,const DebuggerPostTask & debuggerPostTask)277 bool JSNApi::StartDebugger(const char *libraryPath, EcmaVM *vm, bool isDebugMode, int32_t instanceId,
278 const DebuggerPostTask &debuggerPostTask)
279 {
280 const auto &handler = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
281 if (handler.IsValid()) {
282 return false;
283 }
284
285 auto handle = panda::os::library_loader::Load(std::string(libraryPath));
286 if (!handle) {
287 return false;
288 }
289
290 using StartDebugger = bool (*)(const std::string &, EcmaVM *, bool, int32_t, const DebuggerPostTask &);
291
292 auto sym = panda::os::library_loader::ResolveSymbol(handle.Value(), "StartDebug");
293 if (!sym) {
294 LOG_ECMA(ERROR) << sym.Error().ToString();
295 return false;
296 }
297
298 bool ret = reinterpret_cast<StartDebugger>(sym.Value())("PandaDebugger", vm, isDebugMode, instanceId,
299 debuggerPostTask);
300 if (ret) {
301 vm->GetJsDebuggerManager()->SetDebugMode(isDebugMode);
302 vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(handle.Value()));
303 }
304 return ret;
305 }
306
StopDebugger(EcmaVM * vm)307 bool JSNApi::StopDebugger(EcmaVM *vm)
308 {
309 if (vm == nullptr) {
310 return false;
311 }
312 const auto &handle = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
313
314 using StopDebug = void (*)(const std::string &);
315
316 auto sym = panda::os::library_loader::ResolveSymbol(handle, "StopDebug");
317 if (!sym) {
318 LOG_ECMA(ERROR) << sym.Error().ToString();
319 return false;
320 }
321
322 reinterpret_cast<StopDebug>(sym.Value())("PandaDebugger");
323 vm->GetJsDebuggerManager()->SetDebugMode(false);
324 return true;
325 }
326 #else
StartDebugger(EcmaVM * vm,bool isDebugMode,int32_t instanceId,const DebuggerPostTask & debuggerPostTask)327 bool JSNApi::StartDebugger(EcmaVM *vm, bool isDebugMode, int32_t instanceId, const DebuggerPostTask &debuggerPostTask)
328 {
329 bool ret = OHOS::ArkCompiler::Toolchain::StartDebug(DEBUGGER_NAME, vm, isDebugMode, instanceId, debuggerPostTask);
330 if (ret) {
331 vm->GetJsDebuggerManager()->SetDebugMode(isDebugMode);
332 }
333 return ret;
334 }
335
StopDebugger(EcmaVM * vm)336 bool JSNApi::StopDebugger(EcmaVM *vm)
337 {
338 if (vm == nullptr) {
339 return false;
340 }
341
342 OHOS::ArkCompiler::Toolchain::StopDebug(DEBUGGER_NAME);
343 vm->GetJsDebuggerManager()->SetDebugMode(false);
344 return true;
345 }
346 #endif
347
IsMixedDebugEnabled(const EcmaVM * vm)348 bool JSNApi::IsMixedDebugEnabled(const EcmaVM *vm)
349 {
350 return vm->GetJsDebuggerManager()->IsMixedDebugEnabled();
351 }
352
NotifyNativeCalling(const EcmaVM * vm,const void * nativeAddress)353 void JSNApi::NotifyNativeCalling(const EcmaVM *vm, const void *nativeAddress)
354 {
355 vm->GetJsDebuggerManager()->GetNotificationManager()->NativeCallingEvent(nativeAddress);
356 }
357 #endif
358
LoadAotFile(EcmaVM * vm,const std::string & hapPath)359 void JSNApi::LoadAotFile(EcmaVM *vm, const std::string &hapPath)
360 {
361 if (!ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
362 return;
363 }
364 std::string aotFileName = ecmascript::AnFileDataManager::GetInstance()->GetDir();
365 aotFileName += ecmascript::JSFilePath::GetFileName(hapPath);
366 LOG_ECMA(INFO) << "start to load aot file: " << aotFileName;
367 vm->LoadAOTFiles(aotFileName);
368 }
369
Execute(EcmaVM * vm,const std::string & fileName,const std::string & entry,bool needUpdate)370 bool JSNApi::Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry, bool needUpdate)
371 {
372 LOG_ECMA(DEBUG) << "start to execute ark file: " << fileName;
373 JSThread *thread = vm->GetAssociatedJSThread();
374 if (!ecmascript::JSPandaFileExecutor::ExecuteFromFile(thread, fileName.c_str(), entry, needUpdate)) {
375 LOG_ECMA(ERROR) << "Cannot execute ark file '" << fileName
376 << "' with entry '" << entry << "'" << std::endl;
377 return false;
378 }
379 return true;
380 }
381
Execute(EcmaVM * vm,const uint8_t * data,int32_t size,const std::string & entry,const std::string & filename,bool needUpdate)382 bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry,
383 const std::string &filename, bool needUpdate)
384 {
385 LOG_ECMA(DEBUG) << "start to execute ark buffer: " << filename;
386 JSThread *thread = vm->GetAssociatedJSThread();
387 if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(
388 thread, data, size, entry, filename.c_str(), needUpdate)) {
389 LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename
390 << "' with entry '" << entry << "'" << std::endl;
391 return false;
392 }
393 return true;
394 }
395
ExecuteModuleBuffer(EcmaVM * vm,const uint8_t * data,int32_t size,const std::string & filename,bool needUpdate)396 bool JSNApi::ExecuteModuleBuffer(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &filename,
397 bool needUpdate)
398 {
399 LOG_ECMA(DEBUG) << "start to execute module buffer: " << filename;
400 JSThread *thread = vm->GetAssociatedJSThread();
401 if (!ecmascript::JSPandaFileExecutor::ExecuteModuleBuffer(thread, data, size, filename.c_str(), needUpdate)) {
402 LOG_ECMA(ERROR) << "Cannot execute module buffer file '" << filename;
403 return false;
404 }
405 return true;
406 }
407
PreFork(EcmaVM * vm)408 void JSNApi::PreFork(EcmaVM *vm)
409 {
410 vm->PreFork();
411 }
412
PostFork(EcmaVM * vm,const RuntimeOption & option)413 void JSNApi::PostFork(EcmaVM *vm, const RuntimeOption &option)
414 {
415 JSRuntimeOptions &jsOption = vm->GetJSOptions();
416 LOG_ECMA(INFO) << "asmint: " << jsOption.GetEnableAsmInterpreter()
417 << ", aot: " << jsOption.GetEnableAOT()
418 << ", bundle name: " << option.GetBundleName();
419 jsOption.SetEnablePGOProfiler(option.GetEnableProfile());
420 vm->ResetPGOProfiler();
421
422 if (jsOption.GetEnableAOT() && option.GetAnDir().size()) {
423 ecmascript::AnFileDataManager::GetInstance()->SetDir(option.GetAnDir());
424 ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
425 }
426
427 vm->PostFork();
428 }
429
addWorker(EcmaVM * hostVm,EcmaVM * workerVm)430 void JSNApi::addWorker(EcmaVM *hostVm, EcmaVM *workerVm)
431 {
432 if (hostVm != nullptr && workerVm != nullptr) {
433 hostVm->WorkersetInfo(hostVm, workerVm);
434 }
435 }
436
DeleteWorker(EcmaVM * hostVm,EcmaVM * workerVm)437 bool JSNApi::DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm)
438 {
439 if (hostVm != nullptr && workerVm != nullptr) {
440 return hostVm->DeleteWorker(hostVm, workerVm);
441 }
442 return false;
443 }
444
GetUncaughtException(const EcmaVM * vm)445 Local<ObjectRef> JSNApi::GetUncaughtException(const EcmaVM *vm)
446 {
447 return JSNApiHelper::ToLocal<ObjectRef>(vm->GetEcmaUncaughtException());
448 }
449
GetAndClearUncaughtException(const EcmaVM * vm)450 Local<ObjectRef> JSNApi::GetAndClearUncaughtException(const EcmaVM *vm)
451 {
452 return JSNApiHelper::ToLocal<ObjectRef>(vm->GetAndClearEcmaUncaughtException());
453 }
454
HasPendingException(const EcmaVM * vm)455 bool JSNApi::HasPendingException(const EcmaVM *vm)
456 {
457 return vm->GetJSThread()->HasPendingException();
458 }
459
EnableUserUncaughtErrorHandler(EcmaVM * vm)460 void JSNApi::EnableUserUncaughtErrorHandler(EcmaVM *vm)
461 {
462 return vm->EnableUserUncaughtErrorHandler();
463 }
464
GetGlobalObject(const EcmaVM * vm)465 Local<ObjectRef> JSNApi::GetGlobalObject(const EcmaVM *vm)
466 {
467 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
468 JSHandle<JSTaggedValue> global(vm->GetJSThread(), globalEnv->GetGlobalObject());
469 return JSNApiHelper::ToLocal<ObjectRef>(global);
470 }
471
ExecutePendingJob(const EcmaVM * vm)472 void JSNApi::ExecutePendingJob(const EcmaVM *vm)
473 {
474 EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
475 }
476
GetHandleAddr(const EcmaVM * vm,uintptr_t localAddress)477 uintptr_t JSNApi::GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
478 {
479 if (localAddress == 0) {
480 return 0;
481 }
482 JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
483 return ecmascript::EcmaHandleScope::NewHandle(vm->GetJSThread(), value);
484 }
485
GetGlobalHandleAddr(const EcmaVM * vm,uintptr_t localAddress)486 uintptr_t JSNApi::GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
487 {
488 if (localAddress == 0) {
489 return 0;
490 }
491 JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
492 return vm->GetJSThread()->NewGlobalHandle(value);
493 }
494
SetWeak(const EcmaVM * vm,uintptr_t localAddress)495 uintptr_t JSNApi::SetWeak(const EcmaVM *vm, uintptr_t localAddress)
496 {
497 if (localAddress == 0) {
498 return 0;
499 }
500 return vm->GetJSThread()->SetWeak(localAddress);
501 }
502
SetWeakCallback(const EcmaVM * vm,uintptr_t localAddress,void * ref,WeakRefClearCallBack firstCallback,WeakRefClearCallBack secondCallback)503 uintptr_t JSNApi::SetWeakCallback(const EcmaVM *vm, uintptr_t localAddress, void *ref,
504 WeakRefClearCallBack firstCallback, WeakRefClearCallBack secondCallback)
505 {
506 if (localAddress == 0) {
507 return 0;
508 }
509 return vm->GetJSThread()->SetWeak(localAddress, ref, firstCallback, secondCallback);
510 }
511
ClearWeak(const EcmaVM * vm,uintptr_t localAddress)512 uintptr_t JSNApi::ClearWeak(const EcmaVM *vm, uintptr_t localAddress)
513 {
514 if (localAddress == 0) {
515 return 0;
516 }
517 if (JSTaggedValue(reinterpret_cast<ecmascript::Node *>(localAddress)->GetObject())
518 .IsUndefined()) {
519 LOG_ECMA(ERROR) << "The object of weak reference has been recycled!";
520 return 0;
521 }
522 return vm->GetJSThread()->ClearWeak(localAddress);
523 }
524
IsWeak(const EcmaVM * vm,uintptr_t localAddress)525 bool JSNApi::IsWeak(const EcmaVM *vm, uintptr_t localAddress)
526 {
527 if (localAddress == 0) {
528 return false;
529 }
530 return vm->GetJSThread()->IsWeak(localAddress);
531 }
532
DisposeGlobalHandleAddr(const EcmaVM * vm,uintptr_t addr)533 void JSNApi::DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr)
534 {
535 if (addr == 0 || !reinterpret_cast<ecmascript::Node *>(addr)->IsUsing()) {
536 return;
537 }
538 vm->GetJSThread()->DisposeGlobalHandle(addr);
539 }
540
SerializeValue(const EcmaVM * vm,Local<JSValueRef> value,Local<JSValueRef> transfer)541 void *JSNApi::SerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer)
542 {
543 ecmascript::JSThread *thread = vm->GetJSThread();
544 ecmascript::Serializer serializer(thread);
545 JSHandle<JSTaggedValue> arkValue = JSNApiHelper::ToJSHandle(value);
546 JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer);
547 std::unique_ptr<ecmascript::SerializationData> data;
548 if (serializer.WriteValue(thread, arkValue, arkTransfer)) {
549 data = serializer.Release();
550 }
551 if (data == nullptr) {
552 return nullptr;
553 } else {
554 return reinterpret_cast<void *>(data.release());
555 }
556 }
557
DeserializeValue(const EcmaVM * vm,void * recoder,void * hint)558 Local<JSValueRef> JSNApi::DeserializeValue(const EcmaVM *vm, void *recoder, void *hint)
559 {
560 ecmascript::JSThread *thread = vm->GetJSThread();
561 std::unique_ptr<ecmascript::SerializationData> data(reinterpret_cast<ecmascript::SerializationData *>(recoder));
562 ecmascript::Deserializer deserializer(thread, data.release(), hint);
563 JSHandle<JSTaggedValue> result = deserializer.ReadValue();
564 return JSNApiHelper::ToLocal<ObjectRef>(result);
565 }
566
DeleteSerializationData(void * data)567 void JSNApi::DeleteSerializationData(void *data)
568 {
569 ecmascript::SerializationData *value = reinterpret_cast<ecmascript::SerializationData *>(data);
570 delete value;
571 value = nullptr;
572 }
573
HostPromiseRejectionTracker(const EcmaVM * vm,const JSHandle<JSPromise> promise,const JSHandle<JSTaggedValue> reason,const ecmascript::PromiseRejectionEvent operation,void * data)574 void HostPromiseRejectionTracker(const EcmaVM *vm,
575 const JSHandle<JSPromise> promise,
576 const JSHandle<JSTaggedValue> reason,
577 const ecmascript::PromiseRejectionEvent operation,
578 void* data)
579 {
580 ecmascript::PromiseRejectCallback promiseRejectCallback = vm->GetPromiseRejectCallback();
581 if (promiseRejectCallback != nullptr) {
582 Local<JSValueRef> promiseVal = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>::Cast(promise));
583 PromiseRejectInfo promiseRejectInfo(promiseVal, JSNApiHelper::ToLocal<JSValueRef>(reason),
584 static_cast<PromiseRejectInfo::PROMISE_REJECTION_EVENT>(operation), data);
585 promiseRejectCallback(reinterpret_cast<void*>(&promiseRejectInfo));
586 }
587 }
588
SetHostPromiseRejectionTracker(EcmaVM * vm,void * cb,void * data)589 void JSNApi::SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data)
590 {
591 vm->SetHostPromiseRejectionTracker(HostPromiseRejectionTracker);
592 vm->SetPromiseRejectCallback(reinterpret_cast<ecmascript::PromiseRejectCallback>(cb));
593 vm->SetData(data);
594 }
595
SetHostResolveBufferTracker(EcmaVM * vm,std::function<std::vector<uint8_t> (std::string dirPath,std::string requestPath)> cb)596 void JSNApi::SetHostResolveBufferTracker(EcmaVM *vm,
597 std::function<std::vector<uint8_t>(std::string dirPath, std::string requestPath)> cb)
598 {
599 vm->SetResolveBufferCallback(cb);
600 }
601
SetNativePtrGetter(EcmaVM * vm,void * cb)602 void JSNApi::SetNativePtrGetter(EcmaVM *vm, void* cb)
603 {
604 vm->SetNativePtrGetter(reinterpret_cast<ecmascript::NativePtrGetter>(cb));
605 }
606
SetHostEnqueueJob(const EcmaVM * vm,Local<JSValueRef> cb)607 void JSNApi::SetHostEnqueueJob(const EcmaVM *vm, Local<JSValueRef> cb)
608 {
609 JSHandle<JSFunction> fun = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(cb));
610 JSHandle<TaggedArray> array = vm->GetFactory()->EmptyArray();
611 JSHandle<MicroJobQueue> job = vm->GetMicroJobQueue();
612 MicroJobQueue::EnqueueJob(vm->GetJSThread(), job, QueueType::QUEUE_PROMISE, fun, array);
613 }
614
PromiseRejectInfo(Local<JSValueRef> promise,Local<JSValueRef> reason,PromiseRejectInfo::PROMISE_REJECTION_EVENT operation,void * data)615 PromiseRejectInfo::PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason,
616 PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data)
617 : promise_(promise), reason_(reason), operation_(operation), data_(data) {}
618
GetPromise() const619 Local<JSValueRef> PromiseRejectInfo::GetPromise() const
620 {
621 return promise_;
622 }
623
GetReason() const624 Local<JSValueRef> PromiseRejectInfo::GetReason() const
625 {
626 return reason_;
627 }
628
GetOperation() const629 PromiseRejectInfo::PROMISE_REJECTION_EVENT PromiseRejectInfo::GetOperation() const
630 {
631 return operation_;
632 }
633
GetData() const634 void* PromiseRejectInfo::GetData() const
635 {
636 return data_;
637 }
638
ExecuteModuleFromBuffer(EcmaVM * vm,const void * data,int32_t size,const std::string & file)639 bool JSNApi::ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file)
640 {
641 JSThread *thread = vm->GetAssociatedJSThread();
642 if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(thread, data, size, ENTRY_POINTER, file.c_str())) {
643 std::cerr << "Cannot execute panda file from memory" << std::endl;
644 return false;
645 }
646 return true;
647 }
648
GetExportObject(EcmaVM * vm,const std::string & file,const std::string & key)649 Local<ObjectRef> JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, const std::string &key)
650 {
651 ecmascript::CString entry = file.c_str();
652 JSThread *thread = vm->GetJSThread();
653 ecmascript::CString name = vm->GetAssetPath();
654 if (!vm->IsBundlePack()) {
655 entry = PathHelper::ParseOhmUrl(vm, entry, name);
656 const JSPandaFile *jsPandaFile =
657 JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry.c_str(), false);
658 if (jsPandaFile == nullptr) {
659 JSHandle<JSTaggedValue> exportObj(thread, JSTaggedValue::Null());
660 return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
661 }
662 if (!jsPandaFile->IsRecordWithBundleName()) {
663 PathHelper::CroppingRecord(entry);
664 }
665 }
666 ecmascript::ModuleManager *moduleManager = vm->GetModuleManager();
667 JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(entry);
668 if (ecmaModule->GetIsNewBcVersion()) {
669 int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key);
670 JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
671 JSHandle<JSTaggedValue> exportObj(thread, result);
672 return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
673 }
674 ObjectFactory *factory = vm->GetFactory();
675 JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
676
677 JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
678 JSHandle<JSTaggedValue> exportObj(thread, result);
679 return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
680 }
681
GetExportObjectFromBuffer(EcmaVM * vm,const std::string & file,const std::string & key)682 Local<ObjectRef> JSNApi::GetExportObjectFromBuffer(EcmaVM *vm, const std::string &file,
683 const std::string &key)
684 {
685 ecmascript::ModuleManager *moduleManager = vm->GetModuleManager();
686 JSThread *thread = vm->GetJSThread();
687 JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(file.c_str());
688
689 if (ecmaModule->GetIsNewBcVersion()) {
690 int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key);
691 JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
692 JSHandle<JSTaggedValue> exportObj(thread, result);
693 return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
694 }
695
696 ObjectFactory *factory = vm->GetFactory();
697 JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
698 JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
699 JSHandle<JSTaggedValue> exportObj(thread, result);
700 return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
701 }
702
703 // Initialize IcuData Path
InitializeIcuData(const JSRuntimeOptions & options)704 void JSNApi::InitializeIcuData(const JSRuntimeOptions &options)
705 {
706 std::string icuPath = options.GetIcuDataPath();
707 if (icuPath == "default") {
708 #if !WIN_OR_MAC_OR_IOS_PLATFORM && !defined(PANDA_TARGET_LINUX)
709 SetHwIcuDirectory();
710 #endif
711 } else {
712 std::string absPath;
713 if (ecmascript::RealPath(icuPath, absPath)) {
714 u_setDataDirectory(absPath.c_str());
715 }
716 }
717 }
718
InitializeMemMapAllocator()719 void JSNApi::InitializeMemMapAllocator()
720 {
721 MemMapAllocator::GetInstance()->Initialize(ecmascript::DEFAULT_REGION_SIZE);
722 }
723
DestroyMemMapAllocator()724 void JSNApi::DestroyMemMapAllocator()
725 {
726 MemMapAllocator::GetInstance()->Finalize();
727 }
728
InitializePGOProfiler(const ecmascript::JSRuntimeOptions & options)729 void JSNApi::InitializePGOProfiler(const ecmascript::JSRuntimeOptions &options)
730 {
731 ecmascript::PGOProfilerManager::GetInstance()->Initialize(
732 options.GetPGOProfilerPath(), options.GetPGOHotnessThreshold());
733 }
734
DestroyPGOProfiler()735 void JSNApi::DestroyPGOProfiler()
736 {
737 ecmascript::PGOProfilerManager::GetInstance()->Destroy();
738 }
739
DestoryAnDataManager()740 void JSNApi::DestoryAnDataManager()
741 {
742 ecmascript::AnFileDataManager::GetInstance()->SafeDestoryAllData();
743 }
744
745 // ----------------------------------- HandleScope -------------------------------------
LocalScope(const EcmaVM * vm)746 LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread())
747 {
748 auto thread = reinterpret_cast<JSThread *>(thread_);
749 prevNext_ = thread->GetHandleScopeStorageNext();
750 prevEnd_ = thread->GetHandleScopeStorageEnd();
751 prevHandleStorageIndex_ = thread->GetCurrentHandleStorageIndex();
752 thread->HandleScopeCountAdd();
753 }
754
LocalScope(const EcmaVM * vm,JSTaggedType value)755 LocalScope::LocalScope(const EcmaVM *vm, JSTaggedType value) : thread_(vm->GetJSThread())
756 {
757 auto thread = reinterpret_cast<JSThread *>(thread_);
758 ecmascript::EcmaHandleScope::NewHandle(thread, value);
759 prevNext_ = thread->GetHandleScopeStorageNext();
760 prevEnd_ = thread->GetHandleScopeStorageEnd();
761 prevHandleStorageIndex_ = thread->GetCurrentHandleStorageIndex();
762 thread->HandleScopeCountAdd();
763 }
764
~LocalScope()765 LocalScope::~LocalScope()
766 {
767 auto thread = reinterpret_cast<JSThread *>(thread_);
768 thread->HandleScopeCountDec();
769 thread->SetHandleScopeStorageNext(static_cast<JSTaggedType *>(prevNext_));
770 if (thread->GetHandleScopeStorageEnd() != prevEnd_) {
771 thread->SetHandleScopeStorageEnd(static_cast<JSTaggedType *>(prevEnd_));
772 thread->ShrinkHandleStorage(prevHandleStorageIndex_);
773 }
774 }
775
776 // ----------------------------------- EscapeLocalScope ------------------------------
EscapeLocalScope(const EcmaVM * vm)777 EscapeLocalScope::EscapeLocalScope(const EcmaVM *vm) : LocalScope(vm, JSTaggedValue::Undefined().GetRawData())
778 {
779 auto thread = vm->GetJSThread();
780 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
781 escapeHandle_ = ToUintPtr(thread->GetHandleScopeStorageNext() - 1);
782 }
783
784 // ----------------------------------- PritimitiveRef ---------------------------------------
GetValue(const EcmaVM * vm)785 Local<JSValueRef> PrimitiveRef::GetValue(const EcmaVM *vm)
786 {
787 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
788 if (obj->IsJSPrimitiveRef()) {
789 JSTaggedValue primitiveValue = JSPrimitiveRef::Cast(obj->GetTaggedObject())->GetValue();
790 JSHandle<JSTaggedValue> value = JSHandle<JSTaggedValue>(vm->GetJSThread(), primitiveValue);
791 return JSNApiHelper::ToLocal<JSValueRef>(value);
792 }
793 return Local<JSValueRef>();
794 }
795
796 // ----------------------------------- NumberRef ---------------------------------------
New(const EcmaVM * vm,double input)797 Local<NumberRef> NumberRef::New(const EcmaVM *vm, double input)
798 {
799 JSThread *thread = vm->GetJSThread();
800 if (std::isnan(input)) {
801 input = ecmascript::base::NAN_VALUE;
802 }
803 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
804 return JSNApiHelper::ToLocal<NumberRef>(number);
805 }
806
New(const EcmaVM * vm,int32_t input)807 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int32_t input)
808 {
809 JSThread *thread = vm->GetJSThread();
810 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
811 return JSNApiHelper::ToLocal<NumberRef>(number);
812 }
813
New(const EcmaVM * vm,uint32_t input)814 Local<NumberRef> NumberRef::New(const EcmaVM *vm, uint32_t input)
815 {
816 JSThread *thread = vm->GetJSThread();
817 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
818 return JSNApiHelper::ToLocal<NumberRef>(number);
819 }
820
New(const EcmaVM * vm,int64_t input)821 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int64_t input)
822 {
823 JSThread *thread = vm->GetJSThread();
824 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
825 return JSNApiHelper::ToLocal<NumberRef>(number);
826 }
827
Value()828 double NumberRef::Value()
829 {
830 return JSTaggedNumber(JSNApiHelper::ToJSTaggedValue(this)).GetNumber();
831 }
832
833 // ----------------------------------- BigIntRef ---------------------------------------
New(const EcmaVM * vm,uint64_t input)834 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, uint64_t input)
835 {
836 JSThread *thread = vm->GetJSThread();
837 JSHandle<BigInt> big = BigInt::Uint64ToBigInt(thread, input);
838 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
839 return JSNApiHelper::ToLocal<BigIntRef>(bigint);
840 }
841
New(const EcmaVM * vm,int64_t input)842 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, int64_t input)
843 {
844 JSThread *thread = vm->GetJSThread();
845 JSHandle<BigInt> big = BigInt::Int64ToBigInt(thread, input);
846 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
847 return JSNApiHelper::ToLocal<BigIntRef>(bigint);
848 }
849
CreateBigWords(const EcmaVM * vm,bool sign,uint32_t size,const uint64_t * words)850 Local<JSValueRef> BigIntRef::CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words)
851 {
852 JSThread *thread = vm->GetJSThread();
853 JSHandle<BigInt> big = BigInt::CreateBigWords(thread, sign, size, words);
854 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
855 return JSNApiHelper::ToLocal<JSValueRef>(bigint);
856 }
857
BigIntToInt64(const EcmaVM * vm,int64_t * cValue,bool * lossless)858 void BigIntRef::BigIntToInt64(const EcmaVM *vm, int64_t *cValue, bool *lossless)
859 {
860 JSThread *thread = vm->GetJSThread();
861 JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
862 BigInt::BigIntToInt64(thread, bigintVal, cValue, lossless);
863 }
864
BigIntToUint64(const EcmaVM * vm,uint64_t * cValue,bool * lossless)865 void BigIntRef::BigIntToUint64(const EcmaVM *vm, uint64_t *cValue, bool *lossless)
866 {
867 JSThread *thread = vm->GetJSThread();
868 JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
869 BigInt::BigIntToUint64(thread, bigintVal, cValue, lossless);
870 }
871
GetWordsArray(bool * signBit,size_t wordCount,uint64_t * words)872 void BigIntRef::GetWordsArray(bool* signBit, size_t wordCount, uint64_t* words)
873 {
874 JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
875 uint32_t len = bigintVal->GetLength();
876 uint32_t count = 0;
877 uint32_t index = 0;
878 for (; index < wordCount - 1; ++index) {
879 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
880 words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits
881 }
882 if (len % 2 == 0) { // 2 : len is odd or even
883 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
884 words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits
885 } else {
886 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
887 }
888 *signBit = bigintVal->GetSign();
889 }
890
GetWordsArraySize()891 uint32_t BigIntRef::GetWordsArraySize()
892 {
893 JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
894 uint32_t len = bigintVal->GetLength();
895 return len % 2 != 0 ? len / 2 + 1 : len / 2; // 2 : len is odd or even
896 }
897
898 // ----------------------------------- BooleanRef ---------------------------------------
New(const EcmaVM * vm,bool input)899 Local<BooleanRef> BooleanRef::New(const EcmaVM *vm, bool input)
900 {
901 JSThread *thread = vm->GetJSThread();
902 JSHandle<JSTaggedValue> boolean(thread, JSTaggedValue(input));
903 return JSNApiHelper::ToLocal<BooleanRef>(boolean);
904 }
905
Value()906 bool BooleanRef::Value()
907 {
908 return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
909 }
910
911 // ----------------------------------- IntegerRef ---------------------------------------
New(const EcmaVM * vm,int input)912 Local<IntegerRef> IntegerRef::New(const EcmaVM *vm, int input)
913 {
914 JSThread *thread = vm->GetJSThread();
915 JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
916 return JSNApiHelper::ToLocal<IntegerRef>(integer);
917 }
918
NewFromUnsigned(const EcmaVM * vm,unsigned int input)919 Local<IntegerRef> IntegerRef::NewFromUnsigned(const EcmaVM *vm, unsigned int input)
920 {
921 JSThread *thread = vm->GetJSThread();
922 JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
923 return JSNApiHelper::ToLocal<IntegerRef>(integer);
924 }
925
Value()926 int IntegerRef::Value()
927 {
928 return JSNApiHelper::ToJSTaggedValue(this).GetInt();
929 }
930
931 // ----------------------------------- StringRef ----------------------------------------
NewFromUtf8(const EcmaVM * vm,const char * utf8,int length)932 Local<StringRef> StringRef::NewFromUtf8(const EcmaVM *vm, const char *utf8, int length)
933 {
934 ObjectFactory *factory = vm->GetFactory();
935 if (length < 0) {
936 JSHandle<JSTaggedValue> current(factory->NewFromUtf8(utf8));
937 return JSNApiHelper::ToLocal<StringRef>(current);
938 }
939 JSHandle<JSTaggedValue> current(factory->NewFromUtf8(reinterpret_cast<const uint8_t *>(utf8), length));
940 return JSNApiHelper::ToLocal<StringRef>(current);
941 }
942
ToString()943 std::string StringRef::ToString()
944 {
945 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).ToStdString();
946 }
947
Length()948 int32_t StringRef::Length()
949 {
950 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).GetLength();
951 }
952
Utf8Length()953 int32_t StringRef::Utf8Length()
954 {
955 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).GetUtf8Length();
956 }
957
WriteUtf8(char * buffer,int length)958 int StringRef::WriteUtf8(char *buffer, int length)
959 {
960 return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
961 .WriteToFlatUtf8(reinterpret_cast<uint8_t *>(buffer), length);
962 }
963
GetNapiWrapperString(const EcmaVM * vm)964 Local<StringRef> StringRef::GetNapiWrapperString(const EcmaVM *vm)
965 {
966 JSHandle<JSTaggedValue> napiWapperString = vm->GetJSThread()->GlobalConstants()->GetHandledNapiWrapperString();
967 return JSNApiHelper::ToLocal<StringRef>(napiWapperString);
968 }
969
970 // ----------------------------------- SymbolRef -----------------------------------------
New(const EcmaVM * vm,Local<StringRef> description)971 Local<SymbolRef> SymbolRef::New(const EcmaVM *vm, Local<StringRef> description)
972 {
973 ObjectFactory *factory = vm->GetFactory();
974 JSHandle<JSSymbol> symbol = factory->NewJSSymbol();
975 JSTaggedValue desc = JSNApiHelper::ToJSTaggedValue(*description);
976 symbol->SetDescription(vm->GetJSThread(), desc);
977 return JSNApiHelper::ToLocal<SymbolRef>(JSHandle<JSTaggedValue>(symbol));
978 }
979
GetDescription(const EcmaVM * vm)980 Local<StringRef> SymbolRef::GetDescription(const EcmaVM *vm)
981 {
982 JSTaggedValue description = JSSymbol::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetDescription();
983 if (!description.IsString()) {
984 auto constants = vm->GetJSThread()->GlobalConstants();
985 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
986 }
987 JSHandle<JSTaggedValue> descriptionHandle(vm->GetJSThread(), description);
988 return JSNApiHelper::ToLocal<StringRef>(descriptionHandle);
989 }
990
991 // -------------------------------- NativePointerRef ------------------------------------
New(const EcmaVM * vm,void * nativePointer,size_t nativeBindingsize)992 Local<NativePointerRef> NativePointerRef::New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize)
993 {
994 ObjectFactory *factory = vm->GetFactory();
995 JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, nullptr, nullptr,
996 false, nativeBindingsize);
997 return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
998 }
999
New(const EcmaVM * vm,void * nativePointer,NativePointerCallback callBack,void * data,size_t nativeBindingsize)1000 Local<NativePointerRef> NativePointerRef::New(
1001 const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize)
1002 {
1003 ObjectFactory *factory = vm->GetFactory();
1004 JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data,
1005 false, nativeBindingsize);
1006 return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
1007 }
1008
Value()1009 void *NativePointerRef::Value()
1010 {
1011 JSHandle<JSTaggedValue> nativePointer = JSNApiHelper::ToJSHandle(this);
1012 return JSHandle<JSNativePointer>(nativePointer)->GetExternalPointer();
1013 }
1014
1015 // ----------------------------------- ObjectRef ----------------------------------------
New(const EcmaVM * vm)1016 Local<ObjectRef> ObjectRef::New(const EcmaVM *vm)
1017 {
1018 ObjectFactory *factory = vm->GetFactory();
1019 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
1020 JSHandle<JSFunction> constructor(globalEnv->GetObjectFunction());
1021 JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(constructor));
1022 return JSNApiHelper::ToLocal<ObjectRef>(object);
1023 }
1024
New(const EcmaVM * vm,void * detach,void * attach)1025 Local<ObjectRef> ObjectRef::New(const EcmaVM *vm, void *detach, void *attach)
1026 {
1027 ObjectFactory *factory = vm->GetFactory();
1028 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1029 JSHandle<JSFunction> constructor(env->GetObjectFunction());
1030 JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(constructor));
1031 JSHandle<JSTaggedValue> detachKey = env->GetDetachSymbol();
1032 JSHandle<JSTaggedValue> attachKey = env->GetAttachSymbol();
1033 JSHandle<JSTaggedValue> detachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, detach));
1034 JSHandle<JSTaggedValue> attachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, attach));
1035 JSTaggedValue::SetProperty(vm->GetJSThread(), object, detachKey, detachValue);
1036 JSTaggedValue::SetProperty(vm->GetJSThread(), object, attachKey, attachValue);
1037 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), JSValueRef::Undefined(vm));
1038 return JSNApiHelper::ToLocal<ObjectRef>(object);
1039 }
1040
Set(const EcmaVM * vm,void * detach,void * attach)1041 bool ObjectRef::Set(const EcmaVM *vm, void *detach, void *attach)
1042 {
1043 [[maybe_unused]] LocalScope scope(vm);
1044 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1045 JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
1046 JSHandle<JSTaggedValue> detachKey = env->GetDetachSymbol();
1047 JSHandle<JSTaggedValue> attachKey = env->GetAttachSymbol();
1048 JSHandle<JSTaggedValue> detachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, detach));
1049 JSHandle<JSTaggedValue> attachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, attach));
1050 bool detachResult = JSTaggedValue::SetProperty(vm->GetJSThread(), object, detachKey, detachValue);
1051 bool attachResult = JSTaggedValue::SetProperty(vm->GetJSThread(), object, attachKey, attachValue);
1052 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), false);
1053 return detachResult && attachResult;
1054 }
1055
Set(const EcmaVM * vm,Local<JSValueRef> key,Local<JSValueRef> value)1056 bool ObjectRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
1057 {
1058 [[maybe_unused]] LocalScope scope(vm);
1059 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1060 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1061 JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value);
1062 bool result = JSTaggedValue::SetProperty(vm->GetJSThread(), obj, keyValue, valueValue);
1063 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), false);
1064 return result;
1065 }
1066
Set(const EcmaVM * vm,uint32_t key,Local<JSValueRef> value)1067 bool ObjectRef::Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value)
1068 {
1069 [[maybe_unused]] LocalScope scope(vm);
1070 Local<JSValueRef> keyValue = NumberRef::New(vm, key);
1071 return Set(vm, keyValue, value);
1072 }
1073
SetAccessorProperty(const EcmaVM * vm,Local<JSValueRef> key,Local<FunctionRef> getter,Local<FunctionRef> setter,PropertyAttribute attribute)1074 bool ObjectRef::SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter,
1075 Local<FunctionRef> setter, PropertyAttribute attribute)
1076 {
1077 [[maybe_unused]] LocalScope scope(vm);
1078 JSThread *thread = vm->GetJSThread();
1079 JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter);
1080 JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter);
1081 PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
1082 desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
1083 desc.SetSetter(setterValue);
1084 desc.SetGetter(getterValue);
1085 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1086 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1087 bool result = JSTaggedValue::DefineOwnProperty(thread, obj, keyValue, desc);
1088 RETURN_VALUE_IF_ABRUPT(thread, false);
1089 return result;
1090 }
1091
Get(const EcmaVM * vm,Local<JSValueRef> key)1092 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
1093 {
1094 EscapeLocalScope scope(vm);
1095 JSThread *thread = vm->GetJSThread();
1096 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1097 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1098 OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue);
1099 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1100 if (!ret.GetPropertyMetaData().IsFound()) {
1101 return JSValueRef::Undefined(vm);
1102 }
1103 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(ret.GetValue()));
1104 }
1105
Get(const EcmaVM * vm,int32_t key)1106 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, int32_t key)
1107 {
1108 Local<JSValueRef> keyValue = IntegerRef::New(vm, key);
1109 return Get(vm, keyValue);
1110 }
1111
GetOwnProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute & property)1112 bool ObjectRef::GetOwnProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute &property)
1113 {
1114 JSThread *thread = vm->GetJSThread();
1115 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1116 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
1117 PropertyDescriptor desc(thread);
1118 bool ret = JSObject::GetOwnProperty(thread, JSHandle<JSObject>(obj), keyValue, desc);
1119 if (!ret) {
1120 return false;
1121 }
1122 property.SetValue(JSNApiHelper::ToLocal<JSValueRef>(desc.GetValue()));
1123 if (desc.HasGetter()) {
1124 property.SetGetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetGetter()));
1125 }
1126 if (desc.HasSetter()) {
1127 property.SetSetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetSetter()));
1128 }
1129 if (desc.HasWritable()) {
1130 property.SetWritable(desc.IsWritable());
1131 }
1132 if (desc.HasEnumerable()) {
1133 property.SetEnumerable(desc.IsEnumerable());
1134 }
1135 if (desc.HasConfigurable()) {
1136 property.SetConfigurable(desc.IsConfigurable());
1137 }
1138
1139 return true;
1140 }
1141
GetOwnPropertyNames(const EcmaVM * vm)1142 Local<ArrayRef> ObjectRef::GetOwnPropertyNames(const EcmaVM *vm)
1143 {
1144 JSThread *thread = vm->GetJSThread();
1145 JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this));
1146 JSHandle<TaggedArray> array(JSTaggedValue::GetOwnPropertyKeys(thread, obj));
1147 JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
1148 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1149 return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
1150 }
1151
GetOwnEnumerablePropertyNames(const EcmaVM * vm)1152 Local<ArrayRef> ObjectRef::GetOwnEnumerablePropertyNames(const EcmaVM *vm)
1153 {
1154 JSThread *thread = vm->GetJSThread();
1155 JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(this));
1156 JSHandle<TaggedArray> array(JSObject::EnumerableOwnNames(thread, obj));
1157 JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
1158 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1159 return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
1160 }
1161
GetPrototype(const EcmaVM * vm)1162 Local<JSValueRef> ObjectRef::GetPrototype(const EcmaVM *vm)
1163 {
1164 JSThread *thread = vm->GetJSThread();
1165 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1166 JSHandle<JSTaggedValue> prototype(thread, JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(object)));
1167 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1168 return JSNApiHelper::ToLocal<JSValueRef>(prototype);
1169 }
1170
DefineProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute attribute)1171 bool ObjectRef::DefineProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute attribute)
1172 {
1173 JSThread *thread = vm->GetJSThread();
1174 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1175 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
1176 PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
1177 desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
1178 bool result = object->DefinePropertyOrThrow(thread, object, keyValue, desc);
1179 RETURN_VALUE_IF_ABRUPT(thread, false);
1180 return result;
1181 }
1182
Has(const EcmaVM * vm,Local<JSValueRef> key)1183 bool ObjectRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
1184 {
1185 JSThread *thread = vm->GetJSThread();
1186 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1187 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
1188 bool result = object->HasProperty(thread, object, keyValue);
1189 RETURN_VALUE_IF_ABRUPT(thread, false);
1190 return result;
1191 }
1192
Has(const EcmaVM * vm,uint32_t key)1193 bool ObjectRef::Has(const EcmaVM *vm, uint32_t key)
1194 {
1195 JSThread *thread = vm->GetJSThread();
1196 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1197 bool result = object->HasProperty(thread, object, key);
1198 RETURN_VALUE_IF_ABRUPT(thread, false);
1199 return result;
1200 }
1201
Delete(const EcmaVM * vm,Local<JSValueRef> key)1202 bool ObjectRef::Delete(const EcmaVM *vm, Local<JSValueRef> key)
1203 {
1204 JSThread *thread = vm->GetJSThread();
1205 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1206 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
1207 bool result = object->DeleteProperty(thread, object, keyValue);
1208 RETURN_VALUE_IF_ABRUPT(thread, false);
1209 return result;
1210 }
1211
Delete(const EcmaVM * vm,uint32_t key)1212 bool ObjectRef::Delete(const EcmaVM *vm, uint32_t key)
1213 {
1214 JSThread *thread = vm->GetJSThread();
1215 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
1216 JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(key));
1217 bool result = object->DeleteProperty(thread, object, keyHandle);
1218 RETURN_VALUE_IF_ABRUPT(thread, false);
1219 return result;
1220 }
1221
SetNativePointerFieldCount(int32_t count)1222 void ObjectRef::SetNativePointerFieldCount(int32_t count)
1223 {
1224 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1225 object->SetNativePointerFieldCount(count);
1226 }
1227
GetNativePointerFieldCount()1228 int32_t ObjectRef::GetNativePointerFieldCount()
1229 {
1230 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1231 return object->GetNativePointerFieldCount();
1232 }
1233
GetNativePointerField(int32_t index)1234 void *ObjectRef::GetNativePointerField(int32_t index)
1235 {
1236 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1237 return object->GetNativePointerField(index);
1238 }
1239
SetNativePointerField(int32_t index,void * nativePointer,NativePointerCallback callBack,void * data,size_t nativeBindingsize)1240 void ObjectRef::SetNativePointerField(int32_t index, void *nativePointer,
1241 NativePointerCallback callBack, void *data, size_t nativeBindingsize)
1242 {
1243 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
1244 object->SetNativePointerField(index, nativePointer, callBack, data, nativeBindingsize);
1245 }
1246
1247 // ----------------------------------- FunctionRef --------------------------------------
New(EcmaVM * vm,FunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)1248 Local<FunctionRef> FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc,
1249 Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
1250 {
1251 JSThread *thread = vm->GetJSThread();
1252 ObjectFactory *factory = vm->GetFactory();
1253 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1254 JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback)));
1255 current->SetFunctionExtraInfo(thread, reinterpret_cast<void *>(nativeFunc), deleter, data, nativeBindingsize);
1256 current->SetCallNapi(callNapi);
1257 return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
1258 }
1259
NewClassFunction(EcmaVM * vm,FunctionCallback nativeFunc,Deleter deleter,void * data,bool callNapi,size_t nativeBindingsize)1260 Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, FunctionCallback nativeFunc,
1261 Deleter deleter, void *data, bool callNapi, size_t nativeBindingsize)
1262 {
1263 EscapeLocalScope scope(vm);
1264 JSThread *thread = vm->GetJSThread();
1265 ObjectFactory *factory = vm->GetFactory();
1266 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1267 JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName());
1268 JSHandle<JSFunction> current =
1269 factory->NewJSFunctionByHClass(reinterpret_cast<void *>(Callback::RegisterCallback),
1270 hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
1271
1272 auto globalConst = thread->GlobalConstants();
1273 JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor();
1274 current->SetPropertyInlinedProps(thread, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX,
1275 accessor.GetTaggedValue());
1276
1277 current->SetFunctionExtraInfo(thread, reinterpret_cast<void *>(nativeFunc), deleter, data, nativeBindingsize);
1278
1279 JSHandle<JSObject> clsPrototype = JSFunction::NewJSFunctionPrototype(thread, factory, current);
1280 clsPrototype.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassPrototype(true);
1281 JSHandle<JSTaggedValue>::Cast(current)->GetTaggedObject()->GetClass()->SetClassConstructor(true);
1282 current->SetClassConstructor(true);
1283 JSHandle<JSTaggedValue> parent = env->GetFunctionPrototype();
1284 JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(current), parent);
1285 current->SetHomeObject(thread, clsPrototype);
1286 current->SetCallNapi(callNapi);
1287 Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
1288 return scope.Escape(result);
1289 }
1290
Call(const EcmaVM * vm,Local<JSValueRef> thisObj,const Local<JSValueRef> argv[],int32_t length)1291 Local<JSValueRef> FunctionRef::Call(const EcmaVM *vm, Local<JSValueRef> thisObj,
1292 const Local<JSValueRef> argv[], // NOLINTNEXTLINE(modernize-avoid-c-arrays)
1293 int32_t length)
1294 {
1295 EscapeLocalScope scope(vm);
1296 JSThread *thread = vm->GetJSThread();
1297 if (!IsFunction()) {
1298 return JSValueRef::Undefined(vm);
1299 }
1300 vm->GetJsDebuggerManager()->ClearSingleStepper();
1301 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
1302 JSHandle<JSTaggedValue> thisValue = JSNApiHelper::ToJSHandle(thisObj);
1303 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1304 EcmaRuntimeCallInfo *info =
1305 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, length);
1306 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1307 for (int32_t i = 0; i < length; i++) {
1308 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]);
1309 info->SetCallArg(i, arg.GetTaggedValue());
1310 }
1311 JSTaggedValue result = JSFunction::Call(info);
1312 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1313 JSHandle<JSTaggedValue> resultValue(thread, result);
1314
1315 EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
1316 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1317 vm->GetHeap()->ClearKeptObjects();
1318
1319 return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
1320 }
1321
Constructor(const EcmaVM * vm,const Local<JSValueRef> argv[],int32_t length)1322 Local<JSValueRef> FunctionRef::Constructor(const EcmaVM *vm,
1323 const Local<JSValueRef> argv[], // NOLINTNEXTLINE(modernize-avoid-c-arrays)
1324 int32_t length)
1325 {
1326 JSThread *thread = vm->GetJSThread();
1327 if (!IsFunction()) {
1328 return JSValueRef::Undefined(vm);
1329 }
1330 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
1331 JSHandle<JSTaggedValue> newTarget = func;
1332 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1333 EcmaRuntimeCallInfo *info =
1334 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, newTarget, length);
1335 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1336 for (int32_t i = 0; i < length; i++) {
1337 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]);
1338 info->SetCallArg(i, arg.GetTaggedValue());
1339 }
1340 JSTaggedValue result = JSFunction::Construct(info);
1341
1342 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1343 JSHandle<JSTaggedValue> resultValue(thread, result);
1344 return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
1345 }
1346
GetFunctionPrototype(const EcmaVM * vm)1347 Local<JSValueRef> FunctionRef::GetFunctionPrototype(const EcmaVM *vm)
1348 {
1349 JSThread *thread = vm->GetJSThread();
1350 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
1351 JSHandle<JSTaggedValue> prototype(thread, JSHandle<JSFunction>(func)->GetFunctionPrototype());
1352 return JSNApiHelper::ToLocal<JSValueRef>(prototype);
1353 }
1354
Inherit(const EcmaVM * vm,Local<FunctionRef> parent)1355 bool FunctionRef::Inherit(const EcmaVM *vm, Local<FunctionRef> parent)
1356 {
1357 [[maybe_unused]] LocalScope scope(vm);
1358 JSThread *thread = vm->GetJSThread();
1359 JSHandle<JSTaggedValue> parentValue = JSNApiHelper::ToJSHandle(parent);
1360 JSHandle<JSObject> parentHandle = JSHandle<JSObject>::Cast(parentValue);
1361 JSHandle<JSObject> thisHandle = JSHandle<JSObject>::Cast(JSNApiHelper::ToJSHandle(this));
1362 // Set this.__proto__ to parent
1363 bool res = JSObject::SetPrototype(thread, thisHandle, parentValue);
1364 if (!res) {
1365 return false;
1366 }
1367 // Set this.Prototype.__proto__ to parent.Prototype
1368 JSHandle<JSTaggedValue> parentProtoType(thread, JSFunction::PrototypeGetter(thread, parentHandle));
1369 JSHandle<JSTaggedValue> thisProtoType(thread, JSFunction::PrototypeGetter(thread, thisHandle));
1370 return JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(thisProtoType), parentProtoType);
1371 }
1372
SetName(const EcmaVM * vm,Local<StringRef> name)1373 void FunctionRef::SetName(const EcmaVM *vm, Local<StringRef> name)
1374 {
1375 [[maybe_unused]] LocalScope scope(vm);
1376 JSThread *thread = vm->GetJSThread();
1377 JSFunction *func = JSFunction::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject());
1378 JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
1379 JSFunction::SetFunctionNameNoPrefix(thread, func, key);
1380 }
1381
GetName(const EcmaVM * vm)1382 Local<StringRef> FunctionRef::GetName(const EcmaVM *vm)
1383 {
1384 EscapeLocalScope scope(vm);
1385 JSThread *thread = vm->GetJSThread();
1386 JSHandle<JSFunctionBase> func = JSHandle<JSFunctionBase>(thread, JSNApiHelper::ToJSTaggedValue(this));
1387 JSHandle<JSTaggedValue> name = JSFunctionBase::GetFunctionName(thread, func);
1388 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1389 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(name));
1390 }
1391
GetSourceCode(const EcmaVM * vm,int lineNumber)1392 Local<StringRef> FunctionRef::GetSourceCode(const EcmaVM *vm, int lineNumber)
1393 {
1394 EscapeLocalScope scope(vm);
1395 JSThread *thread = vm->GetJSThread();
1396 JSHandle<JSFunctionBase> func = JSHandle<JSFunctionBase>(thread, JSNApiHelper::ToJSTaggedValue(this));
1397 JSHandle<Method> method = JSHandle<Method>(thread, func->GetMethod());
1398 const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
1399 DebugInfoExtractor *debugExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile);
1400 ecmascript::CString entry = JSPandaFile::ENTRY_FUNCTION_NAME;
1401 if (!jsPandaFile->IsBundlePack()) {
1402 JSFunction *function = JSFunction::Cast(func.GetTaggedValue().GetTaggedObject());
1403 JSTaggedValue recordName = function->GetRecordName();
1404 ASSERT(!recordName.IsHole());
1405 entry = ConvertToString(recordName);
1406 }
1407
1408 uint32_t mainMethodIndex = jsPandaFile->GetMainMethodIndex(entry);
1409 JSMutableHandle<JSTaggedValue> sourceCodeHandle(thread, BuiltinsBase::GetTaggedString(thread, ""));
1410 if (mainMethodIndex == 0) {
1411 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
1412 }
1413
1414 const std::string &allSourceCode = debugExtractor->GetSourceCode(panda_file::File::EntityId(mainMethodIndex));
1415 std::string sourceCode = StringHelper::GetSpecifiedLine(allSourceCode, lineNumber);
1416 uint32_t codeLen = sourceCode.length();
1417 if (codeLen == 0) {
1418 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
1419 }
1420
1421 if (sourceCode[codeLen - 1] == '\r') {
1422 sourceCode = sourceCode.substr(0, codeLen - 1);
1423 }
1424 sourceCodeHandle.Update(BuiltinsBase::GetTaggedString(thread, sourceCode.c_str()));
1425 return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
1426 }
1427
IsNative(const EcmaVM * vm)1428 bool FunctionRef::IsNative(const EcmaVM *vm)
1429 {
1430 JSThread *thread = vm->GetJSThread();
1431 JSHandle<JSFunctionBase> func = JSHandle<JSFunctionBase>(thread, JSNApiHelper::ToJSTaggedValue(this));
1432 JSHandle<Method> method = JSHandle<Method>(thread, func->GetMethod());
1433 return method->IsNativeWithCallField();
1434 }
1435
1436 // ----------------------------------- ArrayRef ----------------------------------------
New(const EcmaVM * vm,uint32_t length)1437 Local<ArrayRef> ArrayRef::New(const EcmaVM *vm, uint32_t length)
1438 {
1439 JSThread *thread = vm->GetJSThread();
1440 JSTaggedNumber arrayLen(length);
1441 JSHandle<JSTaggedValue> array = JSArray::ArrayCreate(thread, arrayLen);
1442 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1443 return JSNApiHelper::ToLocal<ArrayRef>(array);
1444 }
1445
Length(const EcmaVM * vm)1446 int32_t ArrayRef::Length([[maybe_unused]] const EcmaVM *vm)
1447 {
1448 return JSArray::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetArrayLength();
1449 }
1450
1451
GetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index)1452 Local<JSValueRef> ArrayRef::GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index)
1453 {
1454 JSThread *thread = vm->GetJSThread();
1455 JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(obj);
1456 JSHandle<JSTaggedValue> result = JSArray::FastGetPropertyByValue(thread, object, index);
1457 return JSNApiHelper::ToLocal<JSValueRef>(result);
1458 }
1459
SetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index,Local<JSValueRef> value)1460 bool ArrayRef::SetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value)
1461 {
1462 JSThread *thread = vm->GetJSThread();
1463 JSHandle<JSTaggedValue> objectHandle = JSNApiHelper::ToJSHandle(obj);
1464 JSHandle<JSTaggedValue> valueHandle = JSNApiHelper::ToJSHandle(value);
1465 return JSArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle);
1466 }
1467 // ---------------------------------- Promise --------------------------------------
New(const EcmaVM * vm)1468 Local<PromiseCapabilityRef> PromiseCapabilityRef::New(const EcmaVM *vm)
1469 {
1470 JSThread *thread = vm->GetJSThread();
1471 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
1472 JSHandle<JSTaggedValue> constructor(globalEnv->GetPromiseFunction());
1473 JSHandle<JSTaggedValue> capability(JSPromise::NewPromiseCapability(thread, constructor));
1474 return JSNApiHelper::ToLocal<PromiseCapabilityRef>(capability);
1475 }
1476
GetPromise(const EcmaVM * vm)1477 Local<PromiseRef> PromiseCapabilityRef::GetPromise(const EcmaVM *vm)
1478 {
1479 JSThread *thread = vm->GetJSThread();
1480 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1481 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, capacity->GetPromise()));
1482 }
1483
Resolve(const EcmaVM * vm,Local<JSValueRef> value)1484 bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value)
1485 {
1486 JSThread *thread = vm->GetJSThread();
1487 const GlobalEnvConstants *constants = thread->GlobalConstants();
1488
1489 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(value);
1490 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1491 JSHandle<JSTaggedValue> resolve(thread, capacity->GetResolve());
1492 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
1493 EcmaRuntimeCallInfo *info =
1494 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1);
1495 RETURN_VALUE_IF_ABRUPT(thread, false);
1496 info->SetCallArg(arg.GetTaggedValue());
1497 JSFunction::Call(info);
1498 RETURN_VALUE_IF_ABRUPT(thread, false);
1499
1500 EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
1501 RETURN_VALUE_IF_ABRUPT(thread, false);
1502 vm->GetHeap()->ClearKeptObjects();
1503 return true;
1504 }
1505
Reject(const EcmaVM * vm,Local<JSValueRef> reason)1506 bool PromiseCapabilityRef::Reject(const EcmaVM *vm, Local<JSValueRef> reason)
1507 {
1508 JSThread *thread = vm->GetJSThread();
1509 const GlobalEnvConstants *constants = thread->GlobalConstants();
1510
1511 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(reason);
1512 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1513 JSHandle<JSTaggedValue> reject(thread, capacity->GetReject());
1514 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
1515
1516 EcmaRuntimeCallInfo *info =
1517 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);
1518 RETURN_VALUE_IF_ABRUPT(thread, false);
1519 info->SetCallArg(arg.GetTaggedValue());
1520 JSFunction::Call(info);
1521 RETURN_VALUE_IF_ABRUPT(thread, false);
1522
1523 EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
1524 RETURN_VALUE_IF_ABRUPT(thread, false);
1525 vm->GetHeap()->ClearKeptObjects();
1526 return true;
1527 }
1528
Catch(const EcmaVM * vm,Local<FunctionRef> handler)1529 Local<PromiseRef> PromiseRef::Catch(const EcmaVM *vm, Local<FunctionRef> handler)
1530 {
1531 JSThread *thread = vm->GetJSThread();
1532 const GlobalEnvConstants *constants = thread->GlobalConstants();
1533
1534 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
1535 JSHandle<JSTaggedValue> catchKey(thread, constants->GetPromiseCatchString());
1536 JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(handler);
1537 JSHandle<JSTaggedValue> undefined = constants->GetHandledUndefined();
1538 EcmaRuntimeCallInfo *info =
1539 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 1);
1540 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1541 info->SetCallArg(reject.GetTaggedValue());
1542 JSTaggedValue result = JSFunction::Invoke(info, catchKey);
1543
1544 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1545 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
1546 }
1547
Finally(const EcmaVM * vm,Local<FunctionRef> handler)1548 Local<PromiseRef> PromiseRef::Finally(const EcmaVM *vm, Local<FunctionRef> handler)
1549 {
1550 JSThread *thread = vm->GetJSThread();
1551 const GlobalEnvConstants *constants = thread->GlobalConstants();
1552
1553 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
1554 JSHandle<JSTaggedValue> finallyKey = constants->GetHandledPromiseFinallyString();
1555 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler);
1556 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
1557 EcmaRuntimeCallInfo *info =
1558 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args
1559 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1560 info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue());
1561 JSTaggedValue result = JSFunction::Invoke(info, finallyKey);
1562
1563 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1564 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
1565 }
1566
Then(const EcmaVM * vm,Local<FunctionRef> handler)1567 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> handler)
1568 {
1569 JSThread *thread = vm->GetJSThread();
1570 const GlobalEnvConstants *constants = thread->GlobalConstants();
1571
1572 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
1573 JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
1574 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler);
1575 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
1576 EcmaRuntimeCallInfo *info =
1577 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args
1578 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1579 info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue());
1580 JSTaggedValue result = JSFunction::Invoke(info, thenKey);
1581
1582 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1583 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
1584 }
1585
Then(const EcmaVM * vm,Local<FunctionRef> onFulfilled,Local<FunctionRef> onRejected)1586 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> onFulfilled, Local<FunctionRef> onRejected)
1587 {
1588 JSThread *thread = vm->GetJSThread();
1589 const GlobalEnvConstants *constants = thread->GlobalConstants();
1590
1591 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
1592 JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
1593 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(onFulfilled);
1594 JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(onRejected);
1595 JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
1596 EcmaRuntimeCallInfo *info =
1597 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2); // 2: two args
1598 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1599 info->SetCallArg(resolver.GetTaggedValue(), reject.GetTaggedValue());
1600 JSTaggedValue result = JSFunction::Invoke(info, thenKey);
1601
1602 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1603 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
1604 }
1605 // ---------------------------------- Promise -------------------------------------
1606
1607 // ---------------------------------- Buffer -----------------------------------
New(const EcmaVM * vm,int32_t length)1608 Local<ArrayBufferRef> ArrayBufferRef::New(const EcmaVM *vm, int32_t length)
1609 {
1610 ObjectFactory *factory = vm->GetFactory();
1611 JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(length);
1612 return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
1613 }
1614
New(const EcmaVM * vm,void * buffer,int32_t length,const Deleter & deleter,void * data)1615 Local<ArrayBufferRef> ArrayBufferRef::New(
1616 const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter, void *data)
1617 {
1618 ObjectFactory *factory = vm->GetFactory();
1619 JSHandle<JSArrayBuffer> arrayBuffer =
1620 factory->NewJSArrayBuffer(buffer, length, reinterpret_cast<ecmascript::DeleteEntryPoint>(deleter), data);
1621 return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
1622 }
1623
ByteLength(const EcmaVM * vm)1624 int32_t ArrayBufferRef::ByteLength([[maybe_unused]] const EcmaVM *vm)
1625 {
1626 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1627 return arrayBuffer->GetArrayBufferByteLength();
1628 }
1629
GetBuffer()1630 void *ArrayBufferRef::GetBuffer()
1631 {
1632 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1633 JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData();
1634 if (!bufferData.IsJSNativePointer()) {
1635 return nullptr;
1636 }
1637 return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
1638 }
1639 // ---------------------------------- Buffer -----------------------------------
1640
1641 // ---------------------------------- DataView -----------------------------------
New(const EcmaVM * vm,Local<ArrayBufferRef> arrayBuffer,uint32_t byteOffset,uint32_t byteLength)1642 Local<DataViewRef> DataViewRef::New(
1643 const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset, uint32_t byteLength)
1644 {
1645 JSThread *thread = vm->GetJSThread();
1646 ObjectFactory *factory = vm->GetFactory();
1647
1648 JSHandle<JSArrayBuffer> buffer(JSNApiHelper::ToJSHandle(arrayBuffer));
1649 JSHandle<JSDataView> dataView = factory->NewJSDataView(buffer, byteOffset, byteLength);
1650 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1651 return JSNApiHelper::ToLocal<DataViewRef>(JSHandle<JSTaggedValue>(dataView));
1652 }
1653
ByteLength()1654 uint32_t DataViewRef::ByteLength()
1655 {
1656 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
1657 return dataView->GetByteLength();
1658 }
1659
ByteOffset()1660 uint32_t DataViewRef::ByteOffset()
1661 {
1662 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
1663 return dataView->GetByteOffset();
1664 }
1665
GetArrayBuffer(const EcmaVM * vm)1666 Local<ArrayBufferRef> DataViewRef::GetArrayBuffer(const EcmaVM *vm)
1667 {
1668 JSThread *thread = vm->GetJSThread();
1669 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
1670 JSHandle<JSTaggedValue> arrayBuffer(thread, dataView->GetViewedArrayBuffer());
1671 return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
1672 }
1673 // ---------------------------------- DataView -----------------------------------
1674
1675 // ---------------------------------- TypedArray -----------------------------------
ByteLength(const EcmaVM * vm)1676 uint32_t TypedArrayRef::ByteLength([[maybe_unused]] const EcmaVM *vm)
1677 {
1678 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
1679 return typedArray->GetByteLength();
1680 }
1681
ByteOffset(const EcmaVM * vm)1682 uint32_t TypedArrayRef::ByteOffset([[maybe_unused]] const EcmaVM *vm)
1683 {
1684 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
1685 return typedArray->GetByteOffset();
1686 }
1687
ArrayLength(const EcmaVM * vm)1688 uint32_t TypedArrayRef::ArrayLength([[maybe_unused]] const EcmaVM *vm)
1689 {
1690 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
1691 return typedArray->GetArrayLength();
1692 }
1693
GetArrayBuffer(const EcmaVM * vm)1694 Local<ArrayBufferRef> TypedArrayRef::GetArrayBuffer(const EcmaVM *vm)
1695 {
1696 JSThread *thread = vm->GetJSThread();
1697 JSHandle<JSTypedArray> typeArray(JSNApiHelper::ToJSHandle(this));
1698 JSHandle<JSTaggedValue> arrayBuffer(thread, JSTypedArray::GetOffHeapBuffer(thread, typeArray));
1699 return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
1700 }
1701
1702 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1703 #define TYPED_ARRAY_NEW(Type) \
1704 Local<Type##Ref> Type##Ref::New( \
1705 const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length) \
1706 { \
1707 JSThread *thread = vm->GetJSThread(); \
1708 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); \
1709 \
1710 JSHandle<JSTaggedValue> func = env->Get##Type##Function(); \
1711 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(buffer)); \
1712 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); \
1713 const int32_t argsLength = 3; \
1714 EcmaRuntimeCallInfo *info = \
1715 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, func, argsLength); \
1716 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); \
1717 info->SetCallArg(arrayBuffer.GetTaggedValue(), JSTaggedValue(byteOffset), JSTaggedValue(length)); \
1718 JSTaggedValue result = JSFunction::Construct(info); \
1719 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); \
1720 JSHandle<JSTaggedValue> resultHandle(thread, result); \
1721 return JSNApiHelper::ToLocal<Type##Ref>(resultHandle); \
1722 }
1723
1724 TYPED_ARRAY_ALL(TYPED_ARRAY_NEW)
1725
1726 #undef TYPED_ARRAY_NEW
1727 // ---------------------------------- TypedArray -----------------------------------
1728
1729 // ---------------------------------- Error ---------------------------------------
1730 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1731 #define EXCEPTION_ERROR_NEW(name, type) \
1732 Local<JSValueRef> Exception::name(const EcmaVM *vm, Local<StringRef> message) \
1733 { \
1734 JSThread *thread = vm->GetJSThread(); \
1735 if (thread->HasPendingException()) { \
1736 thread->ClearException(); \
1737 } \
1738 ObjectFactory *factory = vm->GetFactory(); \
1739 \
1740 JSHandle<EcmaString> messageValue(JSNApiHelper::ToJSHandle(message)); \
1741 JSHandle<JSTaggedValue> result(factory->NewJSError(ErrorType::type, messageValue)); \
1742 return JSNApiHelper::ToLocal<JSValueRef>(result); \
1743 }
1744
EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)1745 EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)
1746
1747 #undef EXCEPTION_ERROR_NEW
1748 // ---------------------------------- Error ---------------------------------------
1749
1750 // ---------------------------------- JSON ------------------------------------------
1751 Local<JSValueRef> JSON::Parse(const EcmaVM *vm, Local<StringRef> string)
1752 {
1753 JSThread *thread = vm->GetJSThread();
1754 auto ecmaStr = EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject());
1755 JSHandle<JSTaggedValue> result;
1756 if (EcmaStringAccessor(ecmaStr).IsUtf8()) {
1757 JsonParser<uint8_t> parser(thread);
1758 result = parser.ParseUtf8(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
1759 } else {
1760 JsonParser<uint16_t> parser(thread);
1761 result = parser.ParseUtf16(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
1762 }
1763 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1764 return JSNApiHelper::ToLocal<JSValueRef>(result);
1765 }
1766
Stringify(const EcmaVM * vm,Local<JSValueRef> json)1767 Local<JSValueRef> JSON::Stringify(const EcmaVM *vm, Local<JSValueRef> json)
1768 {
1769 JSThread *thread = vm->GetJSThread();
1770 auto constants = thread->GlobalConstants();
1771 JsonStringifier stringifier(thread);
1772 JSHandle<JSTaggedValue> str = stringifier.Stringify(
1773 JSNApiHelper::ToJSHandle(json), constants->GetHandledUndefined(), constants->GetHandledUndefined());
1774 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
1775 return JSNApiHelper::ToLocal<JSValueRef>(str);
1776 }
1777
GetOriginalSource(const EcmaVM * vm)1778 Local<StringRef> RegExpRef::GetOriginalSource(const EcmaVM *vm)
1779 {
1780 JSThread *thread = vm->GetJSThread();
1781 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1782 JSTaggedValue source = regExp->GetOriginalSource();
1783 if (!source.IsString()) {
1784 auto constants = thread->GlobalConstants();
1785 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
1786 }
1787 JSHandle<JSTaggedValue> sourceHandle(thread, source);
1788 return JSNApiHelper::ToLocal<StringRef>(sourceHandle);
1789 }
1790
GetOriginalFlags()1791 std::string RegExpRef::GetOriginalFlags()
1792 {
1793 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1794 JSTaggedValue regExpFlags = regExp->GetOriginalFlags();
1795 uint32_t regExpFlagsInt = static_cast<uint32_t>(regExpFlags.GetInt());
1796 std::string strFlags = "";
1797 if (regExpFlagsInt & RegExpParser::FLAG_GLOBAL) {
1798 strFlags += "g";
1799 }
1800 if (regExpFlagsInt & RegExpParser::FLAG_IGNORECASE) {
1801 strFlags += "i";
1802 }
1803 if (regExpFlagsInt & RegExpParser::FLAG_MULTILINE) {
1804 strFlags += "m";
1805 }
1806 if (regExpFlagsInt & RegExpParser::FLAG_DOTALL) {
1807 strFlags += "s";
1808 }
1809 if (regExpFlagsInt & RegExpParser::FLAG_UTF16) {
1810 strFlags += "u";
1811 }
1812 if (regExpFlagsInt & RegExpParser::FLAG_STICKY) {
1813 strFlags += "y";
1814 }
1815 std::sort(strFlags.begin(), strFlags.end());
1816 return strFlags;
1817 }
1818
IsGlobal(const EcmaVM * vm)1819 Local<JSValueRef> RegExpRef::IsGlobal(const EcmaVM *vm)
1820 {
1821 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1822 JSTaggedValue flags = regExp->GetOriginalFlags();
1823 bool result = flags.GetInt() & RegExpParser::FLAG_GLOBAL;
1824 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
1825 return jsValue;
1826 }
1827
IsIgnoreCase(const EcmaVM * vm)1828 Local<JSValueRef> RegExpRef::IsIgnoreCase(const EcmaVM *vm)
1829 {
1830 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1831 JSTaggedValue flags = regExp->GetOriginalFlags();
1832 bool result = flags.GetInt() & RegExpParser::FLAG_IGNORECASE;
1833 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
1834 return jsValue;
1835 }
1836
IsMultiline(const EcmaVM * vm)1837 Local<JSValueRef> RegExpRef::IsMultiline(const EcmaVM *vm)
1838 {
1839 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1840 JSTaggedValue flags = regExp->GetOriginalFlags();
1841 bool result = flags.GetInt() & RegExpParser::FLAG_MULTILINE;
1842 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
1843 return jsValue;
1844 }
1845
IsDotAll(const EcmaVM * vm)1846 Local<JSValueRef> RegExpRef::IsDotAll(const EcmaVM *vm)
1847 {
1848 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1849 JSTaggedValue flags = regExp->GetOriginalFlags();
1850 bool result = flags.GetInt() & RegExpParser::FLAG_DOTALL;
1851 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
1852 return jsValue;
1853 }
1854
IsUtf16(const EcmaVM * vm)1855 Local<JSValueRef> RegExpRef::IsUtf16(const EcmaVM *vm)
1856 {
1857 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1858 JSTaggedValue flags = regExp->GetOriginalFlags();
1859 bool result = flags.GetInt() & RegExpParser::FLAG_UTF16;
1860 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
1861 return jsValue;
1862 }
1863
IsStick(const EcmaVM * vm)1864 Local<JSValueRef> RegExpRef::IsStick(const EcmaVM *vm)
1865 {
1866 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1867 JSTaggedValue flags = regExp->GetOriginalFlags();
1868 bool result = flags.GetInt() & RegExpParser::FLAG_STICKY;
1869 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
1870 return jsValue;
1871 }
1872
New(const EcmaVM * vm,double time)1873 Local<DateRef> DateRef::New(const EcmaVM *vm, double time)
1874 {
1875 JSThread *thread = vm->GetJSThread();
1876 ObjectFactory *factory = vm->GetFactory();
1877 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
1878 JSHandle<JSFunction> dateFunction(globalEnv->GetDateFunction());
1879 JSHandle<JSDate> dateObject(factory->NewJSObjectByConstructor(dateFunction));
1880 dateObject->SetTimeValue(thread, JSTaggedValue(time));
1881 return JSNApiHelper::ToLocal<DateRef>(JSHandle<JSTaggedValue>(dateObject));
1882 }
1883
ToString(const EcmaVM * vm)1884 Local<StringRef> DateRef::ToString(const EcmaVM *vm)
1885 {
1886 JSThread *thread = vm->GetJSThread();
1887 JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
1888 JSTaggedValue dateStr = date->ToString(thread);
1889 if (!dateStr.IsString()) {
1890 auto constants = thread->GlobalConstants();
1891 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
1892 }
1893 JSHandle<JSTaggedValue> dateStrHandle(thread, dateStr);
1894 return JSNApiHelper::ToLocal<StringRef>(dateStrHandle);
1895 }
1896
GetTime()1897 double DateRef::GetTime()
1898 {
1899 JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
1900 if (!date->IsDate()) {
1901 LOG_ECMA(ERROR) << "Not a Date Object";
1902 }
1903 return date->GetTime().GetDouble();
1904 }
1905
Get(const EcmaVM * vm,Local<JSValueRef> key)1906 Local<JSValueRef> MapRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
1907 {
1908 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
1909 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(),
1910 map->Get(JSNApiHelper::ToJSTaggedValue(*key))));
1911 }
1912
Set(const EcmaVM * vm,Local<JSValueRef> key,Local<JSValueRef> value)1913 void MapRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
1914 {
1915 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
1916 JSMap::Set(vm->GetJSThread(), map, JSNApiHelper::ToJSHandle(key), JSNApiHelper::ToJSHandle(value));
1917 }
1918
New(const EcmaVM * vm)1919 Local<MapRef> MapRef::New(const EcmaVM *vm)
1920 {
1921 JSThread *thread = vm->GetJSThread();
1922 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1923 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1924 JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
1925 JSHandle<JSMap> map =
1926 JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
1927 JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
1928 map->SetLinkedMap(thread, hashMap);
1929 JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(map);
1930 return JSNApiHelper::ToLocal<MapRef>(mapTag);
1931 }
1932
GetSize()1933 int32_t MapRef::GetSize()
1934 {
1935 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
1936 return map->GetSize();
1937 }
1938
GetTotalElements()1939 int32_t MapRef::GetTotalElements()
1940 {
1941 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
1942 return map->GetSize() + LinkedHashMap::Cast(map->GetLinkedMap().GetTaggedObject())->NumberOfDeletedElements();
1943 }
1944
GetKey(const EcmaVM * vm,int entry)1945 Local<JSValueRef> MapRef::GetKey(const EcmaVM *vm, int entry)
1946 {
1947 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
1948 JSThread *thread = vm->GetJSThread();
1949 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetKey(entry)));
1950 }
1951
GetValue(const EcmaVM * vm,int entry)1952 Local<JSValueRef> MapRef::GetValue(const EcmaVM *vm, int entry)
1953 {
1954 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
1955 JSThread *thread = vm->GetJSThread();
1956 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetValue(entry)));
1957 }
1958
GetSize()1959 int32_t SetRef::GetSize()
1960 {
1961 JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
1962 return set->GetSize();
1963 }
1964
GetTotalElements()1965 int32_t SetRef::GetTotalElements()
1966 {
1967 JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
1968 return set->GetSize() + LinkedHashSet::Cast(set->GetLinkedSet().GetTaggedObject())->NumberOfDeletedElements();
1969 }
1970
GetValue(const EcmaVM * vm,int entry)1971 Local<JSValueRef> SetRef::GetValue(const EcmaVM *vm, int entry)
1972 {
1973 JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
1974 JSThread *thread = vm->GetJSThread();
1975 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, set->GetValue(entry)));
1976 }
1977
GetIndex()1978 int32_t MapIteratorRef::GetIndex()
1979 {
1980 JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
1981 return jsMapIter->GetNextIndex();
1982 }
1983
GetKind(const EcmaVM * vm)1984 Local<JSValueRef> MapIteratorRef::GetKind(const EcmaVM *vm)
1985 {
1986 JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
1987 IterationKind iterKind = jsMapIter->GetIterationKind();
1988 Local<JSValueRef> result;
1989 switch (iterKind) {
1990 case IterationKind::KEY:
1991 result = StringRef::NewFromUtf8(vm, "keys");
1992 break;
1993 case IterationKind::VALUE:
1994 result = StringRef::NewFromUtf8(vm, "values");
1995 break;
1996 case IterationKind::KEY_AND_VALUE:
1997 result = StringRef::NewFromUtf8(vm, "entries");
1998 break;
1999 default:
2000 break;
2001 }
2002 return result;
2003 }
2004
GetIndex()2005 int32_t SetIteratorRef::GetIndex()
2006 {
2007 JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
2008 return jsSetIter->GetNextIndex();
2009 }
2010
GetKind(const EcmaVM * vm)2011 Local<JSValueRef> SetIteratorRef::GetKind(const EcmaVM *vm)
2012 {
2013 JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
2014 IterationKind iterKind = jsSetIter->GetIterationKind();
2015 Local<JSValueRef> result;
2016 switch (iterKind) {
2017 case IterationKind::KEY:
2018 result = StringRef::NewFromUtf8(vm, "keys");
2019 break;
2020 case IterationKind::VALUE:
2021 result = StringRef::NewFromUtf8(vm, "values");
2022 break;
2023 case IterationKind::KEY_AND_VALUE:
2024 result = StringRef::NewFromUtf8(vm, "entries");
2025 break;
2026 default:
2027 break;
2028 }
2029 return result;
2030 }
2031
IsGenerator()2032 bool GeneratorFunctionRef::IsGenerator()
2033 {
2034 return IsGeneratorFunction();
2035 }
2036
GetGeneratorState(const EcmaVM * vm)2037 Local<JSValueRef> GeneratorObjectRef::GetGeneratorState(const EcmaVM *vm)
2038 {
2039 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this));
2040 if (jsGenerator->GetGeneratorState() == JSGeneratorState::COMPLETED) {
2041 return StringRef::NewFromUtf8(vm, "closed");
2042 }
2043 return StringRef::NewFromUtf8(vm, "suspended");
2044 }
2045
GetGeneratorFunction(const EcmaVM * vm)2046 Local<JSValueRef> GeneratorObjectRef::GetGeneratorFunction(const EcmaVM *vm)
2047 {
2048 JSThread *thread = vm->GetJSThread();
2049 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this));
2050 JSHandle<GeneratorContext> generatorContext(thread, jsGenerator->GetGeneratorContext());
2051 JSTaggedValue jsTagValue = generatorContext->GetMethod();
2052 return JSNApiHelper::ToLocal<GeneratorFunctionRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
2053 }
2054
GetGeneratorReceiver(const EcmaVM * vm)2055 Local<JSValueRef> GeneratorObjectRef::GetGeneratorReceiver(const EcmaVM *vm)
2056 {
2057 JSThread *thread = vm->GetJSThread();
2058 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this));
2059 JSHandle<GeneratorContext> generatorContext(thread, jsGenerator->GetGeneratorContext());
2060 JSTaggedValue jsTagValue = generatorContext->GetAcc();
2061 return JSNApiHelper::ToLocal<GeneratorObjectRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
2062 }
2063
GetCompareFunction(const EcmaVM * vm)2064 Local<JSValueRef> CollatorRef::GetCompareFunction(const EcmaVM *vm)
2065 {
2066 JSThread *thread = vm->GetJSThread();
2067 JSHandle<JSCollator> jsCollator(JSNApiHelper::ToJSHandle(this));
2068 JSTaggedValue jsTagValue = jsCollator->GetBoundCompare();
2069 return JSNApiHelper::ToLocal<CollatorRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
2070 }
2071
GetFormatFunction(const EcmaVM * vm)2072 Local<JSValueRef> DataTimeFormatRef::GetFormatFunction(const EcmaVM *vm)
2073 {
2074 JSThread *thread = vm->GetJSThread();
2075 JSHandle<JSDateTimeFormat> jsDateTimeFormat(JSNApiHelper::ToJSHandle(this));
2076 JSTaggedValue jsTagValue = jsDateTimeFormat->GetBoundFormat();
2077 return JSNApiHelper::ToLocal<DataTimeFormatRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
2078 }
2079
GetFormatFunction(const EcmaVM * vm)2080 Local<JSValueRef> NumberFormatRef::GetFormatFunction(const EcmaVM *vm)
2081 {
2082 JSThread *thread = vm->GetJSThread();
2083 JSHandle<JSNumberFormat> jsNumberFormat(JSNApiHelper::ToJSHandle(this));
2084 JSTaggedValue jsTagValue = jsNumberFormat->GetBoundFormat();
2085 return JSNApiHelper::ToLocal<NumberFormatRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
2086 }
2087
2088 // ----------------------------------- FunctionCallback ---------------------------------
RegisterCallback(ecmascript::EcmaRuntimeCallInfo * ecmaRuntimeCallInfo)2089 JSTaggedValue Callback::RegisterCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
2090 {
2091 // Constructor
2092 JSThread *thread = ecmaRuntimeCallInfo->GetThread();
2093 JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(ecmaRuntimeCallInfo);
2094 if (!constructor->IsJSFunction()) {
2095 return JSTaggedValue::False();
2096 }
2097 [[maybe_unused]] LocalScope scope(thread->GetEcmaVM());
2098 JSHandle<JSFunction> function(constructor);
2099 JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo();
2100 if (!extraInfoValue.IsJSNativePointer()) {
2101 return JSTaggedValue::False();
2102 }
2103 JSHandle<JSNativePointer> extraInfo(thread, extraInfoValue);
2104 // callBack
2105 FunctionCallback nativeFunc = reinterpret_cast<FunctionCallback>(extraInfo->GetExternalPointer());
2106
2107 JsiRuntimeCallInfo jsiRuntimeCallInfo(ecmaRuntimeCallInfo, extraInfo->GetData());
2108 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
2109 if (thread->GetCallNapiGetStack() && function->IsCallNapi()) {
2110 thread->GetEcmaVM()->GetProfiler()->GetStackCallNapi(thread, true);
2111 }
2112 #endif
2113 Local<JSValueRef> result = nativeFunc(&jsiRuntimeCallInfo);
2114 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
2115 if (thread->GetCallNapiGetStack() && function->IsCallNapi()) {
2116 thread->GetEcmaVM()->GetProfiler()->GetStackCallNapi(thread, false);
2117 }
2118 #endif
2119 return JSNApiHelper::ToJSHandle(result).GetTaggedValue();
2120 }
2121
2122 // ------------------------------------- JSExecutionScope ------------------------------
JSExecutionScope(const EcmaVM * vm)2123 JSExecutionScope::JSExecutionScope(const EcmaVM *vm)
2124 {
2125 (void)vm;
2126 }
2127
~JSExecutionScope()2128 JSExecutionScope::~JSExecutionScope()
2129 {
2130 last_current_thread_ = nullptr;
2131 is_revert_ = false;
2132 }
2133
2134 // ----------------------------------- JSValueRef --------------------------------------
Undefined(const EcmaVM * vm)2135 Local<PrimitiveRef> JSValueRef::Undefined(const EcmaVM *vm)
2136 {
2137 JSThread *thread = vm->GetJSThread();
2138 const GlobalEnvConstants *constants = thread->GlobalConstants();
2139 return JSNApiHelper::ToLocal<PrimitiveRef>(constants->GetHandledUndefined());
2140 }
2141
Null(const EcmaVM * vm)2142 Local<PrimitiveRef> JSValueRef::Null(const EcmaVM *vm)
2143 {
2144 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Null()));
2145 }
2146
True(const EcmaVM * vm)2147 Local<PrimitiveRef> JSValueRef::True(const EcmaVM *vm)
2148 {
2149 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::True()));
2150 }
2151
False(const EcmaVM * vm)2152 Local<PrimitiveRef> JSValueRef::False(const EcmaVM *vm)
2153 {
2154 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::False()));
2155 }
2156
ToObject(const EcmaVM * vm)2157 Local<ObjectRef> JSValueRef::ToObject(const EcmaVM *vm)
2158 {
2159 JSThread *thread = vm->GetJSThread();
2160 if (IsUndefined() || IsNull()) {
2161 return Undefined(vm);
2162 }
2163 JSHandle<JSTaggedValue> obj(JSTaggedValue::ToObject(thread, JSNApiHelper::ToJSHandle(this)));
2164 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2165 return JSNApiHelper::ToLocal<ObjectRef>(obj);
2166 }
2167
ToString(const EcmaVM * vm)2168 Local<StringRef> JSValueRef::ToString(const EcmaVM *vm)
2169 {
2170 JSThread *thread = vm->GetJSThread();
2171 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2172 if (!obj->IsString()) {
2173 obj = JSHandle<JSTaggedValue>(JSTaggedValue::ToString(thread, obj));
2174 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2175 }
2176 return JSNApiHelper::ToLocal<StringRef>(obj);
2177 }
2178
ToNativePointer(const EcmaVM * vm)2179 Local<NativePointerRef> JSValueRef::ToNativePointer(const EcmaVM *vm)
2180 {
2181 JSThread *thread = vm->GetJSThread();
2182 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2183 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2184 return JSNApiHelper::ToLocal<NativePointerRef>(obj);
2185 }
2186
BooleaValue()2187 bool JSValueRef::BooleaValue()
2188 {
2189 return JSNApiHelper::ToJSTaggedValue(this).ToBoolean();
2190 }
2191
IntegerValue(const EcmaVM * vm)2192 int64_t JSValueRef::IntegerValue(const EcmaVM *vm)
2193 {
2194 JSThread *thread = vm->GetJSThread();
2195 JSHandle<JSTaggedValue> tagged = JSNApiHelper::ToJSHandle(this);
2196 if (tagged->IsNumber()) {
2197 if (!NumberHelper::IsFinite(tagged.GetTaggedValue()) || NumberHelper::IsNaN(tagged.GetTaggedValue())) {
2198 return 0;
2199 } else {
2200 return NumberHelper::DoubleToInt64(tagged->GetNumber());
2201 }
2202 }
2203 JSTaggedNumber number = JSTaggedValue::ToInteger(thread, tagged);
2204 RETURN_VALUE_IF_ABRUPT(thread, 0);
2205 return NumberHelper::DoubleToInt64(number.GetNumber());
2206 }
2207
Uint32Value(const EcmaVM * vm)2208 uint32_t JSValueRef::Uint32Value(const EcmaVM *vm)
2209 {
2210 JSThread *thread = vm->GetJSThread();
2211 uint32_t number = JSTaggedValue::ToUint32(thread, JSNApiHelper::ToJSHandle(this));
2212 RETURN_VALUE_IF_ABRUPT(thread, 0);
2213 return number;
2214 }
2215
Int32Value(const EcmaVM * vm)2216 int32_t JSValueRef::Int32Value(const EcmaVM *vm)
2217 {
2218 JSThread *thread = vm->GetJSThread();
2219 int32_t number = JSTaggedValue::ToInt32(thread, JSNApiHelper::ToJSHandle(this));
2220 RETURN_VALUE_IF_ABRUPT(thread, 0);
2221 return number;
2222 }
2223
ToBoolean(const EcmaVM * vm)2224 Local<BooleanRef> JSValueRef::ToBoolean(const EcmaVM *vm)
2225 {
2226 JSThread *thread = vm->GetJSThread();
2227 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2228 JSHandle<JSTaggedValue> booleanObj = JSHandle<JSTaggedValue>(thread, JSTaggedValue(obj->ToBoolean()));
2229 return JSNApiHelper::ToLocal<BooleanRef>(booleanObj);
2230 }
2231
ToNumber(const EcmaVM * vm)2232 Local<NumberRef> JSValueRef::ToNumber(const EcmaVM *vm)
2233 {
2234 JSThread *thread = vm->GetJSThread();
2235 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2236 JSHandle<JSTaggedValue> number(thread, JSTaggedValue::ToNumber(thread, obj));
2237 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
2238 return JSNApiHelper::ToLocal<NumberRef>(number);
2239 }
2240
IsStrictEquals(const EcmaVM * vm,Local<JSValueRef> value)2241 bool JSValueRef::IsStrictEquals(const EcmaVM *vm, Local<JSValueRef> value)
2242 {
2243 JSThread *thread = vm->GetJSThread();
2244 JSHandle<JSTaggedValue> xValue = JSNApiHelper::ToJSHandle(this);
2245 JSHandle<JSTaggedValue> yValue = JSNApiHelper::ToJSHandle(value);
2246 return JSTaggedValue::StrictEqual(thread, xValue, yValue);
2247 }
2248
Typeof(const EcmaVM * vm)2249 Local<StringRef> JSValueRef::Typeof(const EcmaVM *vm)
2250 {
2251 JSThread *thread = vm->GetJSThread();
2252 JSTaggedValue value = FastRuntimeStub::FastTypeOf(thread, JSNApiHelper::ToJSTaggedValue(this));
2253 return JSNApiHelper::ToLocal<StringRef>(JSHandle<JSTaggedValue>(thread, value));
2254 }
2255
InstanceOf(const EcmaVM * vm,Local<JSValueRef> value)2256 bool JSValueRef::InstanceOf(const EcmaVM *vm, Local<JSValueRef> value)
2257 {
2258 JSThread *thread = vm->GetJSThread();
2259 JSHandle<JSTaggedValue> origin = JSNApiHelper::ToJSHandle(this);
2260 JSHandle<JSTaggedValue> target = JSNApiHelper::ToJSHandle(value);
2261 bool result = JSObject::InstanceOf(thread, origin, target);
2262 RETURN_VALUE_IF_ABRUPT(thread, false);
2263 return result;
2264 }
2265
IsUndefined()2266 bool JSValueRef::IsUndefined()
2267 {
2268 return JSNApiHelper::ToJSTaggedValue(this).IsUndefined();
2269 }
2270
IsNull()2271 bool JSValueRef::IsNull()
2272 {
2273 return JSNApiHelper::ToJSTaggedValue(this).IsNull();
2274 }
2275
IsHole()2276 bool JSValueRef::IsHole()
2277 {
2278 return JSNApiHelper::ToJSTaggedValue(this).IsHole();
2279 }
2280
IsTrue()2281 bool JSValueRef::IsTrue()
2282 {
2283 return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
2284 }
2285
IsFalse()2286 bool JSValueRef::IsFalse()
2287 {
2288 return JSNApiHelper::ToJSTaggedValue(this).IsFalse();
2289 }
2290
IsNumber()2291 bool JSValueRef::IsNumber()
2292 {
2293 return JSNApiHelper::ToJSTaggedValue(this).IsNumber();
2294 }
2295
IsBigInt()2296 bool JSValueRef::IsBigInt()
2297 {
2298 return JSNApiHelper::ToJSTaggedValue(this).IsBigInt();
2299 }
2300
IsInt()2301 bool JSValueRef::IsInt()
2302 {
2303 return JSNApiHelper::ToJSTaggedValue(this).IsInt();
2304 }
2305
WithinInt32()2306 bool JSValueRef::WithinInt32()
2307 {
2308 return JSNApiHelper::ToJSTaggedValue(this).WithinInt32();
2309 }
2310
IsBoolean()2311 bool JSValueRef::IsBoolean()
2312 {
2313 return JSNApiHelper::ToJSTaggedValue(this).IsBoolean();
2314 }
2315
IsString()2316 bool JSValueRef::IsString()
2317 {
2318 return JSNApiHelper::ToJSTaggedValue(this).IsString();
2319 }
2320
IsSymbol()2321 bool JSValueRef::IsSymbol()
2322 {
2323 return JSNApiHelper::ToJSTaggedValue(this).IsSymbol();
2324 }
2325
IsObject()2326 bool JSValueRef::IsObject()
2327 {
2328 return JSNApiHelper::ToJSTaggedValue(this).IsECMAObject();
2329 }
2330
IsArray(const EcmaVM * vm)2331 bool JSValueRef::IsArray(const EcmaVM *vm)
2332 {
2333 JSThread *thread = vm->GetJSThread();
2334 return JSNApiHelper::ToJSTaggedValue(this).IsArray(thread);
2335 }
2336
IsConstructor()2337 bool JSValueRef::IsConstructor()
2338 {
2339 JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
2340 return value.IsHeapObject() && value.IsConstructor();
2341 }
2342
IsFunction()2343 bool JSValueRef::IsFunction()
2344 {
2345 JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
2346 return value.IsHeapObject() && value.IsCallable();
2347 }
2348
IsProxy()2349 bool JSValueRef::IsProxy()
2350 {
2351 return JSNApiHelper::ToJSTaggedValue(this).IsJSProxy();
2352 }
2353
IsPromise()2354 bool JSValueRef::IsPromise()
2355 {
2356 return JSNApiHelper::ToJSTaggedValue(this).IsJSPromise();
2357 }
2358
IsDataView()2359 bool JSValueRef::IsDataView()
2360 {
2361 return JSNApiHelper::ToJSTaggedValue(this).IsDataView();
2362 }
2363
IsTypedArray()2364 bool JSValueRef::IsTypedArray()
2365 {
2366 return JSNApiHelper::ToJSTaggedValue(this).IsTypedArray();
2367 }
2368
IsNativePointer()2369 bool JSValueRef::IsNativePointer()
2370 {
2371 return JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer();
2372 }
2373
IsDate()2374 bool JSValueRef::IsDate()
2375 {
2376 return JSNApiHelper::ToJSTaggedValue(this).IsDate();
2377 }
2378
IsError()2379 bool JSValueRef::IsError()
2380 {
2381 return JSNApiHelper::ToJSTaggedValue(this).IsJSError();
2382 }
2383
IsMap()2384 bool JSValueRef::IsMap()
2385 {
2386 return JSNApiHelper::ToJSTaggedValue(this).IsJSMap();
2387 }
2388
IsSet()2389 bool JSValueRef::IsSet()
2390 {
2391 return JSNApiHelper::ToJSTaggedValue(this).IsJSSet();
2392 }
2393
IsWeakRef()2394 bool JSValueRef::IsWeakRef()
2395 {
2396 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakRef();
2397 }
2398
IsWeakMap()2399 bool JSValueRef::IsWeakMap()
2400 {
2401 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakMap();
2402 }
2403
IsWeakSet()2404 bool JSValueRef::IsWeakSet()
2405 {
2406 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakSet();
2407 }
2408
IsRegExp()2409 bool JSValueRef::IsRegExp()
2410 {
2411 return JSNApiHelper::ToJSTaggedValue(this).IsJSRegExp();
2412 }
2413
IsArrayIterator()2414 bool JSValueRef::IsArrayIterator()
2415 {
2416 return JSNApiHelper::ToJSTaggedValue(this).IsJSArrayIterator();
2417 }
2418
IsStringIterator()2419 bool JSValueRef::IsStringIterator()
2420 {
2421 return JSNApiHelper::ToJSTaggedValue(this).IsStringIterator();
2422 }
2423
IsSetIterator()2424 bool JSValueRef::IsSetIterator()
2425 {
2426 return JSNApiHelper::ToJSTaggedValue(this).IsJSSetIterator();
2427 }
2428
IsMapIterator()2429 bool JSValueRef::IsMapIterator()
2430 {
2431 return JSNApiHelper::ToJSTaggedValue(this).IsJSMapIterator();
2432 }
2433
IsArrayBuffer()2434 bool JSValueRef::IsArrayBuffer()
2435 {
2436 return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer();
2437 }
2438
IsUint8Array()2439 bool JSValueRef::IsUint8Array()
2440 {
2441 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8Array();
2442 }
2443
IsInt8Array()2444 bool JSValueRef::IsInt8Array()
2445 {
2446 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt8Array();
2447 }
2448
IsUint8ClampedArray()2449 bool JSValueRef::IsUint8ClampedArray()
2450 {
2451 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8ClampedArray();
2452 }
2453
IsInt16Array()2454 bool JSValueRef::IsInt16Array()
2455 {
2456 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt16Array();
2457 }
2458
IsUint16Array()2459 bool JSValueRef::IsUint16Array()
2460 {
2461 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint16Array();
2462 }
2463
IsInt32Array()2464 bool JSValueRef::IsInt32Array()
2465 {
2466 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt32Array();
2467 }
2468
IsUint32Array()2469 bool JSValueRef::IsUint32Array()
2470 {
2471 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint32Array();
2472 }
2473
IsFloat32Array()2474 bool JSValueRef::IsFloat32Array()
2475 {
2476 return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat32Array();
2477 }
2478
IsFloat64Array()2479 bool JSValueRef::IsFloat64Array()
2480 {
2481 return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat64Array();
2482 }
2483
IsBigInt64Array()2484 bool JSValueRef::IsBigInt64Array()
2485 {
2486 return JSNApiHelper::ToJSTaggedValue(this).IsJSBigInt64Array();
2487 }
2488
IsBigUint64Array()2489 bool JSValueRef::IsBigUint64Array()
2490 {
2491 return JSNApiHelper::ToJSTaggedValue(this).IsJSBigUint64Array();
2492 }
2493
IsJSPrimitiveRef()2494 bool JSValueRef::IsJSPrimitiveRef()
2495 {
2496 return JSNApiHelper::ToJSTaggedValue(this).IsJSPrimitiveRef();
2497 }
2498
IsJSPrimitiveNumber()2499 bool JSValueRef::IsJSPrimitiveNumber()
2500 {
2501 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2502 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsNumber();
2503 }
2504
IsJSPrimitiveInt()2505 bool JSValueRef::IsJSPrimitiveInt()
2506 {
2507 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2508 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsInt();
2509 }
2510
IsJSPrimitiveBoolean()2511 bool JSValueRef::IsJSPrimitiveBoolean()
2512 {
2513 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2514 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsBoolean();
2515 }
2516
IsJSPrimitiveString()2517 bool JSValueRef::IsJSPrimitiveString()
2518 {
2519 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2520 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsString();
2521 }
2522
IsJSPrimitiveSymbol()2523 bool JSValueRef::IsJSPrimitiveSymbol()
2524 {
2525 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2526 return JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsSymbol();
2527 }
2528
IsGeneratorObject()2529 bool JSValueRef::IsGeneratorObject()
2530 {
2531 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2532 bool rst = obj->IsGeneratorObject();
2533 return rst;
2534 }
2535
IsModuleNamespaceObject()2536 bool JSValueRef::IsModuleNamespaceObject()
2537 {
2538 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2539 bool rst = obj->IsModuleNamespace();
2540 return rst;
2541 }
2542
IsSharedArrayBuffer()2543 bool JSValueRef::IsSharedArrayBuffer()
2544 {
2545 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2546 bool rst = obj->IsSharedArrayBuffer();
2547 return rst;
2548 }
2549
IsJSLocale()2550 bool JSValueRef::IsJSLocale()
2551 {
2552 return JSNApiHelper::ToJSTaggedValue(this).IsJSLocale();
2553 }
2554
IsJSDateTimeFormat()2555 bool JSValueRef::IsJSDateTimeFormat()
2556 {
2557 return JSNApiHelper::ToJSTaggedValue(this).IsJSDateTimeFormat();
2558 }
2559
IsJSRelativeTimeFormat()2560 bool JSValueRef::IsJSRelativeTimeFormat()
2561 {
2562 return JSNApiHelper::ToJSTaggedValue(this).IsJSRelativeTimeFormat();
2563 }
2564
IsJSIntl()2565 bool JSValueRef::IsJSIntl()
2566 {
2567 return JSNApiHelper::ToJSTaggedValue(this).IsJSIntl();
2568 }
2569
IsJSNumberFormat()2570 bool JSValueRef::IsJSNumberFormat()
2571 {
2572 return JSNApiHelper::ToJSTaggedValue(this).IsJSNumberFormat();
2573 }
2574
IsJSCollator()2575 bool JSValueRef::IsJSCollator()
2576 {
2577 return JSNApiHelper::ToJSTaggedValue(this).IsJSCollator();
2578 }
2579
IsJSPluralRules()2580 bool JSValueRef::IsJSPluralRules()
2581 {
2582 return JSNApiHelper::ToJSTaggedValue(this).IsJSPluralRules();
2583 }
2584
IsJSListFormat()2585 bool JSValueRef::IsJSListFormat()
2586 {
2587 return JSNApiHelper::ToJSTaggedValue(this).IsJSListFormat();
2588 }
2589
IsAsyncGeneratorObject()2590 bool JSValueRef::IsAsyncGeneratorObject()
2591 {
2592 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2593 return obj->IsAsyncGeneratorObject();
2594 }
2595
IsAsyncFunction()2596 bool JSValueRef::IsAsyncFunction()
2597 {
2598 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2599 bool rst = obj->IsJSAsyncFunction();
2600 return rst;
2601 }
2602
IsArgumentsObject()2603 bool JSValueRef::IsArgumentsObject()
2604 {
2605 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2606 bool rst = obj->IsArguments();
2607 return rst;
2608 }
2609
IsGeneratorFunction()2610 bool JSValueRef::IsGeneratorFunction()
2611 {
2612 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2613 bool rst = obj->IsGeneratorFunction();
2614 return rst;
2615 }
2616
IsAsyncGeneratorFunction()2617 bool JSValueRef::IsAsyncGeneratorFunction()
2618 {
2619 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2620 return obj->IsAsyncGeneratorFunction();
2621 }
2622
2623 // ------------------------------------ JsiRuntimeCallInfo -----------------------------------------------
JsiRuntimeCallInfo(ecmascript::EcmaRuntimeCallInfo * ecmaInfo,void * data)2624 JsiRuntimeCallInfo::JsiRuntimeCallInfo(ecmascript::EcmaRuntimeCallInfo* ecmaInfo, void* data)
2625 : thread_(ecmaInfo->GetThread()), numArgs_(ecmaInfo->GetArgsNumber())
2626 {
2627 stackArgs_ = ecmaInfo->GetArgs();
2628 data_ = data;
2629 }
2630
GetVM() const2631 EcmaVM *JsiRuntimeCallInfo::GetVM() const
2632 {
2633 return thread_->GetEcmaVM();
2634 }
2635
2636 // ---------------------------------------Hot Patch----------------------------------------------------
LoadPatch(EcmaVM * vm,const std::string & patchFileName,const std::string & baseFileName)2637 bool JSNApi::LoadPatch(EcmaVM *vm, const std::string &patchFileName, const std::string &baseFileName)
2638 {
2639 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2640 JSThread *thread = vm->GetJSThread();
2641 return quickFixManager->LoadPatch(thread, patchFileName, baseFileName);
2642 }
2643
LoadPatch(EcmaVM * vm,const std::string & patchFileName,const void * patchBuffer,size_t patchSize,const std::string & baseFileName)2644 bool JSNApi::LoadPatch(EcmaVM *vm, const std::string &patchFileName, const void *patchBuffer, size_t patchSize,
2645 const std::string &baseFileName)
2646 {
2647 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2648 JSThread *thread = vm->GetJSThread();
2649 return quickFixManager->LoadPatch(thread, patchFileName, patchBuffer, patchSize, baseFileName);
2650 }
2651
UnloadPatch(EcmaVM * vm,const std::string & patchFileName)2652 bool JSNApi::UnloadPatch(EcmaVM *vm, const std::string &patchFileName)
2653 {
2654 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2655 JSThread *thread = vm->GetJSThread();
2656 return quickFixManager->UnloadPatch(thread, patchFileName);
2657 }
2658
2659 /*
2660 * check whether the exception is caused by quickfix methods.
2661 */
IsQuickFixCausedException(EcmaVM * vm,Local<ObjectRef> exception,const std::string & patchFileName)2662 bool JSNApi::IsQuickFixCausedException(EcmaVM *vm, Local<ObjectRef> exception, const std::string &patchFileName)
2663 {
2664 if (exception.IsEmpty()) {
2665 return false;
2666 }
2667 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2668 JSThread *thread = vm->GetJSThread();
2669 JSHandle<JSTaggedValue> exceptionInfo = JSNApiHelper::ToJSHandle(exception);
2670 return quickFixManager->IsQuickFixCausedException(thread, exceptionInfo, patchFileName);
2671 }
2672
2673 /*
2674 * register quickfix query function.
2675 */
RegisterQuickFixQueryFunc(EcmaVM * vm,QuickFixQueryCallBack callBack)2676 void JSNApi::RegisterQuickFixQueryFunc(EcmaVM *vm, QuickFixQueryCallBack callBack)
2677 {
2678 ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
2679 quickFixManager->RegisterQuickFixQueryFunc(callBack);
2680 }
2681
IsBundle(EcmaVM * vm)2682 bool JSNApi::IsBundle(EcmaVM *vm)
2683 {
2684 return vm->IsBundlePack();
2685 }
2686
SetBundle(EcmaVM * vm,bool value)2687 void JSNApi::SetBundle(EcmaVM *vm, bool value)
2688 {
2689 vm->SetIsBundlePack(value);
2690 }
2691
2692 // note: The function SetAssetPath is a generic interface for previewing and physical machines.
SetAssetPath(EcmaVM * vm,const std::string & assetPath)2693 void JSNApi::SetAssetPath(EcmaVM *vm, const std::string &assetPath)
2694 {
2695 ecmascript::CString path = assetPath.c_str();
2696 vm->SetAssetPath(path);
2697 }
2698
GetAssetPath(EcmaVM * vm)2699 std::string JSNApi::GetAssetPath(EcmaVM *vm)
2700 {
2701 return vm->GetAssetPath().c_str();
2702 }
2703
SetBundleName(EcmaVM * vm,std::string bundleName)2704 void JSNApi::SetBundleName(EcmaVM *vm, std::string bundleName)
2705 {
2706 ecmascript::CString name = bundleName.c_str();
2707 vm->SetBundleName(name);
2708 }
2709
GetBundleName(EcmaVM * vm)2710 std::string JSNApi::GetBundleName(EcmaVM *vm)
2711 {
2712 return vm->GetBundleName().c_str();
2713 }
2714
SetModuleName(EcmaVM * vm,std::string moduleName)2715 void JSNApi::SetModuleName(EcmaVM *vm, std::string moduleName)
2716 {
2717 ecmascript::CString name = moduleName.c_str();
2718 vm->SetModuleName(name);
2719 }
2720
GetModuleName(EcmaVM * vm)2721 std::string JSNApi::GetModuleName(EcmaVM *vm)
2722 {
2723 return vm->GetModuleName().c_str();
2724 }
2725
SetLoop(EcmaVM * vm,void * loop)2726 void JSNApi::SetLoop(EcmaVM *vm, void *loop)
2727 {
2728 vm->SetLoop(loop);
2729 }
2730
InitForConcurrentThread(EcmaVM * vm,ConcurrentCallback cb,void * data)2731 bool JSNApi::InitForConcurrentThread(EcmaVM *vm, ConcurrentCallback cb, void *data)
2732 {
2733 vm->SetConcurrentCallback(cb, data);
2734
2735 return true;
2736 }
2737
InitForConcurrentFunction(EcmaVM * vm,Local<JSValueRef> function)2738 bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local<JSValueRef> function)
2739 {
2740 [[maybe_unused]] LocalScope scope(vm);
2741 JSHandle<JSTaggedValue> funcVal = JSNApiHelper::ToJSHandle(function);
2742 JSHandle<JSFunction> transFunc = JSHandle<JSFunction>::Cast(funcVal);
2743 if (transFunc->GetFunctionKind() != ecmascript::FunctionKind::CONCURRENT_FUNCTION) {
2744 return false;
2745 }
2746 ecmascript::JSThread *thread = vm->GetJSThread();
2747 JSHandle<Method> method(thread, transFunc->GetMethod());
2748 const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
2749 if (jsPandaFile == nullptr) {
2750 return false;
2751 }
2752
2753 ecmascript::CString moduleName = jsPandaFile->GetJSPandaFileDesc();
2754 ecmascript::CString recordName = method->GetRecordName();
2755
2756 // for debugger, to notify the script loaded and parsed which the concurrent function is in
2757 auto *notificationMgr = vm->GetJsDebuggerManager()->GetNotificationManager();
2758 notificationMgr->LoadModuleEvent(moduleName, recordName);
2759
2760 bool isModule = jsPandaFile->IsModule(thread, recordName);
2761 if (isModule) {
2762 ecmascript::ModuleManager *moduleManager = vm->GetModuleManager();
2763 JSHandle<ecmascript::JSTaggedValue> moduleRecord;
2764 if (jsPandaFile->IsBundlePack()) {
2765 moduleRecord = moduleManager->HostResolveImportedModule(moduleName);
2766 } else {
2767 moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(moduleName, recordName);
2768 if (ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
2769 vm->GetAOTFileManager()->LoadAiFile(jsPandaFile);
2770 }
2771 }
2772 ecmascript::SourceTextModule::Instantiate(thread, moduleRecord);
2773 if (thread->HasPendingException()) {
2774 auto exception = thread->GetException();
2775 vm->HandleUncaughtException(exception.GetTaggedObject());
2776 return false;
2777 }
2778 JSHandle<ecmascript::SourceTextModule> module = JSHandle<ecmascript::SourceTextModule>::Cast(moduleRecord);
2779 module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED);
2780 ecmascript::SourceTextModule::EvaluateForConcurrent(thread, module);
2781 transFunc->SetModule(thread, module);
2782 return true;
2783 }
2784 return false;
2785 }
2786 } // namespace panda
2787