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