1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "jsnapi_helper-inl.h"
17
18 #include <array>
19 #include <cstdint>
20
21 #include "ecmascript/base/builtins_base.h"
22 #include "ecmascript/base/json_parser.h"
23 #include "ecmascript/base/json_stringifier.h"
24 #include "ecmascript/base/string_helper.h"
25 #include "ecmascript/base/typed_array_helper-inl.h"
26 #include "ecmascript/cpu_profiler/cpu_profiler.h"
27 #include "ecmascript/ecma_global_storage-inl.h"
28 #include "ecmascript/ecma_language_context.h"
29 #include "ecmascript/ecma_module.h"
30 #include "ecmascript/ecma_string.h"
31 #include "ecmascript/ecma_vm.h"
32 #include "ecmascript/global_env.h"
33 #include "ecmascript/internal_call_params.h"
34 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
35 #include "ecmascript/jobs/micro_job_queue.h"
36 #include "ecmascript/js_array.h"
37 #include "ecmascript/js_arraybuffer.h"
38 #include "ecmascript/js_bigint.h"
39 #include "ecmascript/js_dataview.h"
40 #include "ecmascript/js_function.h"
41 #include "ecmascript/js_map.h"
42 #include "ecmascript/js_primitive_ref.h"
43 #include "ecmascript/js_promise.h"
44 #include "ecmascript/js_regexp.h"
45 #include "ecmascript/js_runtime_options.h"
46 #include "ecmascript/js_serializer.h"
47 #include "ecmascript/js_set.h"
48 #include "ecmascript/js_tagged_number.h"
49 #include "ecmascript/js_thread.h"
50 #include "ecmascript/js_typed_array.h"
51 #include "ecmascript/mem/region.h"
52 #include "ecmascript/object_factory.h"
53 #include "ecmascript/tagged_array.h"
54 #include "generated/base_options.h"
55 #include "utils/pandargs.h"
56
57 #include "os/mutex.h"
58
59 namespace panda {
60 using ecmascript::CString;
61 using ecmascript::ECMAObject;
62 using ecmascript::EcmaString;
63 using ecmascript::ErrorType;
64 using ecmascript::FastRuntimeStub;
65 using ecmascript::GlobalEnv;
66 using ecmascript::GlobalEnvConstants;
67 using ecmascript::InternalCallParams;
68 using ecmascript::JSArray;
69 using ecmascript::JSArrayBuffer;
70 using ecmascript::JSDataView;
71 using ecmascript::JSDate;
72 using ecmascript::JSFunction;
73 using ecmascript::JSFunctionBase;
74 using ecmascript::JSHClass;
75 using ecmascript::JSMap;
76 using ecmascript::JSMethod;
77 using ecmascript::JSNativePointer;
78 using ecmascript::JSObject;
79 using ecmascript::JSPrimitiveRef;
80 using ecmascript::JSPromise;
81 using ecmascript::JSRegExp;
82 using ecmascript::JSSerializer;
83 using ecmascript::JSSet;
84 using ecmascript::JSSymbol;
85 using ecmascript::JSTaggedNumber;
86 using ecmascript::JSTaggedType;
87 using ecmascript::JSTaggedValue;
88 using ecmascript::JSThread;
89 using ecmascript::ObjectFactory;
90 using ecmascript::PromiseCapability;
91 using ecmascript::PropertyDescriptor;
92 using ecmascript::OperationResult;
93 using ecmascript::Region;
94 using ecmascript::TaggedArray;
95 using ecmascript::JSTypedArray;
96 using ecmascript::base::BuiltinsBase;
97 using ecmascript::base::JsonParser;
98 using ecmascript::base::JsonStringifier;
99 using ecmascript::base::StringHelper;
100 using ecmascript::base::TypedArrayHelper;
101 using ecmascript::job::MicroJobQueue;
102 using ecmascript::job::QueueType;
103 using ecmascript::JSRuntimeOptions;
104 using ecmascript::BigInt;
105 using ecmascript::CpuProfiler;
106 template<typename T>
107 using JSHandle = ecmascript::JSHandle<T>;
108
109 namespace {
110 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
111 constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0";
112 }
113
114 int JSNApi::vmCount = 1;
115 static os::memory::Mutex mutex;
116
117 // ------------------------------------ Panda -----------------------------------------------
CreateRuntime(const RuntimeOption & option)118 bool JSNApi::CreateRuntime(const RuntimeOption &option)
119 {
120 JSRuntimeOptions runtimeOptions;
121 runtimeOptions.SetRuntimeType("ecmascript");
122
123 // GC
124 runtimeOptions.SetGcType(option.GetGcType());
125 runtimeOptions.SetRunGcInPlace(true);
126 runtimeOptions.SetArkProperties(option.GetArkProperties());
127 // Mem
128 runtimeOptions.SetHeapSizeLimit(option.GetGcPoolSize());
129 runtimeOptions.SetInternalAllocatorType("malloc");
130
131 // Boot
132 runtimeOptions.SetShouldLoadBootPandaFiles(false);
133 runtimeOptions.SetShouldInitializeIntrinsics(false);
134 runtimeOptions.SetBootClassSpaces({"ecmascript"});
135
136 // Dfx
137 base_options::Options baseOptions("");
138 baseOptions.SetLogLevel(option.GetLogLevel());
139 arg_list_t logComponents;
140 logComponents.emplace_back("all");
141 baseOptions.SetLogComponents(logComponents);
142 Logger::Initialize(baseOptions);
143 if (option.GetLogBufPrint() != nullptr) {
144 Logger::SetMobileLogPrintEntryPointByPtr(reinterpret_cast<void *>(option.GetLogBufPrint()));
145 }
146
147 runtimeOptions.SetEnableArkTools(option.GetEnableArkTools());
148 SetOptions(runtimeOptions);
149 static EcmaLanguageContext lcEcma;
150 if (!Runtime::Create(runtimeOptions, {&lcEcma})) {
151 std::cerr << "Error: cannot create runtime" << std::endl;
152 return false;
153 }
154 return true;
155 }
156
DestroyRuntime()157 bool JSNApi::DestroyRuntime()
158 {
159 return Runtime::Destroy();
160 }
161
CreateJSVM(const RuntimeOption & option)162 EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option)
163 {
164 auto runtime = Runtime::GetCurrent();
165 os::memory::LockHolder lock(mutex);
166 vmCount++;
167 if (runtime == nullptr) {
168 // Only Ark js app
169 if (!CreateRuntime(option)) {
170 vmCount = 0;
171 return nullptr;
172 }
173 vmCount--;
174 runtime = Runtime::GetCurrent();
175 return EcmaVM::Cast(runtime->GetPandaVM());
176 }
177 JSRuntimeOptions runtimeOptions;
178 runtimeOptions.SetArkProperties(option.GetArkProperties());
179 // GC
180 runtimeOptions.SetGcTriggerType("no-gc-for-start-up"); // A non-production gc strategy. Prohibit stw-gc 10 times.
181
182 return EcmaVM::Cast(EcmaVM::Create(runtimeOptions));
183 }
184
DestroyJSVM(EcmaVM * ecmaVm)185 void JSNApi::DestroyJSVM(EcmaVM *ecmaVm)
186 {
187 auto runtime = Runtime::GetCurrent();
188 if (runtime != nullptr) {
189 os::memory::LockHolder lock(mutex);
190 vmCount--;
191 PandaVM *mainVm = runtime->GetPandaVM();
192 // Only Ark js app
193 if (mainVm != ecmaVm) {
194 EcmaVM::Destroy(ecmaVm);
195 }
196
197 if (vmCount <= 0) {
198 DestroyRuntime();
199 }
200 }
201 }
202
TriggerGC(const EcmaVM * vm,TRIGGER_GC_TYPE gcType)203 void JSNApi::TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType)
204 {
205 if (vm->GetJSThread() != nullptr && vm->IsInitialized()) {
206 switch (gcType) {
207 case TRIGGER_GC_TYPE::SEMI_GC:
208 vm->CollectGarbage(ecmascript::TriggerGCType::SEMI_GC);
209 break;
210 case TRIGGER_GC_TYPE::OLD_GC:
211 vm->CollectGarbage(ecmascript::TriggerGCType::OLD_GC);
212 break;
213 case TRIGGER_GC_TYPE::FULL_GC:
214 vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC);
215 break;
216 default:
217 break;
218 }
219 }
220 }
221
ThrowException(const EcmaVM * vm,Local<JSValueRef> error)222 void JSNApi::ThrowException(const EcmaVM *vm, Local<JSValueRef> error)
223 {
224 auto thread = vm->GetJSThread();
225 thread->SetException(JSNApiHelper::ToJSTaggedValue(*error));
226 }
227
StartDebugger(const char * libraryPath,EcmaVM * vm,bool isDebugMode,int32_t instanceId,const DebuggerPostTask & debuggerPostTask)228 bool JSNApi::StartDebugger(const char *libraryPath, EcmaVM *vm, bool isDebugMode, int32_t instanceId,
229 const DebuggerPostTask &debuggerPostTask)
230 {
231 if (vm->GetJsDebuggerManager()->GetDebuggerHandler() != nullptr) {
232 return false;
233 }
234
235 auto handle = panda::os::library_loader::Load(std::string(libraryPath));
236 if (!handle) {
237 return false;
238 }
239 using StartDebugger = bool (*)(const std::string &, EcmaVM *, bool, int32_t, const DebuggerPostTask &);
240
241 auto sym = panda::os::library_loader::ResolveSymbol(handle.Value(), "StartDebug");
242 if (!sym) {
243 LOG(ERROR, RUNTIME) << sym.Error().ToString();
244 return false;
245 }
246
247 bool ret = reinterpret_cast<StartDebugger>(sym.Value())("PandaDebugger", vm, isDebugMode, instanceId,
248 debuggerPostTask);
249 if (ret) {
250 vm->GetJsDebuggerManager()->SetDebugMode(isDebugMode);
251 vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(handle.Value()));
252 }
253 return ret;
254 }
255
StopDebugger(EcmaVM * vm)256 bool JSNApi::StopDebugger(EcmaVM *vm)
257 {
258 if (vm == nullptr) {
259 return false;
260 }
261
262 const auto &handle = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
263 using StopDebug = void (*)(const std::string &);
264
265 auto sym = panda::os::library_loader::ResolveSymbol(handle, "StopDebug");
266 if (!sym) {
267 LOG(ERROR, RUNTIME) << sym.Error().ToString();
268 return false;
269 }
270
271 reinterpret_cast<StopDebug>(sym.Value())("PandaDebugger");
272 vm->GetJsDebuggerManager()->SetDebugMode(false);
273 return true;
274 }
275
Execute(EcmaVM * vm,const std::string & fileName,const std::string & entry)276 bool JSNApi::Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry)
277 {
278 std::vector<std::string> argv;
279 LOG_ECMA(DEBUG) << "start to execute ark file" << fileName;
280 if (!vm->ExecuteFromPf(fileName, entry, argv)) {
281 LOG_ECMA(ERROR) << "Cannot execute ark file '" << fileName
282 << "' with entry '" << entry << "'" << std::endl;
283 return false;
284 }
285 return true;
286 }
287
Execute(EcmaVM * vm,const uint8_t * data,int32_t size,const std::string & entry,const std::string & filename)288 bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size,
289 const std::string &entry, const std::string &filename)
290 {
291 std::vector<std::string> argv;
292 if (!vm->ExecuteFromBuffer(data, size, entry, argv, filename)) {
293 LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename
294 << "' with entry '" << entry << "'" << std::endl;
295 return false;
296 }
297 return true;
298 }
299
GetUncaughtException(const EcmaVM * vm)300 Local<ObjectRef> JSNApi::GetUncaughtException(const EcmaVM *vm)
301 {
302 return JSNApiHelper::ToLocal<ObjectRef>(vm->GetEcmaUncaughtException());
303 }
304
GetAndClearUncaughtException(const EcmaVM * vm)305 Local<ObjectRef> JSNApi::GetAndClearUncaughtException(const EcmaVM *vm)
306 {
307 return JSNApiHelper::ToLocal<ObjectRef>(vm->GetAndClearEcmaUncaughtException());
308 }
309
EnableUserUncaughtErrorHandler(EcmaVM * vm)310 void JSNApi::EnableUserUncaughtErrorHandler(EcmaVM *vm)
311 {
312 return vm->EnableUserUncaughtErrorHandler();
313 }
314
GetGlobalObject(const EcmaVM * vm)315 Local<ObjectRef> JSNApi::GetGlobalObject(const EcmaVM *vm)
316 {
317 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
318 JSHandle<JSTaggedValue> global(vm->GetJSThread(), globalEnv->GetGlobalObject());
319 return JSNApiHelper::ToLocal<ObjectRef>(global);
320 }
321
ExecutePendingJob(const EcmaVM * vm)322 void JSNApi::ExecutePendingJob(const EcmaVM *vm)
323 {
324 vm->ExecutePromisePendingJob();
325 }
326
GetHandleAddr(const EcmaVM * vm,uintptr_t localAddress)327 uintptr_t JSNApi::GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
328 {
329 if (localAddress == 0) {
330 return 0;
331 }
332 JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
333 return ecmascript::EcmaHandleScope::NewHandle(vm->GetJSThread(), value);
334 }
335
GetGlobalHandleAddr(const EcmaVM * vm,uintptr_t localAddress)336 uintptr_t JSNApi::GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
337 {
338 if (localAddress == 0) {
339 return 0;
340 }
341 JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
342 return vm->GetJSThread()->GetEcmaGlobalStorage()->NewGlobalHandle(value);
343 }
344
SetWeak(const EcmaVM * vm,uintptr_t localAddress)345 uintptr_t JSNApi::SetWeak(const EcmaVM *vm, uintptr_t localAddress)
346 {
347 if (localAddress == 0) {
348 return 0;
349 }
350 return vm->GetJSThread()->GetEcmaGlobalStorage()->SetWeak(localAddress);
351 }
352
ClearWeak(const EcmaVM * vm,uintptr_t localAddress)353 uintptr_t JSNApi::ClearWeak(const EcmaVM *vm, uintptr_t localAddress)
354 {
355 if (localAddress == 0) {
356 return 0;
357 }
358 if (JSTaggedValue(reinterpret_cast<ecmascript::EcmaGlobalStorage::Node *>(localAddress)->GetObject())
359 .IsUndefined()) {
360 LOG(ERROR, RUNTIME) << "The object of weak reference has been recycled!";
361 return 0;
362 }
363 return vm->GetJSThread()->GetEcmaGlobalStorage()->ClearWeak(localAddress);
364 }
365
IsWeak(const EcmaVM * vm,uintptr_t localAddress)366 bool JSNApi::IsWeak(const EcmaVM *vm, uintptr_t localAddress)
367 {
368 if (localAddress == 0) {
369 return false;
370 }
371 return vm->GetJSThread()->GetEcmaGlobalStorage()->IsWeak(localAddress);
372 }
373
DisposeGlobalHandleAddr(const EcmaVM * vm,uintptr_t addr)374 void JSNApi::DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr)
375 {
376 if (addr == 0) {
377 return;
378 }
379 vm->GetJSThread()->GetEcmaGlobalStorage()->DisposeGlobalHandle(addr);
380 }
381
SerializeValue(const EcmaVM * vm,Local<JSValueRef> value,Local<JSValueRef> transfer)382 void *JSNApi::SerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer)
383 {
384 ecmascript::JSThread *thread = vm->GetJSThread();
385 ecmascript::Serializer serializer(thread);
386 JSHandle<JSTaggedValue> arkValue = JSNApiHelper::ToJSHandle(value);
387 JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer);
388 std::unique_ptr<ecmascript::SerializationData> data;
389 if (serializer.WriteValue(thread, arkValue, arkTransfer)) {
390 data = serializer.Release();
391 }
392 return reinterpret_cast<void *>(data.release());
393 }
394
DeserializeValue(const EcmaVM * vm,void * recoder)395 Local<JSValueRef> JSNApi::DeserializeValue(const EcmaVM *vm, void *recoder)
396 {
397 ecmascript::JSThread *thread = vm->GetJSThread();
398 std::unique_ptr<ecmascript::SerializationData> data(reinterpret_cast<ecmascript::SerializationData *>(recoder));
399 ecmascript::Deserializer deserializer(thread, data.release());
400 JSHandle<JSTaggedValue> result = deserializer.ReadValue();
401 return JSNApiHelper::ToLocal<ObjectRef>(result);
402 }
403
DeleteSerializationData(void * data)404 void JSNApi::DeleteSerializationData(void *data)
405 {
406 ecmascript::SerializationData *value = reinterpret_cast<ecmascript::SerializationData *>(data);
407 delete value;
408 }
409
HostPromiseRejectionTracker(const EcmaVM * vm,const JSHandle<JSPromise> promise,const JSHandle<JSTaggedValue> reason,const ecmascript::PromiseRejectionEvent operation,void * data)410 void HostPromiseRejectionTracker(const EcmaVM *vm,
411 const JSHandle<JSPromise> promise,
412 const JSHandle<JSTaggedValue> reason,
413 const ecmascript::PromiseRejectionEvent operation,
414 void* data)
415 {
416 ecmascript::PromiseRejectCallback promiseRejectCallback = vm->GetPromiseRejectCallback();
417 if (promiseRejectCallback != nullptr) {
418 Local<JSValueRef> promiseVal = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>::Cast(promise));
419 PromiseRejectInfo promiseRejectInfo(promiseVal, JSNApiHelper::ToLocal<JSValueRef>(reason),
420 static_cast<PromiseRejectInfo::PROMISE_REJECTION_EVENT>(operation), data);
421 promiseRejectCallback(reinterpret_cast<void*>(&promiseRejectInfo));
422 }
423 }
424
SetHostPromiseRejectionTracker(EcmaVM * vm,void * cb,void * data)425 void JSNApi::SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data)
426 {
427 vm->SetHostPromiseRejectionTracker(HostPromiseRejectionTracker);
428 vm->SetPromiseRejectCallback(reinterpret_cast<ecmascript::PromiseRejectCallback>(cb));
429 vm->SetData(data);
430 }
431
SetHostEnqueueJob(const EcmaVM * vm,Local<JSValueRef> cb)432 void JSNApi::SetHostEnqueueJob(const EcmaVM *vm, Local<JSValueRef> cb)
433 {
434 JSHandle<JSFunction> fun = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(cb));
435 JSHandle<TaggedArray> array = vm->GetFactory()->EmptyArray();
436 JSHandle<MicroJobQueue> job = vm->GetMicroJobQueue();
437 MicroJobQueue::EnqueueJob(vm->GetJSThread(), job, QueueType::QUEUE_PROMISE, fun, array);
438 }
439
PromiseRejectInfo(Local<JSValueRef> promise,Local<JSValueRef> reason,PromiseRejectInfo::PROMISE_REJECTION_EVENT operation,void * data)440 PromiseRejectInfo::PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason,
441 PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data)
442 : promise_(promise), reason_(reason), operation_(operation), data_(data) {}
443
GetPromise() const444 Local<JSValueRef> PromiseRejectInfo::GetPromise() const
445 {
446 return promise_;
447 }
448
GetReason() const449 Local<JSValueRef> PromiseRejectInfo::GetReason() const
450 {
451 return reason_;
452 }
453
GetOperation() const454 PromiseRejectInfo::PROMISE_REJECTION_EVENT PromiseRejectInfo::GetOperation() const
455 {
456 return operation_;
457 }
458
GetData() const459 void* PromiseRejectInfo::GetData() const
460 {
461 return data_;
462 }
463
ExecuteModuleFromBuffer(EcmaVM * vm,const void * data,int32_t size,const std::string & file)464 bool JSNApi::ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file)
465 {
466 auto moduleManager = vm->GetModuleManager();
467 moduleManager->SetCurrentExportModuleName(file);
468 // Update Current Module
469 std::vector<std::string> argv;
470 if (!vm->ExecuteFromBuffer(data, size, ENTRY_POINTER, argv)) {
471 std::cerr << "Cannot execute panda file from memory" << std::endl;
472 moduleManager->RestoreCurrentExportModuleName();
473 return false;
474 }
475
476 // Restore Current Module
477 moduleManager->RestoreCurrentExportModuleName();
478 return true;
479 }
480
GetExportObject(EcmaVM * vm,const std::string & file,const std::string & itemName)481 Local<ObjectRef> JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, const std::string &itemName)
482 {
483 auto moduleManager = vm->GetModuleManager();
484 ObjectFactory *factory = vm->GetFactory();
485 JSHandle<JSTaggedValue> moduleName(factory->NewFromStdStringUnCheck(file, true));
486 JSHandle<JSTaggedValue> moduleObj = moduleManager->GetModule(vm->GetJSThread(), moduleName);
487 JSHandle<JSTaggedValue> itemString(factory->NewFromStdString(itemName));
488 JSHandle<JSTaggedValue> exportObj = moduleManager->GetModuleItem(vm->GetJSThread(), moduleObj, itemString);
489 return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
490 }
491
SetOptions(const ecmascript::JSRuntimeOptions & options)492 void JSNApi::SetOptions(const ecmascript::JSRuntimeOptions &options)
493 {
494 ecmascript::EcmaVM::options_ = options;
495 }
496 // ----------------------------------- HandleScope -------------------------------------
LocalScope(const EcmaVM * vm)497 LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread())
498 {
499 auto thread = reinterpret_cast<JSThread *>(thread_);
500 prevNext_ = thread->GetHandleScopeStorageNext();
501 prevEnd_ = thread->GetHandleScopeStorageEnd();
502 prevHandleStorageIndex_ = thread->GetCurrentHandleStorageIndex();
503 thread->HandleScopeCountAdd();
504 }
505
LocalScope(const EcmaVM * vm,JSTaggedType value)506 LocalScope::LocalScope(const EcmaVM *vm, JSTaggedType value) : thread_(vm->GetJSThread())
507 {
508 auto thread = reinterpret_cast<JSThread *>(thread_);
509 ecmascript::EcmaHandleScope::NewHandle(thread, value);
510 prevNext_ = thread->GetHandleScopeStorageNext();
511 prevEnd_ = thread->GetHandleScopeStorageEnd();
512 prevHandleStorageIndex_ = thread->GetCurrentHandleStorageIndex();
513 thread->HandleScopeCountAdd();
514 }
515
~LocalScope()516 LocalScope::~LocalScope()
517 {
518 auto thread = reinterpret_cast<JSThread *>(thread_);
519 thread->HandleScopeCountDec();
520 thread->SetHandleScopeStorageNext(static_cast<JSTaggedType *>(prevNext_));
521 if (thread->GetHandleScopeStorageEnd() != prevEnd_) {
522 thread->SetHandleScopeStorageEnd(static_cast<JSTaggedType *>(prevEnd_));
523 thread->ShrinkHandleStorage(prevHandleStorageIndex_);
524 }
525 }
526
527 // ----------------------------------- EscapeLocalScope ------------------------------
EscapeLocalScope(const EcmaVM * vm)528 EscapeLocalScope::EscapeLocalScope(const EcmaVM *vm) : LocalScope(vm, 0U)
529 {
530 auto thread = vm->GetJSThread();
531 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
532 escapeHandle_ = ToUintPtr(thread->GetHandleScopeStorageNext() - 1);
533 }
534
535 // ----------------------------------- NumberRef ---------------------------------------
New(const EcmaVM * vm,double input)536 Local<NumberRef> NumberRef::New(const EcmaVM *vm, double input)
537 {
538 JSThread *thread = vm->GetJSThread();
539 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
540 return JSNApiHelper::ToLocal<NumberRef>(number);
541 }
542
New(const EcmaVM * vm,int32_t input)543 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int32_t input)
544 {
545 JSThread *thread = vm->GetJSThread();
546 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
547 return JSNApiHelper::ToLocal<NumberRef>(number);
548 }
549
New(const EcmaVM * vm,uint32_t input)550 Local<NumberRef> NumberRef::New(const EcmaVM *vm, uint32_t input)
551 {
552 JSThread *thread = vm->GetJSThread();
553 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
554 return JSNApiHelper::ToLocal<NumberRef>(number);
555 }
556
New(const EcmaVM * vm,int64_t input)557 Local<NumberRef> NumberRef::New(const EcmaVM *vm, int64_t input)
558 {
559 JSThread *thread = vm->GetJSThread();
560 JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input));
561 return JSNApiHelper::ToLocal<NumberRef>(number);
562 }
563
Value()564 double NumberRef::Value()
565 {
566 return JSTaggedNumber(JSNApiHelper::ToJSTaggedValue(this)).GetNumber();
567 }
568
569 // ----------------------------------- BigIntRef ---------------------------------------
New(const EcmaVM * vm,uint64_t input)570 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, uint64_t input)
571 {
572 JSThread *thread = vm->GetJSThread();
573 JSHandle<BigInt> big = BigInt::Uint64ToBigInt(thread, input);
574 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
575 return JSNApiHelper::ToLocal<BigIntRef>(bigint);
576 }
577
New(const EcmaVM * vm,int64_t input)578 Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, int64_t input)
579 {
580 JSThread *thread = vm->GetJSThread();
581 JSHandle<BigInt> big = BigInt::Int64ToBigInt(thread, input);
582 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
583 return JSNApiHelper::ToLocal<BigIntRef>(bigint);
584 }
585
CreateBigWords(const EcmaVM * vm,bool sign,uint32_t size,const uint64_t * words)586 Local<JSValueRef> BigIntRef::CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words)
587 {
588 JSThread *thread = vm->GetJSThread();
589 JSHandle<BigInt> big = BigInt::CreateBigWords(thread, sign, size, words);
590 JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
591 return JSNApiHelper::ToLocal<JSValueRef>(bigint);
592 }
593
BigIntToInt64(const EcmaVM * vm,int64_t * cValue,bool * lossless)594 void BigIntRef::BigIntToInt64(const EcmaVM *vm, int64_t *cValue, bool *lossless)
595 {
596 JSThread *thread = vm->GetJSThread();
597 JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
598 BigInt::BigIntToInt64(thread, bigintVal, cValue, lossless);
599 }
600
BigIntToUint64(const EcmaVM * vm,uint64_t * cValue,bool * lossless)601 void BigIntRef::BigIntToUint64(const EcmaVM *vm, uint64_t *cValue, bool *lossless)
602 {
603 JSThread *thread = vm->GetJSThread();
604 JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
605 BigInt::BigIntToUint64(thread, bigintVal, cValue, lossless);
606 }
607
GetWordsArray(bool * signBit,size_t wordCount,uint64_t * words)608 void BigIntRef::GetWordsArray(bool* signBit, size_t wordCount, uint64_t* words)
609 {
610 JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
611 uint32_t len = bigintVal->GetLength();
612 uint32_t count = 0;
613 uint32_t index = 0;
614 for (; index < wordCount - 1; ++index) {
615 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
616 words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits
617 }
618 if (len % 2 == 0) { // 2 : len is odd or even
619 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
620 words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32; // 32 : int32_t bits
621 } else {
622 words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
623 }
624 *signBit = bigintVal->GetSign();
625 }
626
GetWordsArraySize()627 uint32_t BigIntRef::GetWordsArraySize()
628 {
629 JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
630 uint32_t len = bigintVal->GetLength();
631 return len % 2 != 0 ? len / 2 + 1 : len / 2; // 2 : len is odd or even
632 }
633
634 // ----------------------------------- BooleanRef ---------------------------------------
New(const EcmaVM * vm,bool input)635 Local<BooleanRef> BooleanRef::New(const EcmaVM *vm, bool input)
636 {
637 JSThread *thread = vm->GetJSThread();
638 JSHandle<JSTaggedValue> boolean(thread, JSTaggedValue(input));
639 return JSNApiHelper::ToLocal<BooleanRef>(boolean);
640 }
641
Value()642 bool BooleanRef::Value()
643 {
644 return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
645 }
646
647 // ----------------------------------- IntegerRef ---------------------------------------
New(const EcmaVM * vm,int input)648 Local<IntegerRef> IntegerRef::New(const EcmaVM *vm, int input)
649 {
650 JSThread *thread = vm->GetJSThread();
651 JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
652 return JSNApiHelper::ToLocal<IntegerRef>(integer);
653 }
654
NewFromUnsigned(const EcmaVM * vm,unsigned int input)655 Local<IntegerRef> IntegerRef::NewFromUnsigned(const EcmaVM *vm, unsigned int input)
656 {
657 JSThread *thread = vm->GetJSThread();
658 JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
659 return JSNApiHelper::ToLocal<IntegerRef>(integer);
660 }
661
Value()662 int IntegerRef::Value()
663 {
664 return JSNApiHelper::ToJSTaggedValue(this).GetInt();
665 }
666
667 // ----------------------------------- StringRef ----------------------------------------
NewFromUtf8(const EcmaVM * vm,const char * utf8,int length)668 Local<StringRef> StringRef::NewFromUtf8(const EcmaVM *vm, const char *utf8, int length)
669 {
670 ObjectFactory *factory = vm->GetFactory();
671 if (length < 0) {
672 JSHandle<JSTaggedValue> current(factory->NewFromString(utf8));
673 return JSNApiHelper::ToLocal<StringRef>(current);
674 }
675 JSHandle<JSTaggedValue> current(factory->NewFromUtf8(reinterpret_cast<const uint8_t *>(utf8), length));
676 return JSNApiHelper::ToLocal<StringRef>(current);
677 }
678
ToString()679 std::string StringRef::ToString()
680 {
681 return StringHelper::ToStdString(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject()));
682 }
683
Length()684 int32_t StringRef::Length()
685 {
686 return EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetLength();
687 }
688
Utf8Length()689 int32_t StringRef::Utf8Length()
690 {
691 return EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetUtf8Length();
692 }
693
WriteUtf8(char * buffer,int length)694 int StringRef::WriteUtf8(char *buffer, int length)
695 {
696 return EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())
697 ->CopyDataUtf8(reinterpret_cast<uint8_t *>(buffer), length);
698 }
699
700 // ----------------------------------- SymbolRef -----------------------------------------
New(const EcmaVM * vm,Local<StringRef> description)701 Local<SymbolRef> SymbolRef::New(const EcmaVM *vm, Local<StringRef> description)
702 {
703 ObjectFactory *factory = vm->GetFactory();
704 JSHandle<JSSymbol> symbol = factory->NewJSSymbol();
705 JSTaggedValue desc = JSNApiHelper::ToJSTaggedValue(*description);
706 symbol->SetDescription(vm->GetJSThread(), desc);
707 return JSNApiHelper::ToLocal<SymbolRef>(JSHandle<JSTaggedValue>(symbol));
708 }
709
GetDescription(const EcmaVM * vm)710 Local<StringRef> SymbolRef::GetDescription(const EcmaVM *vm)
711 {
712 JSTaggedValue description = JSSymbol::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetDescription();
713 if (!description.IsString()) {
714 auto constants = vm->GetJSThread()->GlobalConstants();
715 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
716 }
717 JSHandle<JSTaggedValue> descriptionHandle(vm->GetJSThread(), description);
718 return JSNApiHelper::ToLocal<StringRef>(descriptionHandle);
719 }
720
721 // -------------------------------- NativePointerRef ------------------------------------
New(const EcmaVM * vm,void * nativePointer)722 Local<NativePointerRef> NativePointerRef::New(const EcmaVM *vm, void *nativePointer)
723 {
724 ObjectFactory *factory = vm->GetFactory();
725 JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer);
726 return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
727 }
728
New(const EcmaVM * vm,void * nativePointer,NativePointerCallback callBack,void * data)729 Local<NativePointerRef> NativePointerRef::New(
730 const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data)
731 {
732 ObjectFactory *factory = vm->GetFactory();
733 JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data);
734 return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
735 }
736
Value()737 void *NativePointerRef::Value()
738 {
739 JSHandle<JSTaggedValue> nativePointer = JSNApiHelper::ToJSHandle(this);
740 return JSHandle<JSNativePointer>(nativePointer)->GetExternalPointer();
741 }
742
743 // ----------------------------------- ObjectRef ----------------------------------------
New(const EcmaVM * vm)744 Local<ObjectRef> ObjectRef::New(const EcmaVM *vm)
745 {
746 ObjectFactory *factory = vm->GetFactory();
747 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
748 JSHandle<JSTaggedValue> constructor = globalEnv->GetObjectFunction();
749 JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
750 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), JSValueRef::Exception(vm));
751 return JSNApiHelper::ToLocal<ObjectRef>(object);
752 }
753
Set(const EcmaVM * vm,Local<JSValueRef> key,Local<JSValueRef> value)754 bool ObjectRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
755 {
756 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
757 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
758 JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value);
759 bool result = JSTaggedValue::SetProperty(vm->GetJSThread(), obj, keyValue, valueValue);
760 RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), false);
761 return result;
762 }
763
Set(const EcmaVM * vm,uint32_t key,Local<JSValueRef> value)764 bool ObjectRef::Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value)
765 {
766 Local<JSValueRef> keyValue = NumberRef::New(vm, key);
767 return Set(vm, keyValue, value);
768 }
769
SetAccessorProperty(const EcmaVM * vm,Local<JSValueRef> key,Local<FunctionRef> getter,Local<FunctionRef> setter,PropertyAttribute attribute)770 bool ObjectRef::SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter,
771 Local<FunctionRef> setter, PropertyAttribute attribute)
772 {
773 JSThread *thread = vm->GetJSThread();
774 JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter);
775 JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter);
776 PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
777 desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
778 desc.SetSetter(setterValue);
779 desc.SetGetter(getterValue);
780 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
781 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
782 bool result = JSTaggedValue::DefineOwnProperty(thread, obj, keyValue, desc);
783 RETURN_VALUE_IF_ABRUPT(thread, false);
784 return result;
785 }
786
Get(const EcmaVM * vm,Local<JSValueRef> key)787 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
788 {
789 JSThread *thread = vm->GetJSThread();
790 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
791 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
792 OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue);
793 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
794 if (!ret.GetPropertyMetaData().IsFound()) {
795 return JSValueRef::Undefined(vm);
796 }
797 return JSNApiHelper::ToLocal<JSValueRef>(ret.GetValue());
798 }
799
Get(const EcmaVM * vm,int32_t key)800 Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, int32_t key)
801 {
802 Local<JSValueRef> keyValue = IntegerRef::New(vm, key);
803 return Get(vm, keyValue);
804 }
805
GetOwnProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute & property)806 bool ObjectRef::GetOwnProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute &property)
807 {
808 JSThread *thread = vm->GetJSThread();
809 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
810 JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
811 PropertyDescriptor desc(thread);
812 bool ret = JSObject::GetOwnProperty(thread, JSHandle<JSObject>(obj), keyValue, desc);
813 if (!ret) {
814 return false;
815 }
816 property.SetValue(JSNApiHelper::ToLocal<JSValueRef>(desc.GetValue()));
817 if (desc.HasGetter()) {
818 property.SetGetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetGetter()));
819 }
820 if (desc.HasSetter()) {
821 property.SetSetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetSetter()));
822 }
823 if (desc.HasWritable()) {
824 property.SetWritable(desc.IsWritable());
825 }
826 if (desc.HasEnumerable()) {
827 property.SetEnumerable(desc.IsEnumerable());
828 }
829 if (desc.HasConfigurable()) {
830 property.SetConfigurable(desc.IsConfigurable());
831 }
832
833 return true;
834 }
835
GetOwnPropertyNames(const EcmaVM * vm)836 Local<ArrayRef> ObjectRef::GetOwnPropertyNames(const EcmaVM *vm)
837 {
838 JSThread *thread = vm->GetJSThread();
839 JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this));
840 JSHandle<TaggedArray> array(JSTaggedValue::GetOwnPropertyKeys(thread, obj));
841 JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
842 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
843 return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
844 }
845
GetOwnEnumerablePropertyNames(const EcmaVM * vm)846 Local<ArrayRef> ObjectRef::GetOwnEnumerablePropertyNames(const EcmaVM *vm)
847 {
848 JSThread *thread = vm->GetJSThread();
849 JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(this));
850 JSHandle<TaggedArray> array(JSObject::EnumerableOwnNames(thread, obj));
851 JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
852 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
853 return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
854 }
855
GetPrototype(const EcmaVM * vm)856 Local<JSValueRef> ObjectRef::GetPrototype(const EcmaVM *vm)
857 {
858 JSThread *thread = vm->GetJSThread();
859 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
860 JSHandle<JSTaggedValue> prototype(thread, object->GetPrototype(thread));
861 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
862 return JSNApiHelper::ToLocal<JSValueRef>(prototype);
863 }
864
DefineProperty(const EcmaVM * vm,Local<JSValueRef> key,PropertyAttribute attribute)865 bool ObjectRef::DefineProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute attribute)
866 {
867 JSThread *thread = vm->GetJSThread();
868 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
869 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
870 PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
871 desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
872 bool result = object->DefinePropertyOrThrow(thread, object, keyValue, desc);
873 RETURN_VALUE_IF_ABRUPT(thread, false);
874 return result;
875 }
876
Has(const EcmaVM * vm,Local<JSValueRef> key)877 bool ObjectRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
878 {
879 JSThread *thread = vm->GetJSThread();
880 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
881 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
882 bool result = object->HasProperty(thread, object, keyValue);
883 RETURN_VALUE_IF_ABRUPT(thread, false);
884 return result;
885 }
886
Has(const EcmaVM * vm,uint32_t key)887 bool ObjectRef::Has(const EcmaVM *vm, uint32_t key)
888 {
889 JSThread *thread = vm->GetJSThread();
890 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
891 bool result = object->HasProperty(thread, object, key);
892 RETURN_VALUE_IF_ABRUPT(thread, false);
893 return result;
894 }
895
Delete(const EcmaVM * vm,Local<JSValueRef> key)896 bool ObjectRef::Delete(const EcmaVM *vm, Local<JSValueRef> key)
897 {
898 JSThread *thread = vm->GetJSThread();
899 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
900 JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
901 bool result = object->DeleteProperty(thread, object, keyValue);
902 RETURN_VALUE_IF_ABRUPT(thread, false);
903 return result;
904 }
905
Delete(const EcmaVM * vm,uint32_t key)906 bool ObjectRef::Delete(const EcmaVM *vm, uint32_t key)
907 {
908 JSThread *thread = vm->GetJSThread();
909 JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
910 JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(key));
911 bool result = object->DeleteProperty(thread, object, keyHandle);
912 RETURN_VALUE_IF_ABRUPT(thread, false);
913 return result;
914 }
915
SetNativePointerFieldCount(int32_t count)916 void ObjectRef::SetNativePointerFieldCount(int32_t count)
917 {
918 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
919 object->SetNativePointerFieldCount(count);
920 }
921
GetNativePointerFieldCount()922 int32_t ObjectRef::GetNativePointerFieldCount()
923 {
924 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
925 return object->GetNativePointerFieldCount();
926 }
927
GetNativePointerField(int32_t index)928 void *ObjectRef::GetNativePointerField(int32_t index)
929 {
930 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
931 return object->GetNativePointerField(index);
932 }
933
SetNativePointerField(int32_t index,void * nativePointer,NativePointerCallback callBack,void * data)934 void ObjectRef::SetNativePointerField(int32_t index, void *nativePointer,
935 NativePointerCallback callBack, void *data)
936 {
937 JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
938 object->SetNativePointerField(index, nativePointer, callBack, data);
939 }
940
941 // ----------------------------------- FunctionRef --------------------------------------
New(EcmaVM * vm,FunctionCallback nativeFunc,void * data)942 Local<FunctionRef> FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc, void *data)
943 {
944 JSThread *thread = vm->GetJSThread();
945 ObjectFactory *factory = vm->GetFactory();
946 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
947 JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback)));
948 JSHandle<JSNativePointer> extraInfo =
949 factory->NewJSNativePointer(reinterpret_cast<void *>(nativeFunc), nullptr, data);
950 current->SetFunctionExtraInfo(thread, extraInfo.GetTaggedValue());
951 return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
952 }
953
New(EcmaVM * vm,FunctionCallback nativeFunc,Deleter deleter,void * data)954 Local<FunctionRef> FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc, Deleter deleter, void *data)
955 {
956 JSThread *thread = vm->GetJSThread();
957 ObjectFactory *factory = vm->GetFactory();
958 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
959 JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback)));
960 JSHandle<JSNativePointer> extraInfo =
961 factory->NewJSNativePointer(reinterpret_cast<void *>(nativeFunc), deleter, data);
962 vm->PushToArrayDataList(*extraInfo);
963 current->SetFunctionExtraInfo(thread, extraInfo.GetTaggedValue());
964 return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
965 }
966
NewWithProperty(EcmaVM * vm,FunctionCallback nativeFunc,void * data)967 Local<FunctionRef> FunctionRef::NewWithProperty(EcmaVM *vm, FunctionCallback nativeFunc, void *data)
968 {
969 JSThread *thread = vm->GetJSThread();
970 ObjectFactory *factory = vm->GetFactory();
971 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
972 JSHandle<JSFunction> current =
973 factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallbackWithProperty));
974 JSHandle<JSNativePointer> extraInfo =
975 factory->NewJSNativePointer(reinterpret_cast<void *>(nativeFunc), nullptr, data);
976 current->SetFunctionExtraInfo(thread, extraInfo.GetTaggedValue());
977 return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
978 }
979
NewClassFunction(EcmaVM * vm,FunctionCallbackWithNewTarget nativeFunc,Deleter deleter,void * data)980 Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, FunctionCallbackWithNewTarget nativeFunc, Deleter deleter,
981 void *data)
982 {
983 JSThread *thread = vm->GetJSThread();
984 ObjectFactory *factory = vm->GetFactory();
985 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
986 JSHandle<JSHClass> dynclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName());
987 JSMethod *method =
988 vm->GetMethodForNativeFunction(reinterpret_cast<void *>(Callback::RegisterCallbackWithNewTarget));
989 JSHandle<JSFunction> current =
990 factory->NewJSFunctionByDynClass(method, dynclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
991
992 auto globalConst = thread->GlobalConstants();
993 JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor();
994 current->SetPropertyInlinedProps(thread, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX,
995 accessor.GetTaggedValue());
996
997 JSHandle<JSNativePointer> extraInfo =
998 factory->NewJSNativePointer(reinterpret_cast<void *>(nativeFunc), deleter, data);
999 if (deleter != nullptr) {
1000 vm->PushToArrayDataList(*extraInfo);
1001 }
1002 current->SetFunctionExtraInfo(thread, extraInfo.GetTaggedValue());
1003
1004 JSHandle<JSObject> clsPrototype = JSFunction::NewJSFunctionPrototype(thread, factory, current);
1005 clsPrototype.GetTaggedValue().GetTaggedObject()->GetClass()->SetClassPrototype(true);
1006 JSHandle<JSTaggedValue>::Cast(current)->GetTaggedObject()->GetClass()->SetClassConstructor(true);
1007 current->SetClassConstructor(true);
1008 JSHandle<JSTaggedValue> parent = env->GetFunctionPrototype();
1009 JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(current), parent);
1010 current->SetHomeObject(thread, clsPrototype);
1011 return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
1012 }
1013
Call(const EcmaVM * vm,Local<JSValueRef> thisObj,const Local<JSValueRef> argv[],int32_t length)1014 Local<JSValueRef> FunctionRef::Call(const EcmaVM *vm, Local<JSValueRef> thisObj,
1015 const Local<JSValueRef> argv[], // NOLINTNEXTLINE(modernize-avoid-c-arrays)
1016 int32_t length)
1017 {
1018 JSThread *thread = vm->GetJSThread();
1019 if (!IsFunction()) {
1020 return JSValueRef::Undefined(vm);
1021 }
1022 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
1023 JSHandle<JSTaggedValue> thisValue = JSNApiHelper::ToJSHandle(thisObj);
1024 ObjectFactory *factory = vm->GetFactory();
1025 JSHandle<TaggedArray> arguments = factory->NewTaggedArray(length);
1026 Span<const Local<JSValueRef>> sp(argv, length);
1027 for (int i = 0; i < length; ++i) {
1028 arguments->Set(thread, i, JSNApiHelper::ToJSHandle(sp[i]));
1029 }
1030 InternalCallParams *args = thread->GetInternalCallParams();
1031 args->MakeArgList(*arguments);
1032 JSTaggedValue result = JSFunction::Call(thread, func, thisValue, arguments->GetLength(), args->GetArgv());
1033 RETURN_VALUE_IF_ABRUPT_NOT_CLEAR_EXCEPTION(thread, JSValueRef::Exception(vm));
1034 JSHandle<JSTaggedValue> resultValue(thread, result);
1035
1036 vm->ExecutePromisePendingJob();
1037 RETURN_VALUE_IF_ABRUPT_NOT_CLEAR_EXCEPTION(thread, JSValueRef::Exception(vm));
1038
1039 return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
1040 }
1041
Constructor(const EcmaVM * vm,const Local<JSValueRef> argv[],int32_t length)1042 Local<JSValueRef> FunctionRef::Constructor(const EcmaVM *vm,
1043 const Local<JSValueRef> argv[], // NOLINTNEXTLINE(modernize-avoid-c-arrays)
1044 int32_t length)
1045 {
1046 JSThread *thread = vm->GetJSThread();
1047 if (!IsFunction()) {
1048 return JSValueRef::Undefined(vm);
1049 }
1050 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
1051 JSHandle<JSTaggedValue> newTarget = func;
1052 ObjectFactory *factory = vm->GetFactory();
1053 JSHandle<TaggedArray> arguments = factory->NewTaggedArray(length);
1054 Span<const Local<JSValueRef>> sp(argv, length);
1055 for (int i = 0; i < length; ++i) {
1056 arguments->Set(thread, i, JSNApiHelper::ToJSHandle(sp[i]));
1057 }
1058 ecmascript::InternalCallParams *params = thread->GetInternalCallParams();
1059 params->MakeArgList(*arguments);
1060 JSTaggedValue result = JSFunction::Construct(thread, func, length, params->GetArgv(), newTarget);
1061 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1062 JSHandle<JSTaggedValue> resultValue(vm->GetJSThread(), result);
1063 return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
1064 }
1065
GetFunctionPrototype(const EcmaVM * vm)1066 Local<JSValueRef> FunctionRef::GetFunctionPrototype(const EcmaVM *vm)
1067 {
1068 JSThread *thread = vm->GetJSThread();
1069 JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
1070 JSHandle<JSTaggedValue> prototype(thread, JSHandle<JSFunction>(func)->GetFunctionPrototype());
1071 return JSNApiHelper::ToLocal<JSValueRef>(prototype);
1072 }
1073
Inherit(const EcmaVM * vm,Local<FunctionRef> parent)1074 bool FunctionRef::Inherit(const EcmaVM *vm, Local<FunctionRef> parent)
1075 {
1076 JSThread *thread = vm->GetJSThread();
1077 JSHandle<JSTaggedValue> parentValue = JSNApiHelper::ToJSHandle(parent);
1078 JSHandle<JSObject> parentHandle = JSHandle<JSObject>::Cast(parentValue);
1079 JSHandle<JSObject> thisHandle = JSHandle<JSObject>::Cast(JSNApiHelper::ToJSHandle(this));
1080 // Set this.__proto__ to parent
1081 bool res = JSObject::SetPrototype(thread, thisHandle, parentValue);
1082 if (!res) {
1083 return false;
1084 }
1085 // Set this.Prototype.__proto__ to parent.Prototype
1086 JSHandle<JSTaggedValue> parentProtoType(thread, JSFunction::PrototypeGetter(thread, parentHandle));
1087 JSHandle<JSTaggedValue> thisProtoType(thread, JSFunction::PrototypeGetter(thread, thisHandle));
1088 return JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(thisProtoType), parentProtoType);
1089 }
1090
SetName(const EcmaVM * vm,Local<StringRef> name)1091 void FunctionRef::SetName(const EcmaVM *vm, Local<StringRef> name)
1092 {
1093 JSThread *thread = vm->GetJSThread();
1094 JSFunction *func = JSFunction::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject());
1095 JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
1096 JSFunction::SetFunctionNameNoPrefix(thread, func, key);
1097 }
1098
GetName(const EcmaVM * vm)1099 Local<StringRef> FunctionRef::GetName(const EcmaVM *vm)
1100 {
1101 JSThread *thread = vm->GetJSThread();
1102 JSHandle<JSFunctionBase> func = JSHandle<JSFunctionBase>(thread, JSNApiHelper::ToJSTaggedValue(this));
1103 JSHandle<JSTaggedValue> name = JSFunctionBase::GetFunctionName(thread, func);
1104 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1105 return JSNApiHelper::ToLocal<StringRef>(name);
1106 }
1107
IsNative(const EcmaVM * vm)1108 bool FunctionRef::IsNative(const EcmaVM *vm)
1109 {
1110 JSThread *thread = vm->GetJSThread();
1111 JSHandle<JSFunctionBase> func = JSHandle<JSFunctionBase>(thread, JSNApiHelper::ToJSTaggedValue(this));
1112 JSMethod *method = func->GetMethod();
1113 return method->IsNative();
1114 }
1115
1116 // ----------------------------------- ArrayRef ----------------------------------------
New(const EcmaVM * vm,int32_t length)1117 Local<ArrayRef> ArrayRef::New(const EcmaVM *vm, int32_t length)
1118 {
1119 JSThread *thread = vm->GetJSThread();
1120 JSTaggedNumber arrayLen(length);
1121 JSHandle<JSTaggedValue> array = JSArray::ArrayCreate(thread, arrayLen);
1122 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1123 return JSNApiHelper::ToLocal<ArrayRef>(array);
1124 }
1125
Length(const EcmaVM * vm)1126 int32_t ArrayRef::Length([[maybe_unused]] const EcmaVM *vm)
1127 {
1128 return JSArray::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetArrayLength();
1129 }
1130
1131
GetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index)1132 Local<JSValueRef> ArrayRef::GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index)
1133 {
1134 JSThread *thread = vm->GetJSThread();
1135 JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(obj);
1136 JSHandle<JSTaggedValue> result = JSArray::FastGetPropertyByValue(thread, object, index);
1137 return JSNApiHelper::ToLocal<JSValueRef>(result);
1138 }
1139
SetValueAt(const EcmaVM * vm,Local<JSValueRef> obj,uint32_t index,Local<JSValueRef> value)1140 bool ArrayRef::SetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value)
1141 {
1142 JSThread *thread = vm->GetJSThread();
1143 JSHandle<JSTaggedValue> objectHandle = JSNApiHelper::ToJSHandle(obj);
1144 JSHandle<JSTaggedValue> valueHandle = JSNApiHelper::ToJSHandle(value);
1145 return JSArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle);
1146 }
1147 // ---------------------------------- Promise --------------------------------------
New(const EcmaVM * vm)1148 Local<PromiseCapabilityRef> PromiseCapabilityRef::New(const EcmaVM *vm)
1149 {
1150 JSThread *thread = vm->GetJSThread();
1151 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
1152 JSHandle<JSTaggedValue> constructor(globalEnv->GetPromiseFunction());
1153 JSHandle<JSTaggedValue> capability(JSPromise::NewPromiseCapability(thread, constructor));
1154 return JSNApiHelper::ToLocal<PromiseCapabilityRef>(capability);
1155 }
1156
GetPromise(const EcmaVM * vm)1157 Local<PromiseRef> PromiseCapabilityRef::GetPromise(const EcmaVM *vm)
1158 {
1159 JSThread *thread = vm->GetJSThread();
1160 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1161 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, capacity->GetPromise()));
1162 }
1163
Resolve(const EcmaVM * vm,Local<JSValueRef> value)1164 bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value)
1165 {
1166 JSThread *thread = vm->GetJSThread();
1167 const GlobalEnvConstants *constants = thread->GlobalConstants();
1168
1169 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(value);
1170 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1171 JSHandle<JSTaggedValue> resolve(thread, capacity->GetResolve());
1172 JSHandle<JSTaggedValue> undefined(thread, constants->GetUndefined());
1173 InternalCallParams *arguments = thread->GetInternalCallParams();
1174 arguments->MakeArgv(arg);
1175 JSFunction::Call(thread, resolve, undefined, 1, arguments->GetArgv());
1176 RETURN_VALUE_IF_ABRUPT(thread, false);
1177
1178 vm->ExecutePromisePendingJob();
1179 RETURN_VALUE_IF_ABRUPT(thread, false);
1180 return true;
1181 }
1182
Reject(const EcmaVM * vm,Local<JSValueRef> reason)1183 bool PromiseCapabilityRef::Reject(const EcmaVM *vm, Local<JSValueRef> reason)
1184 {
1185 JSThread *thread = vm->GetJSThread();
1186 const GlobalEnvConstants *constants = thread->GlobalConstants();
1187
1188 JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(reason);
1189 JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
1190 JSHandle<JSTaggedValue> reject(thread, capacity->GetReject());
1191 JSHandle<JSTaggedValue> undefined(thread, constants->GetUndefined());
1192 InternalCallParams *arguments = thread->GetInternalCallParams();
1193 arguments->MakeArgv(arg);
1194 JSFunction::Call(thread, reject, undefined, 1, arguments->GetArgv());
1195 RETURN_VALUE_IF_ABRUPT(thread, false);
1196
1197 vm->ExecutePromisePendingJob();
1198 RETURN_VALUE_IF_ABRUPT(thread, false);
1199 return true;
1200 }
1201
Catch(const EcmaVM * vm,Local<FunctionRef> handler)1202 Local<PromiseRef> PromiseRef::Catch(const EcmaVM *vm, Local<FunctionRef> handler)
1203 {
1204 JSThread *thread = vm->GetJSThread();
1205 const GlobalEnvConstants *constants = thread->GlobalConstants();
1206
1207 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
1208 JSHandle<JSTaggedValue> catchKey(thread, constants->GetPromiseCatchString());
1209 JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(handler);
1210 ecmascript::InternalCallParams *arguments = thread->GetInternalCallParams();
1211 arguments->MakeArgv(reject);
1212 JSTaggedValue result = JSFunction::Invoke(thread, promise, catchKey, 1, arguments->GetArgv());
1213
1214 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1215 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
1216 }
1217
Then(const EcmaVM * vm,Local<FunctionRef> handler)1218 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> handler)
1219 {
1220 JSThread *thread = vm->GetJSThread();
1221 const GlobalEnvConstants *constants = thread->GlobalConstants();
1222
1223 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
1224 JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
1225 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler);
1226 ecmascript::InternalCallParams *arguments = thread->GetInternalCallParams();
1227 arguments->MakeArgv(resolver.GetTaggedValue(), constants->GetUndefined());
1228 JSTaggedValue result = JSFunction::Invoke(thread, promise, thenKey, 2, arguments->GetArgv()); // 2: two args
1229
1230 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1231 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
1232 }
1233
Then(const EcmaVM * vm,Local<FunctionRef> onFulfilled,Local<FunctionRef> onRejected)1234 Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> onFulfilled, Local<FunctionRef> onRejected)
1235 {
1236 JSThread *thread = vm->GetJSThread();
1237 const GlobalEnvConstants *constants = thread->GlobalConstants();
1238
1239 JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
1240 JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
1241 JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(onFulfilled);
1242 JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(onRejected);
1243 ecmascript::InternalCallParams *arguments = thread->GetInternalCallParams();
1244 arguments->MakeArgv(resolver, reject);
1245 JSTaggedValue result = JSFunction::Invoke(thread, promise, thenKey, 2, arguments->GetArgv()); // 2: two args
1246
1247 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1248 return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
1249 }
1250 // ---------------------------------- Promise -------------------------------------
1251
1252 // ---------------------------------- Buffer -----------------------------------
New(const EcmaVM * vm,int32_t length)1253 Local<ArrayBufferRef> ArrayBufferRef::New(const EcmaVM *vm, int32_t length)
1254 {
1255 JSThread *thread = vm->GetJSThread();
1256 ObjectFactory *factory = vm->GetFactory();
1257
1258 JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(length);
1259 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1260 return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
1261 }
1262
New(const EcmaVM * vm,void * buffer,int32_t length,const Deleter & deleter,void * data)1263 Local<ArrayBufferRef> ArrayBufferRef::New(
1264 const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter, void *data)
1265 {
1266 JSThread *thread = vm->GetJSThread();
1267 ObjectFactory *factory = vm->GetFactory();
1268
1269 JSHandle<JSArrayBuffer> arrayBuffer =
1270 factory->NewJSArrayBuffer(buffer, length, reinterpret_cast<ecmascript::DeleteEntryPoint>(deleter), data);
1271 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1272 return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
1273 }
1274
ByteLength(const EcmaVM * vm)1275 int32_t ArrayBufferRef::ByteLength(const EcmaVM *vm)
1276 {
1277 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1278 return arrayBuffer->GetArrayBufferByteLength();
1279 }
1280
GetBuffer()1281 void *ArrayBufferRef::GetBuffer()
1282 {
1283 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
1284 JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData();
1285 if (!bufferData.IsJSNativePointer()) {
1286 return nullptr;
1287 }
1288 return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
1289 }
1290 // ---------------------------------- Buffer -----------------------------------
1291
1292 // ---------------------------------- DataView -----------------------------------
New(const EcmaVM * vm,Local<ArrayBufferRef> arrayBuffer,uint32_t byteOffset,uint32_t byteLength)1293 Local<DataViewRef> DataViewRef::New(
1294 const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset, uint32_t byteLength)
1295 {
1296 JSThread *thread = vm->GetJSThread();
1297 ObjectFactory *factory = vm->GetFactory();
1298
1299 JSHandle<JSArrayBuffer> buffer(JSNApiHelper::ToJSHandle(arrayBuffer));
1300 JSHandle<JSDataView> dataView = factory->NewJSDataView(buffer, byteOffset, byteLength);
1301 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1302 return JSNApiHelper::ToLocal<DataViewRef>(JSHandle<JSTaggedValue>(dataView));
1303 }
1304
ByteLength()1305 uint32_t DataViewRef::ByteLength()
1306 {
1307 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
1308 return dataView->GetByteLength();
1309 }
1310
ByteOffset()1311 uint32_t DataViewRef::ByteOffset()
1312 {
1313 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
1314 return dataView->GetByteOffset();
1315 }
1316
GetArrayBuffer(const EcmaVM * vm)1317 Local<ArrayBufferRef> DataViewRef::GetArrayBuffer(const EcmaVM *vm)
1318 {
1319 JSThread *thread = vm->GetJSThread();
1320 JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
1321 JSHandle<JSTaggedValue> arrayBuffer(thread, dataView->GetViewedArrayBuffer());
1322 return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
1323 }
1324 // ---------------------------------- DataView -----------------------------------
1325
1326 // ---------------------------------- TypedArray -----------------------------------
ByteLength(const EcmaVM * vm)1327 int32_t TypedArrayRef::ByteLength(const EcmaVM *vm)
1328 {
1329 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
1330 JSTaggedValue length = typedArray->GetByteLength();
1331 if (!length.IsNumber()) {
1332 return 0;
1333 }
1334 return length.GetNumber();
1335 }
1336
ByteOffset(const EcmaVM * vm)1337 int32_t TypedArrayRef::ByteOffset(const EcmaVM *vm)
1338 {
1339 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
1340 JSTaggedValue length = typedArray->GetByteOffset();
1341 if (!length.IsNumber()) {
1342 return 0;
1343 }
1344 return length.GetNumber();
1345 }
1346
ArrayLength(const EcmaVM * vm)1347 int32_t TypedArrayRef::ArrayLength(const EcmaVM *vm)
1348 {
1349 JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
1350 JSTaggedValue length = typedArray->GetArrayLength();
1351 if (!length.IsNumber()) {
1352 return 0;
1353 }
1354 return length.GetNumber();
1355 }
1356
GetArrayBuffer(const EcmaVM * vm)1357 Local<ArrayBufferRef> TypedArrayRef::GetArrayBuffer(const EcmaVM *vm)
1358 {
1359 JSThread *thread = vm->GetJSThread();
1360 JSHandle<JSObject> typeArray(JSNApiHelper::ToJSHandle(this));
1361 JSHandle<JSTaggedValue> arrayBuffer(thread, JSTypedArray::Cast(*typeArray)->GetViewedArrayBuffer());
1362 return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
1363 }
1364
1365 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1366 #define TYPED_ARRAY_NEW(Type) \
1367 Local<Type##Ref> Type##Ref::New( \
1368 const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length) \
1369 { \
1370 JSThread *thread = vm->GetJSThread(); \
1371 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); \
1372 \
1373 JSHandle<JSTaggedValue> func = env->Get##Type##Function(); \
1374 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(buffer)); \
1375 ecmascript::InternalCallParams *argv = thread->GetInternalCallParams(); \
1376 argv->MakeArgv(arrayBuffer.GetTaggedValue(), JSTaggedValue(byteOffset), JSTaggedValue(length)); \
1377 uint32_t argc = 3; \
1378 JSTaggedValue result = JSFunction::Construct(thread, func, argc, argv->GetArgv(), func); \
1379 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm)); \
1380 JSHandle<JSTaggedValue> resultHandle(thread, result); \
1381 return JSNApiHelper::ToLocal<Type##Ref>(resultHandle); \
1382 }
1383
1384 TYPED_ARRAY_ALL(TYPED_ARRAY_NEW)
1385
1386 #undef TYPED_ARRAY_NEW
1387 // ---------------------------------- TypedArray -----------------------------------
1388
1389 // ---------------------------------- Error ---------------------------------------
1390 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1391 #define EXCEPTION_ERROR_NEW(name, type) \
1392 Local<JSValueRef> Exception::name(const EcmaVM *vm, Local<StringRef> message) \
1393 { \
1394 JSThread *thread = vm->GetJSThread(); \
1395 ObjectFactory *factory = vm->GetFactory(); \
1396 \
1397 JSHandle<EcmaString> messageValue(JSNApiHelper::ToJSHandle(message)); \
1398 JSHandle<JSTaggedValue> result(factory->NewJSError(ErrorType::type, messageValue)); \
1399 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm)); \
1400 return JSNApiHelper::ToLocal<JSValueRef>(result); \
1401 }
1402
EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)1403 EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)
1404
1405 #undef EXCEPTION_ERROR_NEW
1406 // ---------------------------------- Error ---------------------------------------
1407
1408 // ---------------------------------- JSON ------------------------------------------
1409 Local<JSValueRef> JSON::Parse(const EcmaVM *vm, Local<StringRef> string)
1410 {
1411 JSThread *thread = vm->GetJSThread();
1412 auto ecmaStr = EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject());
1413 JSHandle<JSTaggedValue> result;
1414 if (ecmaStr->IsUtf8()) {
1415 JsonParser<uint8_t> parser(thread);
1416 result = parser.ParseUtf8(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
1417 } else {
1418 JsonParser<uint16_t> parser(thread);
1419 result = parser.ParseUtf16(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
1420 }
1421 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1422 return JSNApiHelper::ToLocal<JSValueRef>(result);
1423 }
1424
Stringify(const EcmaVM * vm,Local<JSValueRef> json)1425 Local<JSValueRef> JSON::Stringify(const EcmaVM *vm, Local<JSValueRef> json)
1426 {
1427 JSThread *thread = vm->GetJSThread();
1428 auto constants = thread->GlobalConstants();
1429 JsonStringifier stringifier(thread);
1430 JSHandle<JSTaggedValue> str = stringifier.Stringify(
1431 JSNApiHelper::ToJSHandle(json), constants->GetHandledUndefined(), constants->GetHandledUndefined());
1432 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1433 return JSNApiHelper::ToLocal<JSValueRef>(str);
1434 }
1435
GetOriginalSource(const EcmaVM * vm)1436 Local<StringRef> RegExpRef::GetOriginalSource(const EcmaVM *vm)
1437 {
1438 JSThread *thread = vm->GetJSThread();
1439 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
1440 JSTaggedValue source = regExp->GetOriginalSource();
1441 if (!source.IsString()) {
1442 auto constants = thread->GlobalConstants();
1443 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
1444 }
1445 JSHandle<JSTaggedValue> sourceHandle(thread, source);
1446 return JSNApiHelper::ToLocal<StringRef>(sourceHandle);
1447 }
1448
New(const EcmaVM * vm,double time)1449 Local<DateRef> DateRef::New(const EcmaVM *vm, double time)
1450 {
1451 JSThread *thread = vm->GetJSThread();
1452 ObjectFactory *factory = vm->GetFactory();
1453 JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
1454 JSHandle<JSTaggedValue> dateFunction = globalEnv->GetDateFunction();
1455 JSHandle<JSDate> dateObject =
1456 JSHandle<JSDate>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dateFunction), dateFunction));
1457 dateObject->SetTimeValue(thread, JSTaggedValue(time));
1458 return JSNApiHelper::ToLocal<DateRef>(JSHandle<JSTaggedValue>(dateObject));
1459 }
1460
ToString(const EcmaVM * vm)1461 Local<StringRef> DateRef::ToString(const EcmaVM *vm)
1462 {
1463 JSThread *thread = vm->GetJSThread();
1464 JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
1465 JSTaggedValue dateStr = date->ToString(thread);
1466 if (!dateStr.IsString()) {
1467 auto constants = thread->GlobalConstants();
1468 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
1469 }
1470 JSHandle<JSTaggedValue> dateStrHandle(thread, dateStr);
1471 return JSNApiHelper::ToLocal<StringRef>(dateStrHandle);
1472 }
1473
GetTime()1474 double DateRef::GetTime()
1475 {
1476 JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
1477 if (!date->IsDate()) {
1478 LOG(ERROR, RUNTIME) << "Not a Date Object";
1479 }
1480 return date->GetTime().GetDouble();
1481 }
1482
GetSize()1483 int32_t MapRef::GetSize()
1484 {
1485 JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
1486 return map->GetSize();
1487 }
1488
GetSize()1489 int32_t SetRef::GetSize()
1490 {
1491 JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
1492 return set->GetSize();
1493 }
1494
1495 // ----------------------------------- FunctionCallback ---------------------------------
RegisterCallback(ecmascript::EcmaRuntimeCallInfo * info)1496 JSTaggedValue Callback::RegisterCallback(ecmascript::EcmaRuntimeCallInfo *info)
1497 {
1498 // Constructor
1499 JSThread *thread = info->GetThread();
1500 JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(info);
1501 if (!constructor->IsJSFunction()) {
1502 return JSTaggedValue::False();
1503 }
1504 JSHandle<JSFunction> function(constructor);
1505 JSHandle<JSTaggedValue> extraInfoValue(thread, function->GetFunctionExtraInfo());
1506 if (!extraInfoValue->IsJSNativePointer()) {
1507 return JSTaggedValue::False();
1508 }
1509 JSHandle<JSNativePointer> extraInfo(extraInfoValue);
1510 // vm
1511 Region *region = Region::ObjectAddressToRange(extraInfo.GetTaggedValue().GetTaggedObject());
1512 if (region == nullptr) {
1513 return JSTaggedValue::False();
1514 }
1515 EcmaVM *vm = thread->GetEcmaVM();
1516 // data
1517 void *data = extraInfo->GetData();
1518 // callBack
1519 FunctionCallback nativeFunc = reinterpret_cast<FunctionCallback>(extraInfo->GetExternalPointer());
1520
1521 // this
1522 JSHandle<JSTaggedValue> thisValue(BuiltinsBase::GetThis(info));
1523
1524 // arguments
1525 std::vector<Local<JSValueRef>> arguments;
1526 uint32_t length = info->GetArgsNumber();
1527 for (uint32_t i = 0; i < length; ++i) {
1528 arguments.emplace_back(JSNApiHelper::ToLocal<JSValueRef>(BuiltinsBase::GetCallArg(info, i)));
1529 }
1530
1531 Local<JSValueRef> result = nativeFunc(vm,
1532 JSNApiHelper::ToLocal<JSValueRef>(thisValue),
1533 arguments.data(),
1534 arguments.size(),
1535 data);
1536 return JSNApiHelper::ToJSHandle(result).GetTaggedValue();
1537 }
1538
RegisterCallbackWithProperty(ecmascript::EcmaRuntimeCallInfo * info)1539 JSTaggedValue Callback::RegisterCallbackWithProperty(ecmascript::EcmaRuntimeCallInfo *info)
1540 {
1541 // Constructor
1542 JSThread *thread = info->GetThread();
1543 JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(info);
1544 if (!constructor->IsJSFunction()) {
1545 return JSTaggedValue::False();
1546 }
1547 JSHandle<JSFunction> function(constructor);
1548 JSHandle<JSTaggedValue> extraInfoValue(thread, function->GetFunctionExtraInfo());
1549 if (!extraInfoValue->IsJSNativePointer()) {
1550 return JSTaggedValue::False();
1551 }
1552 JSHandle<JSNativePointer> extraInfo(extraInfoValue);
1553 // vm
1554 Region *region = Region::ObjectAddressToRange(extraInfo.GetTaggedValue().GetTaggedObject());
1555 if (region == nullptr) {
1556 return JSTaggedValue::False();
1557 }
1558 EcmaVM *vm = thread->GetEcmaVM();
1559 // data
1560 void *data = extraInfo->GetData();
1561 // callBack
1562 FunctionCallback nativeFunc = reinterpret_cast<FunctionCallback>(extraInfo->GetExternalPointer());
1563
1564 // constructor
1565 JSHandle<JSTaggedValue> thisValue(BuiltinsBase::GetConstructor(info));
1566
1567 // arguments
1568 std::vector<Local<JSValueRef>> arguments;
1569 uint32_t length = info->GetArgsNumber();
1570 for (uint32_t i = 0; i < length; ++i) {
1571 arguments.emplace_back(JSNApiHelper::ToLocal<JSValueRef>(BuiltinsBase::GetCallArg(info, i)));
1572 }
1573
1574 Local<JSValueRef> result = nativeFunc(vm,
1575 JSNApiHelper::ToLocal<JSValueRef>(thisValue),
1576 arguments.data(),
1577 arguments.size(),
1578 data);
1579 return JSNApiHelper::ToJSHandle(result).GetTaggedValue();
1580 }
1581
RegisterCallbackWithNewTarget(ecmascript::EcmaRuntimeCallInfo * info)1582 JSTaggedValue Callback::RegisterCallbackWithNewTarget(ecmascript::EcmaRuntimeCallInfo *info)
1583 {
1584 // Constructor
1585 JSThread *thread = info->GetThread();
1586 JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(info);
1587 if (!constructor->IsJSFunction()) {
1588 return JSTaggedValue::False();
1589 }
1590 JSHandle<JSFunction> function(constructor);
1591 JSHandle<JSTaggedValue> extraInfoValue(thread, function->GetFunctionExtraInfo());
1592 if (!extraInfoValue->IsJSNativePointer()) {
1593 return JSTaggedValue::False();
1594 }
1595 JSHandle<JSNativePointer> extraInfo(extraInfoValue);
1596 // vm
1597 Region *region = Region::ObjectAddressToRange(extraInfo.GetTaggedValue().GetTaggedObject());
1598 if (region == nullptr) {
1599 return JSTaggedValue::False();
1600 }
1601 EcmaVM *vm = thread->GetEcmaVM();
1602 // data
1603 void *data = extraInfo->GetData();
1604 // callBack
1605 FunctionCallbackWithNewTarget nativeFunc =
1606 reinterpret_cast<FunctionCallbackWithNewTarget>(extraInfo->GetExternalPointer());
1607
1608 // newTarget
1609 JSHandle<JSTaggedValue> newTarget(BuiltinsBase::GetNewTarget(info));
1610
1611 // this
1612 JSHandle<JSTaggedValue> thisValue(BuiltinsBase::GetThis(info));
1613
1614 // arguments
1615 std::vector<Local<JSValueRef>> arguments;
1616 uint32_t length = info->GetArgsNumber();
1617 for (uint32_t i = 0; i < length; ++i) {
1618 arguments.emplace_back(JSNApiHelper::ToLocal<JSValueRef>(BuiltinsBase::GetCallArg(info, i)));
1619 }
1620
1621 Local<JSValueRef> result = nativeFunc(vm,
1622 JSNApiHelper::ToLocal<JSValueRef>(thisValue),
1623 JSNApiHelper::ToLocal<JSValueRef>(newTarget),
1624 arguments.data(),
1625 arguments.size(),
1626 data);
1627 return JSNApiHelper::ToJSHandle(result).GetTaggedValue();
1628 }
1629
1630 // ------------------------------------- JSExecutionScope ------------------------------
JSExecutionScope(const EcmaVM * vm)1631 JSExecutionScope::JSExecutionScope(const EcmaVM *vm)
1632 {
1633 (void)vm;
1634 }
1635
~JSExecutionScope()1636 JSExecutionScope::~JSExecutionScope()
1637 {
1638 last_current_thread_ = nullptr;
1639 is_revert_ = false;
1640 }
1641
1642 // ----------------------------------- JSValueRef --------------------------------------
Undefined(const EcmaVM * vm)1643 Local<PrimitiveRef> JSValueRef::Undefined(const EcmaVM *vm)
1644 {
1645 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Undefined()));
1646 }
1647
Null(const EcmaVM * vm)1648 Local<PrimitiveRef> JSValueRef::Null(const EcmaVM *vm)
1649 {
1650 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Null()));
1651 }
1652
True(const EcmaVM * vm)1653 Local<PrimitiveRef> JSValueRef::True(const EcmaVM *vm)
1654 {
1655 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::True()));
1656 }
1657
False(const EcmaVM * vm)1658 Local<PrimitiveRef> JSValueRef::False(const EcmaVM *vm)
1659 {
1660 return JSNApiHelper::ToLocal<PrimitiveRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::False()));
1661 }
1662
Exception(const EcmaVM * vm)1663 Local<JSValueRef> JSValueRef::Exception(const EcmaVM *vm)
1664 {
1665 return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(vm->GetJSThread(), JSTaggedValue::Exception()));
1666 }
1667
ToObject(const EcmaVM * vm)1668 Local<ObjectRef> JSValueRef::ToObject(const EcmaVM *vm)
1669 {
1670 JSThread *thread = vm->GetJSThread();
1671 if (IsUndefined() || IsNull()) {
1672 return Exception(vm);
1673 }
1674 JSHandle<JSTaggedValue> obj(JSTaggedValue::ToObject(thread, JSNApiHelper::ToJSHandle(this)));
1675 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1676 return JSNApiHelper::ToLocal<ObjectRef>(obj);
1677 }
1678
ToString(const EcmaVM * vm)1679 Local<StringRef> JSValueRef::ToString(const EcmaVM *vm)
1680 {
1681 JSThread *thread = vm->GetJSThread();
1682 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1683 if (!obj->IsString()) {
1684 obj = JSHandle<JSTaggedValue>(JSTaggedValue::ToString(thread, obj));
1685 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1686 }
1687 return JSNApiHelper::ToLocal<StringRef>(obj);
1688 }
1689
ToNativePointer(const EcmaVM * vm)1690 Local<NativePointerRef> JSValueRef::ToNativePointer(const EcmaVM *vm)
1691 {
1692 JSThread *thread = vm->GetJSThread();
1693 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1694 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1695 return JSNApiHelper::ToLocal<NativePointerRef>(obj);
1696 }
1697
BooleaValue()1698 bool JSValueRef::BooleaValue()
1699 {
1700 return JSNApiHelper::ToJSTaggedValue(this).ToBoolean();
1701 }
1702
IntegerValue(const EcmaVM * vm)1703 int64_t JSValueRef::IntegerValue(const EcmaVM *vm)
1704 {
1705 JSThread *thread = vm->GetJSThread();
1706 JSTaggedNumber number = JSTaggedValue::ToInteger(thread, JSNApiHelper::ToJSHandle(this));
1707 RETURN_VALUE_IF_ABRUPT(thread, 0);
1708 return number.GetNumber();
1709 }
1710
Uint32Value(const EcmaVM * vm)1711 uint32_t JSValueRef::Uint32Value(const EcmaVM *vm)
1712 {
1713 JSThread *thread = vm->GetJSThread();
1714 uint32_t number = JSTaggedValue::ToUint32(thread, JSNApiHelper::ToJSHandle(this));
1715 RETURN_VALUE_IF_ABRUPT(thread, 0);
1716 return number;
1717 }
1718
Int32Value(const EcmaVM * vm)1719 int32_t JSValueRef::Int32Value(const EcmaVM *vm)
1720 {
1721 JSThread *thread = vm->GetJSThread();
1722 int32_t number = JSTaggedValue::ToInt32(thread, JSNApiHelper::ToJSHandle(this));
1723 RETURN_VALUE_IF_ABRUPT(thread, 0);
1724 return number;
1725 }
1726
ToBoolean(const EcmaVM * vm)1727 Local<BooleanRef> JSValueRef::ToBoolean(const EcmaVM *vm)
1728 {
1729 JSThread *thread = vm->GetJSThread();
1730 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1731 JSHandle<JSTaggedValue> booleanObj = JSHandle<JSTaggedValue>(thread, JSTaggedValue(obj->ToBoolean()));
1732 return JSNApiHelper::ToLocal<BooleanRef>(booleanObj);
1733 }
1734
ToNumber(const EcmaVM * vm)1735 Local<NumberRef> JSValueRef::ToNumber(const EcmaVM *vm)
1736 {
1737 JSThread *thread = vm->GetJSThread();
1738 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1739 JSHandle<JSTaggedValue> number(thread, JSTaggedValue::ToNumber(thread, obj));
1740 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Exception(vm));
1741 return JSNApiHelper::ToLocal<NumberRef>(number);
1742 }
1743
IsStrictEquals(const EcmaVM * vm,Local<JSValueRef> value)1744 bool JSValueRef::IsStrictEquals(const EcmaVM *vm, Local<JSValueRef> value)
1745 {
1746 JSThread *thread = vm->GetJSThread();
1747 JSHandle<JSTaggedValue> xValue = JSNApiHelper::ToJSHandle(this);
1748 JSHandle<JSTaggedValue> yValue = JSNApiHelper::ToJSHandle(value);
1749 return JSTaggedValue::StrictEqual(thread, xValue, yValue);
1750 }
1751
Typeof(const EcmaVM * vm)1752 Local<StringRef> JSValueRef::Typeof(const EcmaVM *vm)
1753 {
1754 JSThread *thread = vm->GetJSThread();
1755 JSTaggedValue value = FastRuntimeStub::FastTypeOf(thread, JSNApiHelper::ToJSTaggedValue(this));
1756 return JSNApiHelper::ToLocal<StringRef>(JSHandle<JSTaggedValue>(thread, value));
1757 }
1758
InstanceOf(const EcmaVM * vm,Local<JSValueRef> value)1759 bool JSValueRef::InstanceOf(const EcmaVM *vm, Local<JSValueRef> value)
1760 {
1761 JSThread *thread = vm->GetJSThread();
1762 JSHandle<JSTaggedValue> origin = JSNApiHelper::ToJSHandle(this);
1763 JSHandle<JSTaggedValue> target = JSNApiHelper::ToJSHandle(value);
1764 bool result = JSObject::InstanceOf(thread, origin, target);
1765 RETURN_VALUE_IF_ABRUPT(thread, false);
1766 return result;
1767 }
1768
IsUndefined()1769 bool JSValueRef::IsUndefined()
1770 {
1771 return JSNApiHelper::ToJSTaggedValue(this).IsUndefined();
1772 }
1773
IsNull()1774 bool JSValueRef::IsNull()
1775 {
1776 return JSNApiHelper::ToJSTaggedValue(this).IsNull();
1777 }
1778
IsHole()1779 bool JSValueRef::IsHole()
1780 {
1781 return JSNApiHelper::ToJSTaggedValue(this).IsHole();
1782 }
1783
IsTrue()1784 bool JSValueRef::IsTrue()
1785 {
1786 return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
1787 }
1788
IsFalse()1789 bool JSValueRef::IsFalse()
1790 {
1791 return JSNApiHelper::ToJSTaggedValue(this).IsFalse();
1792 }
1793
IsNumber()1794 bool JSValueRef::IsNumber()
1795 {
1796 return JSNApiHelper::ToJSTaggedValue(this).IsNumber();
1797 }
1798
IsBigInt()1799 bool JSValueRef::IsBigInt()
1800 {
1801 return JSNApiHelper::ToJSTaggedValue(this).IsBigInt();
1802 }
1803
IsInt()1804 bool JSValueRef::IsInt()
1805 {
1806 return JSNApiHelper::ToJSTaggedValue(this).IsInt();
1807 }
1808
WithinInt32()1809 bool JSValueRef::WithinInt32()
1810 {
1811 return JSNApiHelper::ToJSTaggedValue(this).WithinInt32();
1812 }
1813
IsBoolean()1814 bool JSValueRef::IsBoolean()
1815 {
1816 return JSNApiHelper::ToJSTaggedValue(this).IsBoolean();
1817 }
1818
IsString()1819 bool JSValueRef::IsString()
1820 {
1821 return JSNApiHelper::ToJSTaggedValue(this).IsString();
1822 }
1823
IsSymbol()1824 bool JSValueRef::IsSymbol()
1825 {
1826 return JSNApiHelper::ToJSTaggedValue(this).IsSymbol();
1827 }
1828
IsObject()1829 bool JSValueRef::IsObject()
1830 {
1831 return JSNApiHelper::ToJSTaggedValue(this).IsECMAObject();
1832 }
1833
IsArray(const EcmaVM * vm)1834 bool JSValueRef::IsArray(const EcmaVM *vm)
1835 {
1836 JSThread *thread = vm->GetJSThread();
1837 return JSNApiHelper::ToJSTaggedValue(this).IsArray(thread);
1838 }
1839
IsConstructor()1840 bool JSValueRef::IsConstructor()
1841 {
1842 JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
1843 return value.IsHeapObject() && value.IsConstructor();
1844 }
1845
IsFunction()1846 bool JSValueRef::IsFunction()
1847 {
1848 JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
1849 return value.IsHeapObject() && value.IsCallable();
1850 }
1851
IsProxy()1852 bool JSValueRef::IsProxy()
1853 {
1854 return JSNApiHelper::ToJSTaggedValue(this).IsJSProxy();
1855 }
1856
IsException()1857 bool JSValueRef::IsException()
1858 {
1859 return JSNApiHelper::ToJSTaggedValue(this).IsException();
1860 }
1861
IsPromise()1862 bool JSValueRef::IsPromise()
1863 {
1864 return JSNApiHelper::ToJSTaggedValue(this).IsJSPromise();
1865 }
1866
IsDataView()1867 bool JSValueRef::IsDataView()
1868 {
1869 return JSNApiHelper::ToJSTaggedValue(this).IsDataView();
1870 }
1871
IsTypedArray()1872 bool JSValueRef::IsTypedArray()
1873 {
1874 return JSNApiHelper::ToJSTaggedValue(this).IsTypedArray();
1875 }
1876
IsNativePointer()1877 bool JSValueRef::IsNativePointer()
1878 {
1879 return JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer();
1880 }
1881
IsDate()1882 bool JSValueRef::IsDate()
1883 {
1884 return JSNApiHelper::ToJSTaggedValue(this).IsDate();
1885 }
1886
IsError()1887 bool JSValueRef::IsError()
1888 {
1889 return JSNApiHelper::ToJSTaggedValue(this).IsJSError();
1890 }
1891
IsMap()1892 bool JSValueRef::IsMap()
1893 {
1894 return JSNApiHelper::ToJSTaggedValue(this).IsJSMap();
1895 }
1896
IsSet()1897 bool JSValueRef::IsSet()
1898 {
1899 return JSNApiHelper::ToJSTaggedValue(this).IsJSSet();
1900 }
1901
IsWeakMap()1902 bool JSValueRef::IsWeakMap()
1903 {
1904 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakMap();
1905 }
1906
IsWeakSet()1907 bool JSValueRef::IsWeakSet()
1908 {
1909 return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakSet();
1910 }
1911
IsRegExp()1912 bool JSValueRef::IsRegExp()
1913 {
1914 return JSNApiHelper::ToJSTaggedValue(this).IsJSRegExp();
1915 }
1916
IsArrayIterator()1917 bool JSValueRef::IsArrayIterator()
1918 {
1919 return JSNApiHelper::ToJSTaggedValue(this).IsJSArrayIterator();
1920 }
1921
IsStringIterator()1922 bool JSValueRef::IsStringIterator()
1923 {
1924 return JSNApiHelper::ToJSTaggedValue(this).IsStringIterator();
1925 }
1926
IsSetIterator()1927 bool JSValueRef::IsSetIterator()
1928 {
1929 return JSNApiHelper::ToJSTaggedValue(this).IsJSSetIterator();
1930 }
1931
IsMapIterator()1932 bool JSValueRef::IsMapIterator()
1933 {
1934 return JSNApiHelper::ToJSTaggedValue(this).IsJSMapIterator();
1935 }
1936
IsArrayBuffer()1937 bool JSValueRef::IsArrayBuffer()
1938 {
1939 return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer();
1940 }
1941
IsUint8Array()1942 bool JSValueRef::IsUint8Array()
1943 {
1944 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8Array();
1945 }
1946
IsInt8Array()1947 bool JSValueRef::IsInt8Array()
1948 {
1949 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt8Array();
1950 }
1951
IsUint8ClampedArray()1952 bool JSValueRef::IsUint8ClampedArray()
1953 {
1954 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8ClampedArray();
1955 }
1956
IsInt16Array()1957 bool JSValueRef::IsInt16Array()
1958 {
1959 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt16Array();
1960 }
1961
IsUint16Array()1962 bool JSValueRef::IsUint16Array()
1963 {
1964 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint16Array();
1965 }
1966
IsInt32Array()1967 bool JSValueRef::IsInt32Array()
1968 {
1969 return JSNApiHelper::ToJSTaggedValue(this).IsJSInt32Array();
1970 }
1971
IsUint32Array()1972 bool JSValueRef::IsUint32Array()
1973 {
1974 return JSNApiHelper::ToJSTaggedValue(this).IsJSUint32Array();
1975 }
1976
IsFloat32Array()1977 bool JSValueRef::IsFloat32Array()
1978 {
1979 return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat32Array();
1980 }
1981
IsFloat64Array()1982 bool JSValueRef::IsFloat64Array()
1983 {
1984 return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat64Array();
1985 }
1986
IsJSPrimitiveRef()1987 bool JSValueRef::IsJSPrimitiveRef()
1988 {
1989 return JSNApiHelper::ToJSTaggedValue(this).IsJSPrimitiveRef();
1990 }
1991
IsJSPrimitiveNumber()1992 bool JSValueRef::IsJSPrimitiveNumber()
1993 {
1994 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
1995 return JSPrimitiveRef::Cast(obj->GetHeapObject())->IsNumber();
1996 }
1997
IsJSPrimitiveInt()1998 bool JSValueRef::IsJSPrimitiveInt()
1999 {
2000 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2001 return JSPrimitiveRef::Cast(obj->GetHeapObject())->IsInt();
2002 }
2003
IsJSPrimitiveBoolean()2004 bool JSValueRef::IsJSPrimitiveBoolean()
2005 {
2006 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2007 return JSPrimitiveRef::Cast(obj->GetHeapObject())->IsBoolean();
2008 }
2009
IsJSPrimitiveString()2010 bool JSValueRef::IsJSPrimitiveString()
2011 {
2012 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2013 return JSPrimitiveRef::Cast(obj->GetHeapObject())->IsString();
2014 }
2015
IsJSPrimitiveSymbol()2016 bool JSValueRef::IsJSPrimitiveSymbol()
2017 {
2018 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2019 return JSPrimitiveRef::Cast(obj->GetHeapObject())->IsSymbol();
2020 }
2021
IsGeneratorObject()2022 bool JSValueRef::IsGeneratorObject()
2023 {
2024 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2025 bool rst = obj->IsGeneratorObject();
2026 return rst;
2027 }
2028
IsAsyncFunction()2029 bool JSValueRef::IsAsyncFunction()
2030 {
2031 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2032 bool rst = obj->IsJSAsyncFunction();
2033 return rst;
2034 }
2035
IsArgumentsObject()2036 bool JSValueRef::IsArgumentsObject()
2037 {
2038 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2039 bool rst = obj->IsArguments();
2040 return rst;
2041 }
2042
IsGeneratorFunction()2043 bool JSValueRef::IsGeneratorFunction()
2044 {
2045 JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
2046 bool rst = obj->IsGeneratorFunction();
2047 return rst;
2048 }
StartCpuProfiler(const EcmaVM * vm,const std::string & fileName)2049 void JSNApi::StartCpuProfiler(const EcmaVM *vm, const std::string &fileName)
2050 {
2051 panda::ecmascript::CpuProfiler* singleton = panda::ecmascript::CpuProfiler::GetInstance();
2052 singleton->StartCpuProfiler(vm, fileName);
2053 }
2054
StopCpuProfiler()2055 void JSNApi::StopCpuProfiler()
2056 {
2057 panda::ecmascript::CpuProfiler* singleton = panda::ecmascript::CpuProfiler::GetInstance();
2058 singleton->StopCpuProfiler();
2059 if (singleton != nullptr) {
2060 delete singleton;
2061 singleton = nullptr;
2062 }
2063 }
2064
SuspendVM(const EcmaVM * vm)2065 bool JSNApi::SuspendVM(const EcmaVM *vm)
2066 {
2067 ecmascript::JSThread* thread = vm->GetJSThreadNoCheck();
2068 return thread->NotifyVMThreadSuspension();
2069 }
2070
ResumeVM(const EcmaVM * vm)2071 void JSNApi::ResumeVM(const EcmaVM *vm)
2072 {
2073 ecmascript::JSThread* thread = vm->GetJSThreadNoCheck();
2074 thread->ResumeVM();
2075 }
2076
IsSuspended(const EcmaVM * vm)2077 bool JSNApi::IsSuspended(const EcmaVM *vm)
2078 {
2079 ecmascript::JSThread* thread = vm->GetJSThreadNoCheck();
2080 return thread->IsSuspended();
2081 }
2082
CheckSafepoint(const EcmaVM * vm)2083 bool JSNApi::CheckSafepoint(const EcmaVM *vm)
2084 {
2085 ecmascript::JSThread* thread = vm->GetJSThread();
2086 return thread->CheckSafepoint();
2087 }
2088 } // namespace panda
2089