* Copyright (c) 2021-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cinttypes>
#include "ecmascript/base/json_stringifier.h"
#include "ecmascript/base/typed_array_helper-inl.h"
#include "ecmascript/builtins/builtins_object.h"
#include "ecmascript/shared_objects/concurrent_api_scope.h"
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
#include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
#endif
#include "ecmascript/checkpoint/thread_state_transition.h"
#include "ecmascript/ecma_global_storage.h"
#include "ecmascript/ic/ic_info.h"
#include "ecmascript/interpreter/fast_runtime_stub-inl.h"
#include "ecmascript/interpreter/interpreter_assembly.h"
#include "ecmascript/jsnapi_sendable.h"
#include "ecmascript/jspandafile/js_pandafile_executor.h"
#include "ecmascript/js_hclass.h"
#include "ecmascript/lexical_env.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/mem/idle_gc_trigger.h"
#include "ecmascript/module/module_logger.h"
#include "ecmascript/module/napi_module_loader.h"
#include "ecmascript/napi/jsnapi_class_creation_helper.h"
#include "ecmascript/ohos/adapter/modulemanager/module_pkg_parser.h"
#include "ecmascript/ohos/js_pandafile_snapshot_interfaces.h"
#include "ecmascript/ohos/constpool_snapshot_interfaces.h"
#include "ecmascript/ohos/module_snapshot_interfaces.h"
#include "ecmascript/ohos/ohos_constants.h"
#include "ecmascript/ohos/aot_runtime_info.h"
#if defined(ENABLE_EXCEPTION_BACKTRACE)
#include "ecmascript/platform/backtrace.h"
#endif
#include "ecmascript/regexp/regexp_parser.h"
#include "ecmascript/serializer/base_deserializer.h"
#include "ecmascript/serializer/inter_op_value_deserializer.h"
#include "ecmascript/serializer/inter_op_value_serializer.h"
#include "ecmascript/serializer/value_serializer.h"
#include "ecmascript/platform/aot_crash_info.h"
#include "ecmascript/platform/dfx_crash_obj.h"
#ifdef ARK_SUPPORT_INTL
#include "ecmascript/js_bigint.h"
#include "ecmascript/js_collator.h"
#include "ecmascript/js_date_time_format.h"
#include "ecmascript/js_number_format.h"
#endif
#if defined(ENABLE_LOCAL_HANDLE_LEAK_DETECT)
#include "ecmascript/dfx/hprof/heap_profiler.h"
#endif
namespace panda {
using ecmascript::AccessorData;
using ecmascript::BigInt;
using ecmascript::ByteArray;
using ecmascript::DataViewType;
using ecmascript::ECMAObject;
using ecmascript::EcmaRuntimeCallInfo;
using ecmascript::EcmaString;
using ecmascript::EcmaStringAccessor;
using ecmascript::ErrorType;
using ecmascript::FastRuntimeStub;
using ecmascript::GeneratorContext;
using ecmascript::GlobalEnv;
using ecmascript::GlobalEnvConstants;
using ecmascript::IterationKind;
using ecmascript::JSArray;
using ecmascript::JSArrayBuffer;
using ecmascript::JSDataView;
using ecmascript::JSDate;
using ecmascript::JSFunction;
using ecmascript::JSFunctionBase;
using ecmascript::JSGeneratorFunction;
using ecmascript::JSGeneratorObject;
using ecmascript::JSGeneratorState;
using ecmascript::JSHClass;
using ecmascript::JSIterator;
using ecmascript::JSMap;
using ecmascript::JSMapIterator;
using ecmascript::JSNapiSendable;
using ecmascript::JSNativePointer;
using ecmascript::JSObject;
using ecmascript::JSPandaFile;
using ecmascript::JSPandaFileManager;
using ecmascript::JSPrimitiveRef;
using ecmascript::JSPromise;
using ecmascript::JSProxy;
using ecmascript::ObjectFastOperator;
using ecmascript::JSRegExp;
using ecmascript::JSRuntimeOptions;
using ecmascript::JSSet;
using ecmascript::JSSetIterator;
using ecmascript::JSSymbol;
using ecmascript::JSTaggedNumber;
using ecmascript::JSTaggedType;
using ecmascript::JSTaggedValue;
using ecmascript::JSThread;
using ecmascript::JSType;
using ecmascript::JSTypedArray;
using ecmascript::JSNApiClassCreationHelper;
using ecmascript::LinkedHashMap;
using ecmascript::LinkedHashSet;
using ecmascript::LockHolder;
using ecmascript::MemMapAllocator;
using ecmascript::Method;
using ecmascript::NativeModuleFailureInfo;
using ecmascript::ObjectFactory;
using ecmascript::OperationResult;
using ecmascript::PromiseCapability;
using ecmascript::PropertyDescriptor;
using ecmascript::Region;
using ecmascript::ICInfo;
using ecmascript::ICKind;
using ecmascript::NapiICInfo;
using ecmascript::TaggedArray;
using ecmascript::WeakLinkedHashMap;
using ecmascript::base::BuiltinsBase;
using ecmascript::base::JsonStringifier;
using ecmascript::SharedHeap;
using ecmascript::base::StringHelper;
using ecmascript::base::TypedArrayHelper;
using ecmascript::base::Utf16JsonParser;
using ecmascript::base::Utf8JsonParser;
using ecmascript::builtins::BuiltinsObject;
using ecmascript::job::MicroJobQueue;
using ecmascript::job::QueueType;
#ifdef ARK_SUPPORT_INTL
using ecmascript::JSCollator;
using ecmascript::JSDateTimeFormat;
using ecmascript::JSNumberFormat;
#endif
using ecmascript::DebugInfoExtractor;
using ecmascript::JSWeakMap;
using ecmascript::JSWeakSet;
using ecmascript::RegExpParser;
using ecmascript::base::NumberHelper;
template <typename T>
using JSHandle = ecmascript::JSHandle<T>;
template <typename T>
using JSMutableHandle = ecmascript::JSMutableHandle<T>;
using PathHelper = ecmascript::base::PathHelper;
using ModulePathHelper = ecmascript::ModulePathHelper;
using JsDebuggerManager = ecmascript::tooling::JsDebuggerManager;
using FrameIterator = ecmascript::FrameIterator;
using Concurrent = ecmascript::Concurrent;
using EnableAotJitListHelper = ecmascript::ohos::EnableAotJitListHelper;
using PGOProfilerManager = ecmascript::pgo::PGOProfilerManager;
using AotRuntimeInfo = ecmascript::ohos::AotRuntimeInfo;
#if defined(ENABLE_LOCAL_HANDLE_LEAK_DETECT)
using HeapProfiler = ecmascript::HeapProfiler;
using HeapProfilerInterface = ecmascript::HeapProfilerInterface;
#endif
namespace {
constexpr std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0";
}
bool JSNApi::isForked_ = false;
static ecmascript::Mutex *mutex = new panda::ecmascript::Mutex();
StartIdleMonitorCallback JSNApi::startIdleMonitorCallback_ = nullptr;
const static uint32_t API_VERSION_MASK = 100;
constexpr size_t FORMATED_FUNCPTR_LENGTH = 36;
ArkCrashHolder::~ArkCrashHolder()
{
ecmascript::ResetCrashObject(handle_);
if (data_ != nullptr) {
delete [] data_;
data_ = nullptr;
}
}
void ArkCrashHolder::SetCrashObj(const char* tag, const char* info)
{
std::string data = "[";
data += tag,
data += "] Crash occurred on ";
data += info;
data += ", callback: ";
size_ = data.length();
const size_t bufSize = size_ + FORMATED_FUNCPTR_LENGTH;
data_ = new char[bufSize];
if (memcpy_s(data_, bufSize, data.c_str(), size_) != EOK) {
LOG_FULL(WARN) << "Failed to init crash holder.";
size_ = 0;
data_[0] = '\0';
};
handle_ = ecmascript::SetCrashObject(ecmascript::DFXObjectType::STRING, reinterpret_cast<uintptr_t>(data_));
}
void ArkCrashHolder::UpdateCallbackPtr(uintptr_t addr)
{
if (sprintf_s(data_ + size_, FORMATED_FUNCPTR_LENGTH, "%" PRIuPTR, addr) < 0) {
LOG_FULL(ERROR) << "Failed to update callback info: " << addr;
}
}
#undef ENABLE_DFX_CRASH_OBJECT
Local<PrimitiveRef> JSValueRef::Undefined(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<PrimitiveRef>(
vm->GetJSThread()->GlobalConstants()->GetHandledUndefined());
}
Local<PrimitiveRef> JSValueRef::Null(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<PrimitiveRef>(
vm->GetJSThread()->GlobalConstants()->GetHandledNull());
}
Local<PrimitiveRef> JSValueRef::Hole(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<PrimitiveRef>(
vm->GetJSThread()->GlobalConstants()->GetHandledHole());
}
Local<PrimitiveRef> JSValueRef::True(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<PrimitiveRef>(
vm->GetJSThread()->GlobalConstants()->GetHandledTrue());
}
Local<PrimitiveRef> JSValueRef::False(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<PrimitiveRef>(
vm->GetJSThread()->GlobalConstants()->GetHandledFalse());
}
Local<ObjectRef> JSValueRef::ToObject(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
if (IsUndefined() || IsNull()) {
return Undefined(vm);
}
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj(JSTaggedValue::ToObject(thread, JSNApiHelper::ToJSHandle(this)));
LOG_IF_SPECIAL(obj, ERROR);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<ObjectRef>(obj);
}
Local<ObjectRef> JSValueRef::ToEcmaObject(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
if (obj->IsECMAObject()) {
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<ObjectRef>(obj);
}
return Undefined(vm);
}
Local<ObjectRef> JSValueRef::ToEcmaObjectWithoutSwitchState(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<ObjectRef>(obj);
}
Local<StringRef> JSValueRef::ToString(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
if (!obj->IsString()) {
obj = JSHandle<JSTaggedValue>(JSTaggedValue::ToString(thread, obj));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
}
return JSNApiHelper::ToLocal<StringRef>(obj);
}
Local<NativePointerRef> JSValueRef::ToNativePointer(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
return JSNApiHelper::ToLocal<NativePointerRef>(obj);
}
bool JSValueRef::BooleaValue(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).ToBoolean();
}
int64_t JSValueRef::IntegerValue(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> tagged = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(tagged, ERROR);
if (tagged->IsNumber()) {
if (!NumberHelper::IsFinite(tagged.GetTaggedValue()) || NumberHelper::IsNaN(tagged.GetTaggedValue())) {
return 0;
} else {
return NumberHelper::DoubleToInt64(tagged->GetNumber());
}
}
JSTaggedNumber number = JSTaggedValue::ToInteger(thread, tagged);
RETURN_VALUE_IF_ABRUPT(thread, 0);
return NumberHelper::DoubleToInt64(number.GetNumber());
}
uint32_t JSValueRef::Uint32Value(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> tagged = JSNApiHelper::ToJSHandle(this);
uint32_t number = 0;
if (!tagged->IsECMAObject()) {
number = JSTaggedValue::ToUint32(thread, tagged);
} else {
number = JSTaggedValue::ToUint32(thread, tagged);
}
RETURN_VALUE_IF_ABRUPT(thread, 0);
return number;
}
int32_t JSValueRef::Int32Value(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> tagged = JSNApiHelper::ToJSHandle(this);
int32_t number = 0;
if (!tagged->IsECMAObject()) {
number = JSTaggedValue::ToInt32(thread, tagged);
} else {
number = JSTaggedValue::ToInt32(thread, tagged);
}
RETURN_VALUE_IF_ABRUPT(thread, 0);
return number;
}
double JSValueRef::GetValueDouble(bool &isNumber)
{
JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
if (value.IsInt()) {
isNumber = true;
return static_cast<double>(value.GetInt());
}
if (value.IsDouble()) {
isNumber = true;
return value.GetDouble();
}
isNumber = false;
return 0.0;
}
int32_t JSValueRef::GetValueInt32(bool &isNumber)
{
JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
if (value.IsInt()) {
isNumber = true;
return value.GetInt();
}
if (value.IsDouble()) {
isNumber = true;
return static_cast<int32_t>(ecmascript::base::NumberHelper::DoubleToInt(value.GetDouble(),
ecmascript::base::INT32_BITS));
}
isNumber = false;
return 0;
}
uint32_t JSValueRef::GetValueUint32(bool &isNumber)
{
return static_cast<uint32_t>(GetValueInt32(isNumber));
}
int64_t JSValueRef::GetValueInt64(bool &isNumber)
{
JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
if (value.IsInt()) {
isNumber = true;
return static_cast<int64_t>(value.GetInt());
}
if (value.IsDouble()) {
isNumber = true;
double getVale = value.GetDouble();
if (!std::isfinite(getVale) || std::isnan(getVale)) {
return 0;
}
return NumberHelper::DoubleToInt64(getVale);
}
isNumber = false;
return 0;
}
bool JSValueRef::GetValueBool(bool &isBool)
{
JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
if (value.IsTrue()) {
isBool = true;
return true;
}
if (value.IsFalse()) {
isBool = true;
return false;
}
isBool = false;
return false;
}
Local<BooleanRef> JSValueRef::ToBoolean(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> booleanObj(thread, JSTaggedValue(obj->ToBoolean()));
return JSNApiHelper::ToLocal<BooleanRef>(booleanObj);
}
Local<BigIntRef> JSValueRef::ToBigInt(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> bigIntObj(thread, JSTaggedValue::ToBigInt(thread, obj));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<BigIntRef>(bigIntObj);
}
Local<NumberRef> JSValueRef::ToNumber(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> number(thread, JSTaggedValue::ToNumber(thread, obj));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<NumberRef>(number);
}
bool JSValueRef::IsStrictEquals(const EcmaVM *vm, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> xValue = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(xValue, ERROR);
JSHandle<JSTaggedValue> yValue = JSNApiHelper::ToJSHandle(value);
return JSTaggedValue::StrictEqual(thread, xValue, yValue);
}
Local<StringRef> JSValueRef::Typeof(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue value = FastRuntimeStub::FastTypeOf(thread, JSNApiHelper::ToJSTaggedValue(this));
return JSNApiHelper::ToLocal<StringRef>(JSHandle<JSTaggedValue>(thread, value));
}
bool JSValueRef::InstanceOf(const EcmaVM *vm, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> origin = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(origin, ERROR);
JSHandle<JSTaggedValue> target = JSNApiHelper::ToJSHandle(value);
return JSObject::InstanceOf(thread, origin, target);
}
bool JSValueRef::IsUndefined()
{
return JSNApiHelper::ToJSTaggedValue(this).IsUndefined();
}
bool JSValueRef::IsNull()
{
return JSNApiHelper::ToJSTaggedValue(this).IsNull();
}
bool JSValueRef::IsHole()
{
return JSNApiHelper::ToJSTaggedValue(this).IsHole();
}
bool JSValueRef::IsTrue()
{
return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
}
bool JSValueRef::IsFalse()
{
return JSNApiHelper::ToJSTaggedValue(this).IsFalse();
}
bool JSValueRef::IsNumber()
{
return JSNApiHelper::ToJSTaggedValue(this).IsNumber();
}
bool JSValueRef::IsBigInt(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsBigInt();
}
bool JSValueRef::IsInt()
{
return JSNApiHelper::ToJSTaggedValue(this).IsInt();
}
bool JSValueRef::WithinInt32()
{
return JSNApiHelper::ToJSTaggedValue(this).WithinInt32();
}
bool JSValueRef::IsBoolean()
{
return JSNApiHelper::ToJSTaggedValue(this).IsBoolean();
}
bool JSValueRef::IsString(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsString();
}
bool JSValueRef::IsStringWithoutSwitchState(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
return JSNApiHelper::ToJSTaggedValue(this).IsString();
}
bool JSValueRef::IsSymbol(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsSymbol();
}
bool JSValueRef::IsObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsECMAObject();
}
bool JSValueRef::IsObjectWithoutSwitchState(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
return JSNApiHelper::ToJSTaggedValue(this).IsECMAObject();
}
bool JSValueRef::IsNativeBindingObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSTaggedValue object = JSNApiHelper::ToJSTaggedValue(this);
if (!object.IsECMAObject()) {
return false;
}
return object.GetTaggedObject()->GetClass()->IsNativeBindingObject();
}
bool JSValueRef::IsArray(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsArray(thread);
}
bool JSValueRef::IsJSArray(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSArray();
}
bool JSValueRef::IsConstructor(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
return value.IsHeapObject() && value.IsConstructor();
}
bool JSValueRef::IsFunction(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
return value.IsCallable();
}
bool JSValueRef::IsJSFunction(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSTaggedValue value = JSNApiHelper::ToJSTaggedValue(this);
return value.IsJSFunction();
}
bool JSValueRef::IsProxy(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSProxy();
}
bool JSValueRef::IsPromise(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSPromise();
}
bool JSValueRef::IsDataView(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsDataView();
}
bool JSValueRef::IsTypedArray(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsTypedArray();
}
bool JSValueRef::IsNativePointer(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer();
}
bool JSValueRef::IsDate(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsDate();
}
bool JSValueRef::IsError(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSError();
}
bool JSValueRef::IsMap(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSMap();
}
bool JSValueRef::IsSet(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSet();
}
bool JSValueRef::IsWeakRef(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakRef();
}
bool JSValueRef::IsWeakMap(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakMap();
}
bool JSValueRef::IsWeakSet(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSWeakSet();
}
bool JSValueRef::IsRegExp(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSRegExp();
}
bool JSValueRef::IsArrayIterator(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSArrayIterator();
}
bool JSValueRef::IsStringIterator(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsStringIterator();
}
bool JSValueRef::IsSetIterator(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSetIterator();
}
bool JSValueRef::IsMapIterator(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSMapIterator();
}
bool JSValueRef::IsArrayBuffer(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer();
}
bool JSValueRef::IsBuffer(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsArrayBuffer();
}
bool JSValueRef::IsUint8Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8Array();
}
bool JSValueRef::IsInt8Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSInt8Array();
}
bool JSValueRef::IsUint8ClampedArray(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSUint8ClampedArray();
}
bool JSValueRef::IsInt16Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSInt16Array();
}
bool JSValueRef::IsUint16Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSUint16Array();
}
bool JSValueRef::IsInt32Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSInt32Array();
}
bool JSValueRef::IsUint32Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSUint32Array();
}
bool JSValueRef::IsFloat32Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat32Array();
}
bool JSValueRef::IsFloat64Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSFloat64Array();
}
bool JSValueRef::IsBigInt64Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSBigInt64Array();
}
bool JSValueRef::IsBigUint64Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSBigUint64Array();
}
bool JSValueRef::IsJSSharedInt8Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedInt8Array();
}
bool JSValueRef::IsJSSharedUint8Array([[maybe_unused]]const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedUint8Array();
}
bool JSValueRef::IsJSSharedUint8ClampedArray([[maybe_unused]]const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedUint8ClampedArray();
}
bool JSValueRef::IsJSSharedInt16Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedInt16Array();
}
bool JSValueRef::IsJSSharedUint16Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedUint16Array();
}
bool JSValueRef::IsJSSharedInt32Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedInt32Array();
}
bool JSValueRef::IsJSSharedFloat32Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedFloat32Array();
}
bool JSValueRef::IsJSSharedUint32Array(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedUint32Array();
}
bool JSValueRef::IsJSPrimitiveRef(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSPrimitiveRef();
}
bool JSValueRef::IsJSPrimitiveNumber(const EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, FATAL);
return IsJSPrimitiveRef(vm) ? JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsNumber(thread) : false;
}
bool JSValueRef::IsJSPrimitiveInt(const EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, FATAL);
return IsJSPrimitiveRef(vm) ? JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsInt(thread) : false;
}
bool JSValueRef::IsJSPrimitiveBoolean(const EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, FATAL);
return IsJSPrimitiveRef(vm) ? JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsBoolean(thread) : false;
}
bool JSValueRef::IsJSPrimitiveString(const EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, FATAL);
return IsJSPrimitiveRef(vm) ? JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsString(thread) : false;
}
bool JSValueRef::IsJSPrimitiveSymbol(const EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, FATAL);
return IsJSPrimitiveRef(vm) ? JSPrimitiveRef::Cast(obj->GetTaggedObject())->IsSymbol(thread) : false;
}
bool JSValueRef::IsGeneratorObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsGeneratorObject();
}
bool JSValueRef::IsModuleNamespaceObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsModuleNamespace();
}
bool JSValueRef::IsNativeModuleFailureInfoObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsNativeModuleFailureInfo();
}
bool JSValueRef::IsSharedArrayBuffer(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsSharedArrayBuffer();
}
bool JSValueRef::IsSendableArrayBuffer(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsSendableArrayBuffer();
}
bool JSValueRef::IsJSLocale(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSLocale();
}
bool JSValueRef::IsJSDateTimeFormat(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSDateTimeFormat();
}
bool JSValueRef::IsJSRelativeTimeFormat(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSRelativeTimeFormat();
}
bool JSValueRef::IsJSIntl(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSIntl();
}
bool JSValueRef::IsJSNumberFormat(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSNumberFormat();
}
bool JSValueRef::IsJSCollator(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSCollator();
}
bool JSValueRef::IsJSPluralRules(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSPluralRules();
}
bool JSValueRef::IsJSListFormat(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSListFormat();
}
bool JSValueRef::IsAsyncGeneratorObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsAsyncGeneratorObject();
}
bool JSValueRef::IsAsyncFunction(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAsyncFunction();
}
bool JSValueRef::IsConcurrentFunction(const EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> funcVal = JSNApiHelper::ToJSHandle(this);
JSHandle<JSFunction> transFunc = JSHandle<JSFunction>::Cast(funcVal);
return transFunc->GetFunctionKind(thread) == ecmascript::FunctionKind::CONCURRENT_FUNCTION;
}
bool JSValueRef::IsArgumentsObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsArguments();
}
bool JSValueRef::IsGeneratorFunction(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsGeneratorFunction();
}
bool JSValueRef::IsAsyncGeneratorFunction(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsAsyncGeneratorFunction();
}
bool JSValueRef::IsArrayList(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIArrayList();
}
bool JSValueRef::IsDeque(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIDeque();
}
bool JSValueRef::IsHashMap(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIHashMap();
}
bool JSValueRef::IsHashSet(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIHashSet();
}
bool JSValueRef::IsLightWeightMap(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILightWeightMap();
}
bool JSValueRef::IsLightWeightSet(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILightWeightSet();
}
bool JSValueRef::IsLinkedList(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILinkedList();
}
bool JSValueRef::IsLinkedListIterator(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPILinkedListIterator();
}
bool JSValueRef::IsList(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIList();
}
bool JSValueRef::IsPlainArray(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIPlainArray();
}
bool JSValueRef::IsQueue(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIQueue();
}
bool JSValueRef::IsStack(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIStack();
}
bool JSValueRef::IsTreeMap(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPITreeMap();
}
bool JSValueRef::IsTreeSet(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPITreeSet();
}
bool JSValueRef::IsVector(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIVector();
}
bool JSValueRef::IsBitVector(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSAPIBitVector();
}
bool JSValueRef::IsSendableObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return IsJSShared(vm) && IsObject(vm);
}
bool JSValueRef::IsJSShared(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSShared();
}
bool JSValueRef::IsSharedArray(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedArray();
}
bool JSValueRef::IsSharedTypedArray(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsSharedTypedArray();
}
bool JSValueRef::IsSharedSet(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedSet();
}
bool JSValueRef::IsSharedMap(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedMap();
}
bool JSValueRef::IsSharedMapIterator(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedMapIterator();
}
bool JSValueRef::IsHeapObject()
{
return JSNApiHelper::ToJSTaggedValue(this).IsHeapObject();
}
void *JSValueRef::GetNativePointerValue(const EcmaVM* vm, bool &isNativePointer)
{
return GetNativePointerValueImpl(vm, isNativePointer);
}
void *JSValueRef::GetNativePointerWrapperDataValue(const EcmaVM* vm, bool &isNativePointer, bool &flag)
{
return GetNativePointerWrapperDataValueImpl(vm, isNativePointer, flag);
}
void *JSValueRef::GetNativePointerWrapperDataValueImpl(const EcmaVM* vm, bool &isNativePointer, bool &isWrapperData)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope managedScope(thread);
if (!JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer()) {
isNativePointer = false;
return nullptr;
}
isNativePointer = true;
JSHandle<JSTaggedValue> nativePointer = JSNApiHelper::ToJSHandle(this);
ecmascript::NativeFlag nativeFlag = JSHandle<JSNativePointer>(nativePointer)->GetNativeFlag();
if (nativeFlag != ecmascript::NativeFlag::WRAPPER_DATA) {
isWrapperData = false;
return nullptr;
}
isWrapperData = true;
return JSHandle<JSNativePointer>(nativePointer)->GetExternalPointer();
}
void *JSValueRef::GetNativePointerValueImpl(const EcmaVM* vm, bool &isNativePointer)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
if (!JSNApiHelper::ToJSTaggedValue(this).IsJSNativePointer()) {
isNativePointer = false;
return nullptr;
}
isNativePointer = true;
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
JSHandle<JSTaggedValue> nativePointer = JSNApiHelper::ToJSHandle(this);
return JSHandle<JSNativePointer>(nativePointer)->GetExternalPointer();
}
bool JSValueRef::IsDetachedArraybuffer(const EcmaVM *vm, bool &isArrayBuffer)
{
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
if (!IsArrayBuffer(vm)) {
isArrayBuffer = false;
return false;
}
isArrayBuffer = true;
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
return arrayBuffer->IsDetach(thread);
}
void JSValueRef::DetachedArraybuffer(const EcmaVM *vm, bool &isArrayBuffer)
{
auto thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
if (IsArrayBuffer(vm)) {
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
if (arrayBuffer->IsDetach(thread)) {
return;
}
arrayBuffer->Detach(thread);
isArrayBuffer = true;
} else if (IsSendableArrayBuffer(vm)) {
JSHandle<ecmascript::JSSendableArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
if (arrayBuffer->IsDetach(thread)) {
return;
}
arrayBuffer->Detach(thread);
isArrayBuffer = true;
} else {
isArrayBuffer = false;
}
}
void JSValueRef::GetDataViewInfo(const EcmaVM *vm,
bool &isDataView,
size_t *byteLength,
void **data,
JSValueRef **arrayBuffer,
size_t *byteOffset)
{
auto thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
if (!IsDataView(vm)) {
isDataView = false;
return;
}
isDataView = true;
JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
if (byteLength) {
*byteLength = dataView->GetByteLength();
}
if (data || arrayBuffer) {
JSHandle<JSArrayBuffer> retArrayBuffer(thread, dataView->GetViewedArrayBuffer(thread));
if (data) {
JSTaggedValue bufferData = retArrayBuffer->GetArrayBufferData(thread);
if (!bufferData.IsJSNativePointer()) {
*data = nullptr;
}
*data = JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
}
if (arrayBuffer) {
*arrayBuffer = reinterpret_cast<JSValueRef*>(retArrayBuffer.GetAddress());
}
}
if (byteOffset) {
*byteOffset = dataView->GetByteOffset();
}
}
void JSValueRef::TryGetArrayLength(const EcmaVM *vm, bool *isPendingException,
bool *isArrayOrSharedArray, uint32_t *arrayLength)
{
JSThread *thread = vm->GetJSThread();
*isPendingException = thread->HasPendingException();
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue thisValue = JSNApiHelper::ToJSTaggedValue(this);
if (LIKELY(thisValue.IsJSArray())) {
*isArrayOrSharedArray = true;
*arrayLength = (*isPendingException) ?
0 : JSArray::Cast(thisValue.GetTaggedObject())->GetArrayLength();
} else if (thisValue.IsJSSharedArray()) {
*isArrayOrSharedArray = true;
*arrayLength = (*isPendingException) ?
0 : ecmascript::JSSharedArray::Cast(thisValue.GetTaggedObject())->GetArrayLength();
} else {
*isArrayOrSharedArray = false;
}
}
bool JSValueRef::IsJsGlobalEnv(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSGlobalEnv();
}
bool JSValueRef::IsSendable(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsSendable();
}
bool JSValueRef::IsWrappedNapiObject(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToJSTaggedValue(this).IsJSWrappedNapiObject();
}
Local<DataViewRef> DataViewRef::New(
const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset, uint32_t byteLength)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSArrayBuffer> buffer(JSNApiHelper::ToJSHandle(arrayBuffer));
JSHandle<JSDataView> dataView = factory->NewJSDataView(buffer, byteOffset, byteLength);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<DataViewRef>(JSHandle<JSTaggedValue>(dataView));
}
Local<DataViewRef> DataViewRef::NewWithoutSwitchState(
const EcmaVM *vm, Local<ArrayBufferRef> arrayBuffer, uint32_t byteOffset, uint32_t byteLength)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
JSHandle<JSArrayBuffer> buffer(JSNApiHelper::ToJSHandle(arrayBuffer));
LOG_IF_SPECIAL(buffer, FATAL);
if (byteOffset + byteLength > buffer->GetArrayBufferByteLength()) {
return JSValueRef::Hole(vm);
}
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSDataView> dataView = factory->NewJSDataView(buffer, byteOffset, byteLength);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<DataViewRef>(JSHandle<JSTaggedValue>(dataView));
}
uint32_t DataViewRef::ByteLength()
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
return dataView->GetByteLength();
}
uint32_t DataViewRef::ByteOffset()
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
return dataView->GetByteOffset();
}
Local<ArrayBufferRef> DataViewRef::GetArrayBuffer(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSDataView> dataView(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(dataView, FATAL);
JSHandle<JSTaggedValue> arrayBuffer(thread, dataView->GetViewedArrayBuffer(thread));
return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
}
Local<JSValueRef> PrimitiveRef::GetValue(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
if (obj->IsJSPrimitiveRef()) {
JSTaggedValue primitiveValue = JSPrimitiveRef::Cast(obj->GetTaggedObject())->GetValue(thread);
JSHandle<JSTaggedValue> value(thread, primitiveValue);
return JSNApiHelper::ToLocal<JSValueRef>(value);
}
return Local<JSValueRef>();
}
Local<NumberRef> NumberRef::New(const EcmaVM *vm, double input)
{
CROSS_THREAD_CHECK(vm);
if (std::isnan(input)) {
input = ecmascript::base::NAN_VALUE;
}
JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input), true);
return JSNApiHelper::ToLocal<NumberRef>(number);
}
Local<NumberRef> NumberRef::New(const EcmaVM *vm, int32_t input)
{
CROSS_THREAD_CHECK(vm);
JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input), true);
return JSNApiHelper::ToLocal<NumberRef>(number);
}
Local<NumberRef> NumberRef::New(const EcmaVM *vm, uint32_t input)
{
CROSS_THREAD_CHECK(vm);
JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input), true);
return JSNApiHelper::ToLocal<NumberRef>(number);
}
Local<NumberRef> NumberRef::New(const EcmaVM *vm, int64_t input)
{
CROSS_THREAD_CHECK(vm);
JSHandle<JSTaggedValue> number(thread, JSTaggedValue(input), true);
return JSNApiHelper::ToLocal<NumberRef>(number);
}
double NumberRef::Value()
{
return JSTaggedNumber(JSNApiHelper::ToJSTaggedValue(this)).GetNumber();
}
Local<JSValueRef> MapRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread,
map->Get(thread, JSNApiHelper::ToJSTaggedValue(*key))));
}
Local<JSValueRef> MapRef::Get(const EcmaVM *vm, const char *utf8)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
auto result = JSHandle<JSTaggedValue>(thread, map->Get(thread, key.GetTaggedValue()));
return JSNApiHelper::ToLocal<JSValueRef>(result);
}
void MapRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
JSMap::Set(thread, map, JSNApiHelper::ToJSHandle(key), JSNApiHelper::ToJSHandle(value));
}
void MapRef::Set(const EcmaVM *vm, const char *utf8, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
JSMap::Set(thread, map, key, JSNApiHelper::ToJSHandle(value));
}
bool MapRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
bool result = map->Has(thread, JSNApiHelper::ToJSTaggedValue(*key));
return result;
}
bool MapRef::Has(const EcmaVM *vm, const char *utf8)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
bool result = map->Has(thread, key.GetTaggedValue());
return result;
}
void MapRef::Delete(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
JSMap::Delete(thread, map, JSNApiHelper::ToJSHandle(key));
}
void MapRef::Clear(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
JSMap::Clear(thread, map);
}
Local<MapRef> MapRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
JSHandle<JSMap> map =
JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
map->SetLinkedMap(thread, hashMap);
JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(map);
return JSNApiHelper::ToLocal<MapRef>(mapTag);
}
int32_t MapRef::GetSize(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
return map->GetSize(thread);
}
int32_t MapRef::GetTotalElements(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
return static_cast<int>((map->GetSize(thread))) +
LinkedHashMap::Cast(map->GetLinkedMap(thread).GetTaggedObject())->NumberOfDeletedElements();
}
Local<JSValueRef> MapRef::GetKey(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(map, FATAL);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetKey(thread, entry)));
}
Local<JSValueRef> MapRef::GetValue(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> map(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(map, FATAL);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, map->GetValue(thread, entry)));
}
Local<MapIteratorRef> MapRef::GetEntries(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSTaggedValue> map(JSNApiHelper::ToJSHandle(this));
JSHandle<JSTaggedValue> mapIter =
ecmascript::JSMapIterator::CreateMapIterator(thread, map, IterationKind::KEY_AND_VALUE);
return JSNApiHelper::ToLocal<MapIteratorRef>(mapIter);
}
Local<MapIteratorRef> MapRef::GetKeys(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSTaggedValue> map(JSNApiHelper::ToJSHandle(this));
JSHandle<JSTaggedValue> mapIter = ecmascript::JSMapIterator::CreateMapIterator(thread, map, IterationKind::KEY);
return JSNApiHelper::ToLocal<MapIteratorRef>(mapIter);
}
Local<MapIteratorRef> MapRef::GetValues(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSTaggedValue> map(JSNApiHelper::ToJSHandle(this));
JSHandle<JSTaggedValue> mapIter = ecmascript::JSMapIterator::CreateMapIterator(thread, map, IterationKind::VALUE);
return JSNApiHelper::ToLocal<MapIteratorRef>(mapIter);
}
Local<SendableMapRef> SendableMapRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor = env->GetSBuiltininMapFunction();
ASSERT(constructor->IsJSSharedFunction() && constructor.GetTaggedValue().IsInSharedHeap());
JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor);
ASSERT(obj.GetTaggedValue().IsInSharedHeap());
JSHandle<ecmascript::JSSharedMap> sharedMap = JSHandle<ecmascript::JSSharedMap>::Cast(obj);
JSHandle<LinkedHashMap> linkedMap =
LinkedHashMap::Create(thread, LinkedHashMap::MIN_CAPACITY, ecmascript::MemSpaceKind::SHARED);
sharedMap->SetLinkedMap(thread, linkedMap);
JSHandle<JSTaggedValue> sharedMapTag = JSHandle<JSTaggedValue>::Cast(sharedMap);
return JSNApiHelper::ToLocal<SendableMapRef>(sharedMapTag);
}
Local<JSValueRef> SendableMapRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread,
ecmascript::JSSharedMap::Get(thread, map, JSNApiHelper::ToJSTaggedValue(*key))));
}
Local<JSValueRef> SendableMapRef::Get(const EcmaVM *vm, const char *utf8)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
auto result = JSHandle<JSTaggedValue>(thread, ecmascript::JSSharedMap::Get(thread, map, key.GetTaggedValue()));
return JSNApiHelper::ToLocal<JSValueRef>(result);
}
void SendableMapRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
ecmascript::JSSharedMap::Set(thread, map, JSNApiHelper::ToJSHandle(key), JSNApiHelper::ToJSHandle(value));
}
void SendableMapRef::Set(const EcmaVM *vm, const char *utf8, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
ecmascript::JSSharedMap::Set(thread, map, key, JSNApiHelper::ToJSHandle(value));
}
bool SendableMapRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
bool result = ecmascript::JSSharedMap::Has(thread, map, JSNApiHelper::ToJSTaggedValue(*key));
return result;
}
bool SendableMapRef::Has(const EcmaVM *vm, const char *utf8)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
bool result = ecmascript::JSSharedMap::Has(thread, map, key.GetTaggedValue());
return result;
}
void SendableMapRef::Delete(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
ecmascript::JSSharedMap::Delete(thread, map, JSNApiHelper::ToJSHandle(key));
}
void SendableMapRef::Clear(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
ecmascript::JSSharedMap::Clear(thread, map);
}
uint32_t SendableMapRef::GetSize(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
return ecmascript::JSSharedMap::GetSize(thread, map);
}
uint32_t SendableMapRef::GetTotalElements(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
return static_cast<int>(ecmascript::JSSharedMap::GetSize(thread, map)) +
LinkedHashMap::Cast(map->GetLinkedMap(thread).GetTaggedObject())->NumberOfDeletedElements();
}
Local<JSValueRef> SendableMapRef::GetKey(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(map, FATAL);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread,
ecmascript::JSSharedMap::GetKey(thread, map, entry)));
}
Local<JSValueRef> SendableMapRef::GetValue(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedMap> map(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(map, FATAL);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread,
ecmascript::JSSharedMap::GetValue(thread, map, entry)));
}
Local<SendableMapIteratorRef> SendableMapRef::GetEntries(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSTaggedValue> map(JSNApiHelper::ToJSHandle(this));
JSHandle<JSTaggedValue> sharedMapIter =
ecmascript::JSSharedMapIterator::CreateMapIterator(thread, map, IterationKind::KEY_AND_VALUE);
return JSNApiHelper::ToLocal<SendableMapIteratorRef>(sharedMapIter);
}
Local<SendableMapIteratorRef> SendableMapRef::GetKeys(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSTaggedValue> map(JSNApiHelper::ToJSHandle(this));
JSHandle<JSTaggedValue> sharedMapIter =
ecmascript::JSSharedMapIterator::CreateMapIterator(thread, map, IterationKind::KEY);
return JSNApiHelper::ToLocal<SendableMapIteratorRef>(sharedMapIter);
}
Local<SendableMapIteratorRef> SendableMapRef::GetValues(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSTaggedValue> map(JSNApiHelper::ToJSHandle(this));
JSHandle<JSTaggedValue> sharedMapIter =
ecmascript::JSSharedMapIterator::CreateMapIterator(thread, map, IterationKind::VALUE);
return JSNApiHelper::ToLocal<SendableMapIteratorRef>(sharedMapIter);
}
Local<SendableSetRef> SendableSetRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor = env->GetSBuiltininSetFunction();
ASSERT(constructor->IsJSSharedFunction() && constructor.GetTaggedValue().IsInSharedHeap());
JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor);
ASSERT(obj.GetTaggedValue().IsInSharedHeap());
JSHandle<ecmascript::JSSharedSet> set = JSHandle<ecmascript::JSSharedSet>::Cast(obj);
JSHandle<LinkedHashSet> linkedSet =
LinkedHashSet::Create(thread, LinkedHashSet::MIN_CAPACITY, ecmascript::MemSpaceKind::SHARED);
set->SetLinkedSet(thread, linkedSet);
JSHandle<JSTaggedValue> sharedSetTag = JSHandle<JSTaggedValue>::Cast(set);
return JSNApiHelper::ToLocal<SendableSetRef>(sharedSetTag);
}
uint32_t SendableSetRef::GetSize(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedSet> set(JSNApiHelper::ToJSHandle(this));
return ecmascript::JSSharedSet::GetSize(thread, set);
}
uint32_t SendableSetRef::GetTotalElements(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedSet> set(JSNApiHelper::ToJSHandle(this));
return static_cast<int>(ecmascript::JSSharedSet::GetSize(thread, set)) +
LinkedHashSet::Cast(set->GetLinkedSet(thread).GetTaggedObject())->NumberOfDeletedElements();
}
Local<JSValueRef> SendableSetRef::GetValue(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedSet> set(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(set, FATAL);
return JSNApiHelper::ToLocal<JSValueRef>(
JSHandle<JSTaggedValue>(thread, ecmascript::JSSharedSet::GetValue(thread, set, entry)));
}
void SendableSetRef::Add(const EcmaVM *vm, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedSet> set(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(set, FATAL);
ecmascript::JSSharedSet::Add(thread, set, JSNApiHelper::ToJSHandle(value));
}
int32_t MapIteratorRef::GetIndex()
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, -1);
JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
return jsMapIter->GetNextIndex();
}
Local<JSValueRef> MapIteratorRef::GetKind(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(jsMapIter, FATAL);
IterationKind iterKind = jsMapIter->GetIterationKind();
Local<JSValueRef> result;
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
switch (iterKind) {
case IterationKind::KEY:
result = JSNApiHelper::ToLocal<JSValueRef>(globalConst->GetHandledKeysString());
break;
case IterationKind::VALUE:
result = JSNApiHelper::ToLocal<JSValueRef>(globalConst->GetHandledValuesString());
break;
case IterationKind::KEY_AND_VALUE:
result = JSNApiHelper::ToLocal<JSValueRef>(globalConst->GetHandledEntriesString());
break;
default:
break;
}
return result;
}
Local<MapIteratorRef> MapIteratorRef::New(const EcmaVM *vm, Local<MapRef> map)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMap> jsMap(JSNApiHelper::ToJSHandle(map));
IterationKind iterKind = IterationKind::KEY_AND_VALUE;
JSHandle<JSTaggedValue> mapIteratorKeyAndValue =
JSMapIterator::CreateMapIterator(vm->GetJSThread(), JSHandle<JSTaggedValue>::Cast(jsMap), iterKind);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<JSValueRef>(mapIteratorKeyAndValue);
}
ecmascript::EcmaRuntimeCallInfo *MapIteratorRef::GetEcmaRuntimeCallInfo(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSMapIterator> jsMapIter(JSNApiHelper::ToJSHandle(this));
JSHandle<LinkedHashMap> linkedHashMap(thread, jsMapIter->GetIteratedMap(thread));
uint32_t size = linkedHashMap->GetLength();
return ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread,
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, jsMapIter.GetTaggedValue()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()), size);
}
Local<ArrayRef> MapIteratorRef::Next(const EcmaVM *vm, ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> nextTagValResult(thread, JSMapIterator::Next(ecmaRuntimeCallInfo));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> iteratorVal(thread,
JSIterator::IteratorValue(thread, nextTagValResult).GetTaggedValue());
return JSNApiHelper::ToLocal<ArrayRef>(iteratorVal);
}
Local<JSValueRef> MapIteratorRef::Next(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> mapIter(JSNApiHelper::ToJSHandle(this));
auto result = JSMapIterator::NextInternal(thread, mapIter);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, result));
}
Local<JSValueRef> SendableMapIteratorRef::Next(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> sharedMapIter(JSNApiHelper::ToJSHandle(this));
auto result = ecmascript::JSSharedMapIterator::NextInternal(thread, sharedMapIter);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, result));
}
int32_t SetIteratorRef::GetIndex()
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, -1);
JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
return jsSetIter->GetNextIndex();
}
Local<JSValueRef> SetIteratorRef::GetKind(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(jsSetIter, FATAL);
IterationKind iterKind = jsSetIter->GetIterationKind();
Local<JSValueRef> result;
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
switch (iterKind) {
case IterationKind::KEY:
result = JSNApiHelper::ToLocal<JSValueRef>(globalConst->GetHandledKeysString());
break;
case IterationKind::VALUE:
result = JSNApiHelper::ToLocal<JSValueRef>(globalConst->GetHandledValuesString());
break;
case IterationKind::KEY_AND_VALUE:
result = JSNApiHelper::ToLocal<JSValueRef>(globalConst->GetHandledEntriesString());
break;
default:
break;
}
return result;
}
Local<SetIteratorRef> SetIteratorRef::New(const EcmaVM *vm, Local<SetRef> set)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSSet> jsSet(JSNApiHelper::ToJSHandle(set));
IterationKind iterKind = IterationKind::KEY_AND_VALUE;
JSHandle<JSTaggedValue> setIteratorKeyAndValue =
JSSetIterator::CreateSetIterator(thread, JSHandle<JSTaggedValue>::Cast(jsSet), iterKind);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<JSValueRef>(setIteratorKeyAndValue);
}
ecmascript::EcmaRuntimeCallInfo *SetIteratorRef::GetEcmaRuntimeCallInfo(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSSetIterator> jsSetIter(JSNApiHelper::ToJSHandle(this));
JSHandle<LinkedHashSet> linkedHashSet(thread, jsSetIter->GetIteratedSet(thread));
uint32_t size = linkedHashSet->GetLength();
return ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread,
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, jsSetIter.GetTaggedValue()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()), size);
}
Local<ArrayRef> SetIteratorRef::Next(const EcmaVM *vm, ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> nextTagValResult(thread, JSSetIterator::Next(ecmaRuntimeCallInfo));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> iteratorVal(thread,
JSIterator::IteratorValue(thread, nextTagValResult).GetTaggedValue());
return JSNApiHelper::ToLocal<ArrayRef>(iteratorVal);
}
Local<BufferRef> BufferRef::New(const EcmaVM *vm, const Local<JSValueRef> &context, int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSArrayBuffer> arrayBuffer = JSHandle<JSArrayBuffer>::Cast(factory->NewJSArrayBuffer(length));
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSFunction> current =
factory->NewJSFunction(env, reinterpret_cast<void *>(BufferRef::BufferToStringCallback));
Local<StringRef> key = StringRef::NewFromUtf8(vm, "toString");
JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
JSHandle<JSTaggedValue> currentTaggedValue(current);
JSHandle<JSTaggedValue> obj(arrayBuffer);
bool result = JSTaggedValue::SetProperty(thread, obj, keyValue, currentTaggedValue);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
if (!result) {
LOG_ECMA(ERROR) << "SetProperty failed ! ! !";
}
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return JSNApiHelper::ToLocal<BufferRef>(obj);
}
Local<BufferRef> BufferRef::New(const EcmaVM *vm, int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return New(vm, context, length);
}
Local<BufferRef> BufferRef::New(const EcmaVM *vm, const Local<JSValueRef> &context, void *buffer,
int32_t length, const NativePointerCallback &deleter, void *data)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(buffer, length, deleter, data);
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSFunction> current =
factory->NewJSFunction(env, reinterpret_cast<void *>(BufferRef::BufferToStringCallback));
Local<StringRef> key = StringRef::NewFromUtf8(vm, "toString");
JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
JSHandle<JSTaggedValue> currentTaggedValue(current);
JSHandle<JSTaggedValue> obj(arrayBuffer);
bool result = JSTaggedValue::SetProperty(thread, obj, keyValue, currentTaggedValue);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
if (!result) {
LOG_ECMA(ERROR) << "SetProperty failed ! ! !";
}
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
}
Local<BufferRef> BufferRef::New(
const EcmaVM *vm, void *buffer, int32_t length, const NativePointerCallback &deleter, void *data)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return New(vm, context, buffer, length, deleter, data);
}
int32_t BufferRef::ByteLength(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
return arrayBuffer->GetArrayBufferByteLength();
}
void *BufferRef::GetBuffer(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData(vm->GetJSThread());
if (!bufferData.IsJSNativePointer()) {
return nullptr;
}
return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
}
JSTaggedValue BufferRef::BufferToStringCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
{
JSThread *thread = ecmaRuntimeCallInfo->GetThread();
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(thread->GetEcmaVM());
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> arrayBuff = ecmaRuntimeCallInfo->GetThis();
JSHandle<JSArrayBuffer> arrayBuffer(arrayBuff);
uint32_t length = arrayBuffer->GetArrayBufferByteLength();
JSTaggedValue data = arrayBuffer->GetArrayBufferData(thread);
ecmascript::CVector<uint16_t> valueTable;
valueTable.reserve(length);
for (uint32_t i = 0; i < length; i++) {
void* rawData = reinterpret_cast<void *>(
ToUintPtr(JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer()) + i);
uint8_t *block = reinterpret_cast<uint8_t *>(rawData);
uint16_t nextCv = static_cast<uint16_t>(*block);
valueTable.emplace_back(nextCv);
}
auto *char16tData0 = reinterpret_cast<const char16_t *>(valueTable.data());
std::u16string u16str(char16tData0, length);
const char16_t *constChar16tData = u16str.data();
auto *char16tData = const_cast<char16_t *>(constChar16tData);
auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
uint32_t u16strSize = u16str.size();
JSTaggedValue rString = factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
JSHandle<EcmaString> StringHandle = JSTaggedValue::ToString(thread, rString);
RETURN_VALUE_IF_ABRUPT(thread, JSTaggedValue::Undefined());
return StringHandle.GetTaggedValue();
}
Local<PromiseCapabilityRef> PromiseCapabilityRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor(globalEnv->GetPromiseFunction());
JSHandle<JSTaggedValue> capability(JSPromise::NewPromiseCapability(thread, constructor));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<PromiseCapabilityRef>(capability);
}
Local<PromiseRef> PromiseCapabilityRef::GetPromise(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(capacity, FATAL);
return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, capacity->GetPromise(thread)));
}
bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, uintptr_t value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSTaggedValue arg = *reinterpret_cast<JSTaggedValue *>(value);
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(arg.GetRawData());
#endif
JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(capacity, FATAL);
JSTaggedValue resolve = capacity->GetResolve(thread);
JSTaggedValue undefined = constants->GetUndefined();
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1);
RETURN_VALUE_IF_ABRUPT(thread, false);
info->SetCallArg(arg);
JSFunction::Call(info);
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ClearKeptObjects(thread);
return true;
}
bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(value);
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(arg.GetTaggedValue().GetRawData());
#endif
JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(capacity, FATAL);
JSHandle<JSTaggedValue> resolve(thread, capacity->GetResolve(thread));
JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, resolve, undefined, undefined, 1);
RETURN_VALUE_IF_ABRUPT(thread, false);
info->SetCallArg(arg.GetTaggedValue());
JSFunction::Call(info);
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ClearKeptObjects(thread);
return true;
}
bool PromiseCapabilityRef::Reject(const EcmaVM *vm, uintptr_t reason)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSTaggedValue arg = *reinterpret_cast<JSTaggedValue *>(reason);
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(arg.GetRawData());
#endif
JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(capacity, FATAL);
JSTaggedValue reject = capacity->GetReject(thread);
JSTaggedValue undefined = constants->GetUndefined();
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);
RETURN_VALUE_IF_ABRUPT(thread, false);
info->SetCallArg(arg);
JSFunction::Call(info);
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ClearKeptObjects(thread);
return true;
}
bool PromiseCapabilityRef::Reject(const EcmaVM *vm, Local<JSValueRef> reason)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(reason);
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(arg.GetTaggedValue().GetRawData());
#endif
JSHandle<PromiseCapability> capacity(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(capacity, FATAL);
JSHandle<JSTaggedValue> reject(thread, capacity->GetReject(thread));
JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);
RETURN_VALUE_IF_ABRUPT(thread, false);
info->SetCallArg(arg.GetTaggedValue());
JSFunction::Call(info);
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
EcmaVM::ClearKeptObjects(thread);
return true;
}
Local<SymbolRef> SymbolRef::New(const EcmaVM *vm, Local<StringRef> description)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSSymbol> symbol = factory->NewJSSymbol();
if (!description.IsEmpty()) {
JSTaggedValue desc = JSNApiHelper::ToJSTaggedValue(*description);
symbol->SetDescription(thread, desc);
}
return JSNApiHelper::ToLocal<SymbolRef>(JSHandle<JSTaggedValue>(symbol));
}
Local<StringRef> SymbolRef::GetDescription(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue description =
JSSymbol::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetDescription(thread);
if (!description.IsString()) {
auto constants = thread->GlobalConstants();
return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
}
JSHandle<JSTaggedValue> descriptionHandle(thread, description);
return JSNApiHelper::ToLocal<StringRef>(descriptionHandle);
}
Local<BooleanRef> BooleanRef::New(const EcmaVM *vm, bool value)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> boolean(thread, JSTaggedValue(value));
return JSNApiHelper::ToLocal<BooleanRef>(boolean);
}
bool BooleanRef::Value()
{
return JSNApiHelper::ToJSTaggedValue(this).IsTrue();
}
Local<StringRef> StringRef::NewFromUtf8(const EcmaVM *vm, const char *utf8, int length)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
if (length < 0) {
JSHandle<JSTaggedValue> current(factory->NewFromUtf8(utf8));
return JSNApiHelper::ToLocal<StringRef>(current);
}
JSHandle<JSTaggedValue> current(factory->NewFromUtf8(reinterpret_cast<const uint8_t *>(utf8), length));
return JSNApiHelper::ToLocal<StringRef>(current);
}
Local<StringRef> StringRef::NewFromUtf8Replacement(const EcmaVM *vm, const char *utf8, int length)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
if (length < 0) {
JSHandle<JSTaggedValue> current(factory->NewFromUtf8Replacement(utf8));
return JSNApiHelper::ToLocal<StringRef>(current);
}
JSHandle<JSTaggedValue> current(factory->NewFromUtf8Replacement(reinterpret_cast<const uint8_t *>(utf8), length));
return JSNApiHelper::ToLocal<StringRef>(current);
}
Local<StringRef> StringRef::NewFromUtf8WithoutStringTable(const EcmaVM *vm, const char *utf8, int length)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
if (length < 0) {
JSHandle<JSTaggedValue> current(factory->NewFromUtf8WithoutStringTable(utf8));
return JSNApiHelper::ToLocal<StringRef>(current);
}
JSHandle<JSTaggedValue> current(
factory->NewFromUtf8WithoutStringTable(reinterpret_cast<const uint8_t *>(utf8), length));
return JSNApiHelper::ToLocal<StringRef>(current);
}
Local<StringRef> StringRef::NewFromUtf8WithoutStringTableReplacement(const EcmaVM *vm, const char *utf8, int length)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
if (length < 0) {
JSHandle<JSTaggedValue> current(factory->NewFromUtf8WithoutStringTableReplacement(utf8));
return JSNApiHelper::ToLocal<StringRef>(current);
}
JSHandle<JSTaggedValue> current(
factory->NewFromUtf8WithoutStringTableReplacement(reinterpret_cast<const uint8_t *>(utf8), length));
return JSNApiHelper::ToLocal<StringRef>(current);
}
Local<StringRef> StringRef::NewFromUtf16WithoutStringTable(const EcmaVM *vm, const char16_t *utf16, int length)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
if (length < 0) {
JSHandle<JSTaggedValue> current(factory->NewFromUtf16WithoutStringTable(utf16));
return JSNApiHelper::ToLocal<StringRef>(current);
}
JSHandle<JSTaggedValue> current(factory->NewFromUtf16WithoutStringTable(reinterpret_cast<const uint16_t *>(utf16),
length));
return JSNApiHelper::ToLocal<StringRef>(current);
}
Local<StringRef> StringRef::NewFromUtf16(const EcmaVM *vm, const char16_t *utf16, int length)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
if (length < 0) {
JSHandle<JSTaggedValue> current(factory->NewFromUtf16(utf16));
return JSNApiHelper::ToLocal<StringRef>(current);
}
JSHandle<JSTaggedValue> current(factory->NewFromUtf16(reinterpret_cast<const uint16_t *>(utf16), length));
return JSNApiHelper::ToLocal<StringRef>(current);
}
Local<StringRef> StringRef::NewExternalFromUtf16(const EcmaVM *vm,
const char16_t *utf16,
int length,
ExternalStringFinalizerCallback callback,
void *hint)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<EcmaString> strHandle(vm->GetJSThread(),
EcmaStringAccessor::CreateFromExternalResource(
vm, const_cast<char16_t *>(utf16),
length, false, static_cast<ecmascript::ExternalStringResourceCallback>(callback), hint));
JSHandle<JSTaggedValue> current = JSHandle<JSTaggedValue>::Cast(strHandle);
return JSNApiHelper::ToLocal<StringRef>(current);
}
Local<StringRef> StringRef::NewExternalFromAscii(const EcmaVM *vm,
const char *ascii,
int length,
ExternalStringFinalizerCallback callback,
void *hint)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<EcmaString> strHandle(vm->GetJSThread(),
EcmaStringAccessor::CreateFromExternalResource(
vm, const_cast<char *>(ascii),
length, true, static_cast<ecmascript::ExternalStringResourceCallback>(callback), hint));
JSHandle<JSTaggedValue> current = JSHandle<JSTaggedValue>::Cast(strHandle);
return JSNApiHelper::ToLocal<StringRef>(current);
}
std::string StringRef::ToString(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, "");
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).ToStdString(vm->GetJSThread());
}
std::string StringRef::DebuggerToString(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, "");
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).DebuggerToStdString(vm->GetJSThread());
}
uint32_t StringRef::Length(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).GetLength();
}
bool StringRef::IsCompressed(const panda::EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return !EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this)).IsUtf16();
}
size_t StringRef::Utf8Length(const EcmaVM *vm, bool isGetBufferSize)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
auto thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<EcmaString> strHandle(thread, EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(this)));
return EcmaStringAccessor(EcmaStringAccessor::Flatten(vm, strHandle)).GetUtf8Length(thread, isGetBufferSize);
}
uint32_t StringRef::WriteUtf8(const EcmaVM *vm, char *buffer, uint32_t length, bool isWriteBuffer)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
.WriteToFlatUtf8(thread, reinterpret_cast<uint8_t *>(buffer), length, isWriteBuffer);
}
uint32_t StringRef::WriteUtf16(const EcmaVM *vm, char16_t *buffer, uint32_t length)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
.WriteToUtf16(vm->GetJSThread(), reinterpret_cast<uint16_t *>(buffer), length);
}
uint32_t StringRef::WriteLatin1(const EcmaVM *vm, char *buffer, uint32_t length)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
.WriteToOneByte(vm->GetJSThread(), reinterpret_cast<uint8_t *>(buffer), length);
}
uint32_t StringRef::WriteLatin1WithoutSwitchState(const EcmaVM *vm, char *buffer, uint32_t length)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
CROSS_THREAD_CHECK(vm);
return EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this))
.WriteToOneByte(vm->GetJSThread(), reinterpret_cast<uint8_t *>(buffer), length);
}
Local<StringRef> StringRef::GetNapiWrapperString(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
JSHandle<JSTaggedValue> napiWrapperString = thread->GlobalConstants()->GetHandledNapiWrapperString();
return JSNApiHelper::ToLocal<StringRef>(napiWrapperString);
}
const uint16_t *StringRef::GetBufferUtf16(const EcmaVM *vm, uint32_t &length)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
CROSS_THREAD_CHECK(vm);
auto ecmaStringAccessor = EcmaStringAccessor(JSNApiHelper::ToJSTaggedValue(this));
if (!ecmaStringAccessor.IsLineString() || !ecmaStringAccessor.IsUtf16()) {
LOG_ECMA(DEBUG) << "StringRef GetBufferUtf16 failed: Not LineString or not utf-16.";
return nullptr;
}
length = this->Length(vm);
return ecmaStringAccessor.GetDataUtf16();
}
Local<TypedArrayRef> StringRef::EncodeIntoUint8Array(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> string = JSNApiHelper::ToJSHandle(this);
uint32_t length = this->Utf8Length(vm, true);
if (length <= 1) {
return Undefined(vm);
}
JSHandle<JSObject> obj =
TypedArrayHelper::FastCreateTypedArray(thread, length - 1, DataViewType::UINT8);
if (JSNApi::HasPendingException(vm)) {
LOG_ECMA(ERROR) << "JSNapi EncodeIntoUint8Array: Create TypedArray failed";
return Undefined(vm);
}
JSHandle<JSObject> arrayBuffer(thread, JSTypedArray::Cast(*obj)->GetViewedArrayBufferOrByteArray(thread));
JSTaggedValue bufferData = JSHandle<JSArrayBuffer>::Cast(arrayBuffer)->GetArrayBufferData(thread);
void *buffer = JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
JSHandle<EcmaString> stringHandle = JSHandle<EcmaString>::Cast(string);
EcmaStringAccessor(stringHandle).WriteToFlatUtf8(thread, reinterpret_cast<uint8_t *>(buffer), length - 1, true);
JSHandle<JSTaggedValue> typedArrayTag = JSHandle<JSTaggedValue>::Cast(obj);
return JSNApiHelper::ToLocal<TypedArrayRef>(typedArrayTag);
}
PromiseRejectInfo::PromiseRejectInfo(Local<JSValueRef> promise, Local<JSValueRef> reason,
PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data)
: promise_(promise), reason_(reason), operation_(operation), data_(data) {}
Local<JSValueRef> PromiseRejectInfo::GetPromise() const
{
return promise_;
}
Local<JSValueRef> PromiseRejectInfo::GetReason() const
{
return reason_;
}
PromiseRejectInfo::PROMISE_REJECTION_EVENT PromiseRejectInfo::GetOperation() const
{
return operation_;
}
void* PromiseRejectInfo::GetData() const
{
return data_;
}
Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, uint64_t input)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<BigInt> big = BigInt::Uint64ToBigInt(thread, input);
JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
return JSNApiHelper::ToLocal<BigIntRef>(bigint);
}
Local<BigIntRef> BigIntRef::New(const EcmaVM *vm, int64_t input)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<BigInt> big = BigInt::Int64ToBigInt(thread, input);
JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
return JSNApiHelper::ToLocal<BigIntRef>(bigint);
}
Local<JSValueRef> BigIntRef::CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<BigInt> big = BigInt::CreateBigWords(thread, sign, size, words);
JSHandle<JSTaggedValue> bigint = JSHandle<JSTaggedValue>::Cast(big);
return JSNApiHelper::ToLocal<JSValueRef>(bigint);
}
void BigIntRef::BigIntToInt64(const EcmaVM *vm, int64_t *value, bool *lossless)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(bigintVal, ERROR);
BigInt::BigIntToInt64(thread, bigintVal, value, lossless);
}
void BigIntRef::BigIntToUint64(const EcmaVM *vm, uint64_t *value, bool *lossless)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> bigintVal(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(bigintVal, ERROR);
BigInt::BigIntToUint64(thread, bigintVal, value, lossless);
}
void BigIntRef::GetWordsArray(const EcmaVM *vm, bool* signBit, size_t wordCount, uint64_t* words)
{
DCHECK_SPECIAL_VALUE(this);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
uint32_t len = bigintVal->GetLength();
uint32_t count = 0;
uint32_t index = 0;
ASSERT(wordCount > 0);
for (; index < wordCount - 1; ++index) {
words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32;
}
if (len % 2 == 0) {
words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
words[index] |= static_cast<uint64_t>(bigintVal->GetDigit(count++)) << 32;
} else {
words[index] = static_cast<uint64_t>(bigintVal->GetDigit(count++));
}
*signBit = bigintVal->GetSign();
}
uint32_t BigIntRef::GetWordsArraySize(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<BigInt> bigintVal(JSNApiHelper::ToJSHandle(this));
uint32_t len = bigintVal->GetLength();
return len % 2 != 0 ? len / 2 + 1 : len / 2;
}
LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread())
{
#ifdef USE_HWASAN
(const_cast<EcmaVM*>(vm))->AddHandleScopeDepth();
#endif
prevNext_ = vm->GetHandleScopeStorageNext();
prevEnd_ = vm->GetHandleScopeStorageEnd();
prevHandleStorageIndex_ = vm->GetCurrentHandleStorageIndex();
prevPrimitiveNext_ = vm->GetPrimitiveScopeStorageNext();
prevPrimitiveEnd_ = vm->GetPrimitiveScopeStorageEnd();
prevPrimitiveStorageIndex_ = vm->GetCurrentPrimitiveStorageIndex();
#if defined(ENABLE_LOCAL_HANDLE_LEAK_DETECT)
auto heapProfiler = reinterpret_cast<HeapProfiler *>(
HeapProfilerInterface::GetInstance(const_cast<EcmaVM *>(vm)));
heapProfiler->IncreaseScopeCount();
heapProfiler->PushToActiveScopeStack(this, nullptr);
#endif
#if defined(ENABLE_HITRACE_LOCAL_HANDLE_DETECT)
const_cast<EcmaVM *>(vm)->IncreaseOpenHandleScopes();
scopeLevel_ = vm->GetOpenHandleScopes();
#endif
}
LocalScope::LocalScope(const EcmaVM *vm, JSTaggedType value) : thread_(vm->GetJSThread())
{
ecmascript::ThreadManagedScope managedScope(reinterpret_cast<JSThread *>(thread_));
#ifdef USE_HWASAN
(const_cast<EcmaVM*>(vm))->AddHandleScopeDepth();
#endif
ecmascript::EcmaHandleScope::NewHandle(reinterpret_cast<JSThread *>(thread_), value);
prevNext_ = vm->GetHandleScopeStorageNext();
prevEnd_ = vm->GetHandleScopeStorageEnd();
prevHandleStorageIndex_ = vm->GetCurrentHandleStorageIndex();
prevPrimitiveNext_ = vm->GetPrimitiveScopeStorageNext();
prevPrimitiveEnd_ = vm->GetPrimitiveScopeStorageEnd();
prevPrimitiveStorageIndex_ = vm->GetCurrentPrimitiveStorageIndex();
#if defined(ENABLE_LOCAL_HANDLE_LEAK_DETECT)
auto heapProfiler = reinterpret_cast<HeapProfiler *>(
HeapProfilerInterface::GetInstance(const_cast<EcmaVM *>(vm)));
heapProfiler->IncreaseScopeCount();
heapProfiler->PushToActiveScopeStack(this, nullptr);
#endif
#if defined(ENABLE_HITRACE_LOCAL_HANDLE_DETECT)
const_cast<EcmaVM *>(vm)->IncreaseOpenHandleScopes();
scopeLevel_ = vm->GetOpenHandleScopes();
#endif
}
LocalScope::~LocalScope()
{
ecmascript::ThreadManagedScope managedScope(reinterpret_cast<JSThread *>(thread_));
auto vm = reinterpret_cast<JSThread *>(thread_)->GetEcmaVM();
#ifdef USE_HWASAN
vm->DelHandleScopeDepth();
#endif
vm->SetHandleScopeStorageNext(static_cast<JSTaggedType *>(prevNext_));
vm->SetPrimitiveScopeStorageNext(static_cast<JSTaggedType *>(prevPrimitiveNext_));
if (vm->GetHandleScopeStorageEnd() != prevEnd_) {
vm->SetHandleScopeStorageEnd(static_cast<JSTaggedType *>(prevEnd_));
vm->ShrinkHandleStorage(prevHandleStorageIndex_);
}
if (vm->GetPrimitiveScopeStorageEnd() != prevPrimitiveEnd_) {
vm->SetPrimitiveScopeStorageEnd(static_cast<JSTaggedType *>(prevPrimitiveEnd_));
vm->ShrinkPrimitiveStorage(prevPrimitiveStorageIndex_);
}
#if defined(ENABLE_LOCAL_HANDLE_LEAK_DETECT)
auto heapProfiler = reinterpret_cast<HeapProfiler *>(HeapProfilerInterface::GetInstance(vm));
heapProfiler->DecreaseScopeCount();
heapProfiler->PopFromActiveScopeStack();
#endif
#if defined(ENABLE_HITRACE_LOCAL_HANDLE_DETECT)
if (scopeLevel_ != vm->GetOpenHandleScopes()) {
#ifdef HOOK_ENABLE
restraceExt(RES_ARK_LOCAL_HANDLE, (void *)this, sizeof(JSTaggedType), TAG_RES_ARK_LOCAL_HANDLE, true, false);
#endif
}
const_cast<EcmaVM *>(vm)->DecreaseOpenHandleScopes();
#endif
}
EscapeLocalScope::EscapeLocalScope(const EcmaVM *vm) : LocalScope(vm, JSTaggedValue::Undefined().GetRawData())
{
escapeHandle_ = ToUintPtr(vm->GetHandleScopeStorageNext() - 1);
}
Local<IntegerRef> IntegerRef::New(const EcmaVM *vm, int input)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
return JSNApiHelper::ToLocal<IntegerRef>(integer);
}
Local<IntegerRef> IntegerRef::NewFromUnsigned(const EcmaVM *vm, unsigned int input)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> integer(thread, JSTaggedValue(input));
return JSNApiHelper::ToLocal<IntegerRef>(integer);
}
int IntegerRef::Value()
{
return JSNApiHelper::ToJSTaggedValue(this).GetInt();
}
Local<ObjectRef> ObjectRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> object(factory->CreateNapiObject());
return JSNApiHelper::ToLocal<ObjectRef>(object);
}
Local<ObjectRef> ObjectRef::NewWrappedNapiObject(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> object(factory->CreateNapiObject(true));
return JSNApiHelper::ToLocal<ObjectRef>(object);
}
uintptr_t ObjectRef::NewObject(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm,
(thread->GlobalConstants()->GetHandledUndefined()).GetAddress());
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object(vm->GetFactory()->CreateNapiObject());
return object.GetAddress();
}
Local<ObjectRef> ObjectRef::NewS(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
JSHandle<JSFunction> constructor(globalEnv->GetSObjectFunction());
JSHandle<JSTaggedValue> object(factory->NewJSObjectByConstructor(constructor));
return JSNApiHelper::ToLocal<ObjectRef>(object);
}
Local<ObjectRef> ObjectRef::NewWithProperties(const EcmaVM *vm, size_t propertyCount,
const Local<JSValueRef> *keys,
const PropertyAttribute *attributes)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> obj;
auto CreateObjImpl = [vm, thread, propertyCount, keys, attributes] (uintptr_t head) -> JSHandle<JSTaggedValue> {
const PropertyDescriptor *desc = reinterpret_cast<const PropertyDescriptor *>(head);
for (size_t i = 0; i < propertyCount; ++i) {
const PropertyAttribute &attr = attributes[i];
new (reinterpret_cast<void *>(head)) PropertyDescriptor(thread,
JSNApiHelper::ToJSHandle(attr.GetValue(vm)),
attr.IsWritable(), attr.IsEnumerable(),
attr.IsConfigurable());
head += sizeof(PropertyDescriptor);
}
ObjectFactory *factory = vm->GetFactory();
return factory->CreateJSObjectWithProperties(propertyCount, keys, desc);
};
if (propertyCount <= MAX_PROPERTIES_ON_STACK) {
char desc[sizeof(PropertyDescriptor) * MAX_PROPERTIES_ON_STACK];
obj = CreateObjImpl(reinterpret_cast<uintptr_t>(desc));
} else {
void *desc = malloc(sizeof(PropertyDescriptor) * propertyCount);
if (desc == nullptr) {
LOG_FULL(FATAL) << "malloc failed in NewWithProperties";
}
obj = CreateObjImpl(reinterpret_cast<uintptr_t>(desc));
free(desc);
}
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<ObjectRef>(obj));
}
Local<ObjectRef> ObjectRef::NewSWithProperties(const EcmaVM *vm, SendablePropertiesInfo &info)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
std::vector<PropertyDescriptor> descs;
JSNapiSendable::InitWithPropertiesInfo(thread, info, descs);
auto obj = factory->CreateSObjectWithProperties(descs);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<ObjectRef>(obj));
}
Local<ObjectRef> ObjectRef::NewWithNamedProperties(const EcmaVM *vm, size_t propertyCount,
const char **keys, const Local<JSValueRef> *values)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> obj = factory->CreateJSObjectWithNamedProperties(propertyCount, keys, values);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<ObjectRef>(obj));
}
Local<ObjectRef> ObjectRef::CreateNativeModuleFailureInfo(const EcmaVM *vm, const std::string &failureInfo)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
if (EcmaVM::GetErrorInfoEnhance()) {
JSHandle<NativeModuleFailureInfo> nativeModuleErrorFailureInfo =
NativeModuleFailureInfo::CreateNativeModuleFailureInfo(vm, failureInfo);
return JSNApiHelper::ToLocal<ObjectRef>(JSHandle<JSTaggedValue>::Cast(nativeModuleErrorFailureInfo));
}
return JSValueRef::Undefined(vm);
}
Local<ObjectRef> ObjectRef::CreateAccessorData(const EcmaVM *vm,
Local<FunctionRef> getter, Local<FunctionRef> setter)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter);
JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter);
JSHandle<AccessorData> accessor = thread->GetEcmaVM()->GetFactory()->NewAccessorData();
accessor->SetGetter(thread, getterValue);
accessor->SetSetter(thread, setterValue);
return JSNApiHelper::ToLocal<ObjectRef>(JSHandle<JSTaggedValue>::Cast(accessor));
}
Local<ObjectRef> ObjectRef::CreateSendableAccessorData(const EcmaVM *vm,
Local<FunctionRef> getter,
Local<FunctionRef> setter)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter);
JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter);
JSHandle<AccessorData> accessor = thread->GetEcmaVM()->GetFactory()->NewSAccessorData();
accessor->SetGetter(thread, getterValue);
accessor->SetSetter(thread, setterValue);
return JSNApiHelper::ToLocal<ObjectRef>(JSHandle<JSTaggedValue>::Cast(accessor));
}
bool ObjectRef::ConvertToNativeBindingObject(const EcmaVM *vm, Local<NativePointerRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(object, ERROR);
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSTaggedValue> keyValue = thread->GlobalConstants()->GetHandledNativeBindingSymbol();
auto key = JSNApiHelper::ToLocal<JSValueRef>(keyValue);
PropertyAttribute attr(Local<JSValueRef>(value), true, false, false);
bool result = DefineProperty(vm, key, attr);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
object->GetTaggedObject()->GetClass()->SetIsNativeBindingObject(true);
return result;
}
Local<NativePointerRef> ObjectRef::GetNativeBindingPointer(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(object, ERROR);
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSTaggedValue> keyValue = thread->GlobalConstants()->GetHandledNativeBindingSymbol();
OperationResult ret = JSTaggedValue::GetProperty(thread, object, keyValue);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(ret.GetValue()));
}
bool ObjectRef::Set(const EcmaVM *vm, Local<JSValueRef> key, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value);
if (!obj->IsHeapObject()) {
return JSTaggedValue::SetProperty(thread, obj, keyValue, valueValue);
}
return ObjectFastOperator::FastSetPropertyByValue(thread, obj.GetTaggedValue(),
keyValue.GetTaggedValue(),
valueValue.GetTaggedValue());
}
bool ObjectRef::Set(const EcmaVM *vm, const char *utf8, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
JSHandle<JSTaggedValue> val = JSNApiHelper::ToJSHandle(value);
if (!obj->IsHeapObject()) {
return JSTaggedValue::SetProperty(thread, obj, key, val);
}
JSTaggedValue res = ObjectFastOperator::TrySetPropertyByNameThroughCacheAtLocal(thread, obj, key, val);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (!res.IsHole()) {
return !res.IsException();
}
if (!JSNApi::KeyIsNumber(utf8)) {
res = ObjectFastOperator::SetPropertyByName(thread, obj.GetTaggedValue(), key.GetTaggedValue(),
val.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (!res.IsHole()) {
return !res.IsException();
}
return JSTaggedValue::SetProperty(thread, obj, key, val, true);
}
return ObjectFastOperator::FastSetPropertyByValue(thread, obj.GetTaggedValue(),
key.GetTaggedValue(),
val.GetTaggedValue());
}
bool ObjectRef::SetWithoutSwitchState(const EcmaVM *vm, const char *utf8, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromUtf8(utf8));
JSHandle<JSTaggedValue> val = JSNApiHelper::ToJSHandle(value);
JSTaggedValue res = ObjectFastOperator::TrySetPropertyByNameThroughCacheAtLocal(thread, obj, key, val);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (!res.IsHole()) {
return !res.IsException();
}
if (!JSNApi::KeyIsNumber(utf8)) {
res = ObjectFastOperator::SetPropertyByName(thread, obj.GetTaggedValue(), key.GetTaggedValue(),
val.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (!res.IsHole()) {
return !res.IsException();
}
return JSTaggedValue::SetProperty(thread, obj, key, val, true);
}
return ObjectFastOperator::FastSetPropertyByValue(thread, obj.GetTaggedValue(),
key.GetTaggedValue(),
val.GetTaggedValue());
}
Local<JSValueRef> JSNApi::GetImplements(const EcmaVM *vm, Local<JSValueRef> instance)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue result;
{
LocalScope scope(vm);
if (!instance->IsObject(vm)) {
return JSValueRef::Undefined(vm);
}
JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(instance));
OperationResult constructorValue = JSTaggedValue::GetProperty(
thread, obj, thread->GlobalConstants()->GetHandledConstructorString());
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
result = constructorValue.GetValue().GetTaggedValue();
if (!result.IsJSFunction()) {
return JSValueRef::Undefined(vm);
}
JSHandle<JSTaggedValue> resultValue(thread, result);
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSTaggedValue> interfaceTypeSymbol = env->GetInterfaceTypeSymbol();
OperationResult interfaceTypeValue = JSObject::GetProperty(thread, resultValue, interfaceTypeSymbol);
result = interfaceTypeValue.GetValue().GetTaggedValue();
if (result.IsUndefined()) {
return JSValueRef::Undefined(vm);
}
}
JSHandle<JSTaggedValue> implementRet(thread, result);
return JSNApiHelper::ToLocal<JSValueRef>(implementRet);
}
uintptr_t JSNApi::CreateStrongRef(const EcmaVM *vm, Local<JSValueRef> local)
{
CROSS_THREAD_CHECK(vm);
return GetGlobalHandleAddr(vm, reinterpret_cast<uintptr_t>(*local));
}
void JSNApi::DeleteStrongRef(const EcmaVM *vm, uintptr_t strongRef)
{
CROSS_THREAD_CHECK(vm);
DisposeGlobalHandleAddr(vm, strongRef);
}
void JSNApi::NotifyOnANR()
{
EcmaVM::NotifyANR();
}
void JSNApi::SetTrackGlobalRef(EcmaVM *vm, bool enable)
{
CROSS_THREAD_CHECK(vm);
thread->SetTrackGlobalRef(enable);
}
bool JSNApi::IsTrackGlobalRefEnabled(const EcmaVM *vm)
{
CROSS_THREAD_CHECK(vm);
return thread->IsTrackGlobalRefEnabled();
}
void JSNApi::StoreGlobalRefMapping(EcmaVM *vm, uintptr_t slotAddr, void *ref)
{
CROSS_THREAD_CHECK(vm);
thread->StoreGlobalRefMapping(slotAddr, ref);
}
void JSNApi::EraseGlobalRefMapping(EcmaVM *vm, uintptr_t slotAddr)
{
CROSS_THREAD_CHECK(vm);
thread->EraseGlobalRefMapping(slotAddr);
}
void *JSNApi::FindGlobalRefMapping(const EcmaVM *vm, uintptr_t slotAddr)
{
CROSS_THREAD_CHECK(vm);
return thread->FindGlobalRefMapping(slotAddr);
}
bool ObjectRef::Set(const EcmaVM *vm, uint32_t key, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> valueValue = JSNApiHelper::ToJSHandle(value);
if (!obj->IsHeapObject()) {
return JSTaggedValue::SetProperty(thread, obj, key, valueValue);
}
return ObjectFastOperator::FastSetPropertyByIndex(thread, obj.GetTaggedValue(),
key, valueValue.GetTaggedValue());
}
bool ObjectRef::SetAccessorProperty(const EcmaVM *vm, Local<JSValueRef> key, Local<FunctionRef> getter,
Local<FunctionRef> setter, PropertyAttribute attribute)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> getterValue = JSNApiHelper::ToJSHandle(getter);
JSHandle<JSTaggedValue> setterValue = JSNApiHelper::ToJSHandle(setter);
PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
desc.SetSetter(setterValue);
desc.SetGetter(getterValue);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
return JSTaggedValue::DefineOwnProperty(thread, obj, keyValue, desc);
}
Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue result;
{
LocalScope scope(vm);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
if (UNLIKELY(!obj->IsHeapObject())) {
OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
result = ret.GetValue().GetTaggedValue();
} else {
result = ObjectFastOperator::FastGetPropertyByValue(thread, obj.GetTaggedValue(),
keyValue.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
}
}
JSHandle<JSTaggedValue> resultValue(thread, result);
return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
}
Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, const char *utf8)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue result;
{
LocalScope scope(vm);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> keyValue(factory->NewFromUtf8(utf8));
if (UNLIKELY(!obj->IsHeapObject())) {
OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
result = ret.GetValue().GetTaggedValue();
} else {
result = ObjectFastOperator::FastGetPropertyByValue(thread, obj.GetTaggedValue(),
keyValue.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
}
}
JSHandle<JSTaggedValue> resultValue(thread, result);
return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
}
Local<JSValueRef> ObjectRef::Get(const EcmaVM *vm, int32_t key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue result;
{
LocalScope scope(vm);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
if (!obj->IsHeapObject()) {
OperationResult ret = JSTaggedValue::GetProperty(thread, obj, key);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
result = ret.GetValue().GetTaggedValue();
} else {
result = ObjectFastOperator::FastGetPropertyByIndex(thread, obj.GetTaggedValue(), key);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
}
}
JSHandle<JSTaggedValue> resultValue(thread, result);
return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
}
bool ObjectRef::GetOwnProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute &property)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<JSTaggedValue> keyValue = JSNApiHelper::ToJSHandle(key);
PropertyDescriptor desc(thread);
bool ret = JSTaggedValue::GetOwnProperty(thread, obj, keyValue, desc);
if (!ret) {
return false;
}
property.SetValue(JSNApiHelper::ToLocal<JSValueRef>(desc.GetValue()));
if (desc.HasGetter()) {
property.SetGetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetGetter()));
}
if (desc.HasSetter()) {
property.SetSetter(JSNApiHelper::ToLocal<JSValueRef>(desc.GetSetter()));
}
if (desc.HasWritable()) {
property.SetWritable(desc.IsWritable());
}
if (desc.HasEnumerable()) {
property.SetEnumerable(desc.IsEnumerable());
}
if (desc.HasConfigurable()) {
property.SetConfigurable(desc.IsConfigurable());
}
return true;
}
Local<ArrayRef> ObjectRef::GetOwnPropertyNames(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<TaggedArray> array(JSTaggedValue::GetOwnPropertyKeys(thread, obj));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
}
Local<ArrayRef> ObjectRef::GetAllPropertyNames(const EcmaVM *vm, uint32_t filter)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> obj(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<TaggedArray> array(JSTaggedValue::GetAllPropertyKeys(thread, obj, filter));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
}
Local<ArrayRef> ObjectRef::GetOwnEnumerablePropertyNames(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSObject> obj(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(obj, ERROR);
JSHandle<TaggedArray> array(JSObject::EnumerableOwnNames(thread, obj));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
return JSNApiHelper::ToLocal<ArrayRef>(jsArray);
}
Local<JSValueRef> ObjectRef::GetPrototype(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSTaggedValue> prototype(thread, JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(object)));
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<JSValueRef>(prototype);
}
bool ObjectRef::SetPrototype(const EcmaVM *vm, Local<ObjectRef> prototype)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
JSHandle<JSObject> proto(JSNApiHelper::ToJSHandle(prototype));
return JSTaggedValue::SetPrototype(thread, JSHandle<JSTaggedValue>(object), JSHandle<JSTaggedValue>(proto));
}
bool ObjectRef::DefineProperty(const EcmaVM *vm, Local<JSValueRef> key, PropertyAttribute attribute)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
PropertyDescriptor desc(thread, attribute.IsWritable(), attribute.IsEnumerable(), attribute.IsConfigurable());
desc.SetValue(JSNApiHelper::ToJSHandle(attribute.GetValue(vm)));
return JSTaggedValue::DefinePropertyOrThrow(thread, object, keyValue, desc);
}
bool ObjectRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
return JSTaggedValue::HasProperty(thread, object, keyValue);
}
bool ObjectRef::Has(const EcmaVM *vm, uint32_t key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(object, ERROR);
return JSTaggedValue::HasProperty(thread, object, key);
}
bool ObjectRef::HasOwnProperty(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
return JSTaggedValue::HasOwnProperty(thread, object, keyValue);
}
bool ObjectRef::Delete(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSTaggedValue> keyValue(JSNApiHelper::ToJSHandle(key));
return JSTaggedValue::DeleteProperty(thread, object, keyValue);
}
bool ObjectRef::Delete(const EcmaVM *vm, uint32_t key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(key));
return JSTaggedValue::DeleteProperty(thread, object, keyHandle);
}
Local<JSValueRef> ObjectRef::Freeze(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSObject> obj(object);
bool status = JSObject::SetIntegrityLevel(thread, obj, ecmascript::IntegrityLevel::FROZEN);
if (JSNApi::HasPendingException(vm)) {
JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
}
if (!status) {
LOG_ECMA(ERROR) << "Freeze: freeze failed";
Local<StringRef> message = StringRef::NewFromUtf8(vm, "Freeze: freeze failed");
Local<JSValueRef> error = Exception::Error(vm, message);
JSNApi::ThrowException(vm, error);
JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
}
JSHandle<JSTaggedValue> resultValue(obj);
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
}
Local<JSValueRef> ObjectRef::Seal(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(object, ERROR);
JSHandle<JSObject> obj(object);
bool status = JSObject::SetIntegrityLevel(thread, obj, ecmascript::IntegrityLevel::SEALED);
if (JSNApi::HasPendingException(vm)) {
JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
}
if (!status) {
LOG_ECMA(ERROR) << "Seal: seal failed";
Local<StringRef> message = StringRef::NewFromUtf8(vm, "Freeze: freeze failed");
Local<JSValueRef> error = Exception::Error(vm, message);
JSNApi::ThrowException(vm, error);
JSHandle<JSTaggedValue> exception(thread, JSTaggedValue::Exception());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(exception));
}
JSHandle<JSTaggedValue> resultValue(obj);
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
}
void ObjectRef::SetNativePointerFieldCount(const EcmaVM *vm, int32_t count)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
DCHECK_SPECIAL_VALUE(this);
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
JSObject::SetNativePointerFieldCount(thread, object, count);
}
int32_t ObjectRef::GetNativePointerFieldCount(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
return object->GetNativePointerFieldCount(vm->GetJSThread());
}
void *ObjectRef::GetNativePointerField(const EcmaVM *vm, int32_t index)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
return object->GetNativePointerField(vm->GetJSThread(), index);
}
void ObjectRef::SetNativePointerField(const EcmaVM *vm, int32_t index, void *nativePointer,
NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
DCHECK_SPECIAL_VALUE(this);
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
JSObject::SetNativePointerField(thread, object, index, nativePointer, callBack, data, nativeBindingsize);
}
void ObjectRef::SetConcurrentNativePointerField(const EcmaVM *vm, int32_t index, void *nativePointer,
NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
DCHECK_SPECIAL_VALUE(this);
JSHandle<JSObject> object(JSNApiHelper::ToJSHandle(this));
JSObject::SetNativePointerField(thread, object, index, nativePointer, callBack, data, nativeBindingsize,
Concurrent::YES);
}
Local<NativePointerRef> NativePointerRef::New(const EcmaVM *vm, void *nativePointer, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, nullptr, nullptr,
false, nativeBindingsize);
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
}
Local<NativePointerRef> NativePointerRef::New(
const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data,
false, nativeBindingsize);
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
}
Local<NativePointerRef> NativePointerRef::NewConcurrent(
const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSNativePointer> obj =
factory->NewJSNativePointer(nativePointer, callBack, data, false, nativeBindingsize, Concurrent::YES);
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
}
Local<NativePointerRef> NativePointerRef::NewSendable(
const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSNativePointer> obj =
factory->NewSJSNativePointer(nativePointer, callBack, data, false, nativeBindingsize);
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
}
void *NativePointerRef::Value()
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
JSHandle<JSTaggedValue> nativePointer = JSNApiHelper::ToJSHandle(this);
return JSHandle<JSNativePointer>(nativePointer)->GetExternalPointer();
}
Local<NativePointerRef> NativePointerRef::NewWrapperData(
const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data,
false, nativeBindingsize, Concurrent::YES, ecmascript::NativeFlag::WRAPPER_DATA);
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
}
Local<ArrayBufferRef> ArrayBufferRef::New(const EcmaVM *vm, int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(length);
return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
}
Local<ArrayBufferRef> ArrayBufferRef::New(
const EcmaVM *vm, void *buffer, int32_t length, const NativePointerCallback &deleter, void *data)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(buffer, length, deleter, data);
return JSNApiHelper::ToLocal<ArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
}
int32_t ArrayBufferRef::ByteLength(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(arrayBuffer, FATAL);
return arrayBuffer->GetArrayBufferByteLength();
}
void *ArrayBufferRef::GetBuffer(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData(vm->GetJSThread());
if (!bufferData.IsJSNativePointer()) {
return nullptr;
}
return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
}
void *ArrayBufferRef::GetBufferAndLength(const EcmaVM *vm, int32_t *length)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData(vm->GetJSThread());
void *data = nullptr;
if (bufferData.IsJSNativePointer()) {
data = JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
}
LOG_IF_SPECIAL(arrayBuffer, FATAL);
*length = arrayBuffer->GetArrayBufferByteLength();
return data;
}
void ArrayBufferRef::Detach(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
arrayBuffer->Detach(thread);
}
bool ArrayBufferRef::IsDetach(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
return arrayBuffer->IsDetach(thread);
}
Local<SendableArrayBufferRef> SendableArrayBufferRef::New(const EcmaVM *vm, int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<ecmascript::JSSendableArrayBuffer> arrayBuffer = factory->NewJSSendableArrayBuffer(length);
return JSNApiHelper::ToLocal<SendableArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
}
Local<SendableArrayBufferRef> SendableArrayBufferRef::New(
const EcmaVM *vm, void *buffer, int32_t length, const NativePointerCallback &deleter, void *data)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<ecmascript::JSSendableArrayBuffer> arrayBuffer =
factory->NewJSSendableArrayBuffer(buffer, length, deleter, data);
return JSNApiHelper::ToLocal<SendableArrayBufferRef>(JSHandle<JSTaggedValue>(arrayBuffer));
}
int32_t SendableArrayBufferRef::ByteLength(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSendableArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(arrayBuffer, FATAL);
return arrayBuffer->GetArrayBufferByteLength();
}
void SendableArrayBufferRef::Detach(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSendableArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
arrayBuffer->Detach(thread);
}
bool SendableArrayBufferRef::IsDetach(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSendableArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
return arrayBuffer->IsDetach(thread);
}
void *SendableArrayBufferRef::GetBuffer(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<ecmascript::JSSendableArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(this));
JSTaggedValue bufferData = arrayBuffer->GetArrayBufferData(vm->GetJSThread());
if (!bufferData.IsJSNativePointer()) {
return nullptr;
}
return JSNativePointer::Cast(bufferData.GetTaggedObject())->GetExternalPointer();
}
Local<DateRef> DateRef::New(const EcmaVM *vm, double time)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
JSHandle<JSFunction> dateFunction(globalEnv->GetDateFunction());
JSHandle<JSDate> dateObject(factory->NewJSObjectByConstructor(dateFunction));
dateObject->SetTimeValue(thread, JSTaggedValue(time));
return JSNApiHelper::ToLocal<DateRef>(JSHandle<JSTaggedValue>(dateObject));
}
Local<StringRef> DateRef::ToString(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(date, ERROR);
JSTaggedValue dateStr = date->ToString(thread);
if (!dateStr.IsString()) {
auto constants = thread->GlobalConstants();
return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
}
JSHandle<JSTaggedValue> dateStrHandle(thread, dateStr);
return JSNApiHelper::ToLocal<StringRef>(dateStrHandle);
}
double DateRef::GetTime(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0.0);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
JSHandle<JSDate> date(JSNApiHelper::ToJSHandle(this));
if (!date->IsDate()) {
LOG_ECMA(ERROR) << "Not a Date Object";
}
return date->GetTimeValue(vm->GetJSThread()).GetDouble();
}
uint32_t TypedArrayRef::ByteLength(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, FATAL);
return typedArray->GetByteLength();
}
uint32_t TypedArrayRef::ByteOffset(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, FATAL);
return typedArray->GetByteOffset();
}
uint32_t TypedArrayRef::ArrayLength(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, FATAL);
return typedArray->GetArrayLength();
}
Local<ArrayBufferRef> TypedArrayRef::GetArrayBuffer(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, ERROR);
JSHandle<JSTaggedValue> arrayBuffer(thread, JSTypedArray::GetOffHeapBuffer(thread, typedArray));
return JSNApiHelper::ToLocal<ArrayBufferRef>(arrayBuffer);
}
uint32_t SendableTypedArrayRef::ByteLength(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, FATAL);
return typedArray->GetByteLength();
}
uint32_t SendableTypedArrayRef::ByteOffset(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, FATAL);
return typedArray->GetByteOffset();
}
uint32_t SendableTypedArrayRef::ArrayLength(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, FATAL);
return typedArray->GetArrayLength();
}
Local<SendableArrayBufferRef> SendableTypedArrayRef::GetArrayBuffer(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<ecmascript::JSSharedTypedArray> typedArray(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(typedArray, ERROR);
JSHandle<JSTaggedValue> arrayBuffer(thread,
ecmascript::JSSharedTypedArray::GetSharedOffHeapBuffer(thread, typedArray));
return JSNApiHelper::ToLocal<SendableArrayBufferRef>(arrayBuffer);
}
Local<FunctionRef> FunctionRef::New(EcmaVM *vm, const Local<JSValueRef> &context, FunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
JSHandle<JSFunction> current(factory->NewNormalJSApiFunction(env,
reinterpret_cast<void *>(Callback::RegisterCallback)));
#else
JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback)));
#endif
JSFunction::SetFunctionExtraInfo(thread, current, reinterpret_cast<void *>(nativeFunc),
deleter, data, nativeBindingsize);
current->SetCallNapi(callNapi);
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
}
Local<FunctionRef> FunctionRef::New(EcmaVM *vm, FunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return New(vm, context, nativeFunc, deleter, data, callNapi, nativeBindingsize);
}
Local<FunctionRef> FunctionRef::NewConcurrent(EcmaVM *vm, const Local<JSValueRef> &context, FunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
JSHandle<JSFunction> current(factory->NewNormalJSApiFunction(env,
reinterpret_cast<void *>(Callback::RegisterCallback)));
#else
JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(Callback::RegisterCallback)));
#endif
JSFunction::SetFunctionExtraInfo(thread, current, reinterpret_cast<void *>(nativeFunc), deleter,
data, nativeBindingsize, Concurrent::YES);
current->SetCallNapi(callNapi);
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
}
Local<FunctionRef> FunctionRef::NewConcurrent(EcmaVM *vm, FunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return NewConcurrent(vm, context, nativeFunc, deleter, data, callNapi, nativeBindingsize);
}
Local<FunctionRef> FunctionRef::New(EcmaVM *vm, const Local<JSValueRef> &context, InternalFunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
JSHandle<JSFunction> current(factory->NewNormalJSApiFunction(env, reinterpret_cast<void *>(nativeFunc)));
#else
JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(nativeFunc)));
#endif
JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize);
current->SetCallNapi(callNapi);
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
}
Local<FunctionRef> FunctionRef::New(EcmaVM *vm, InternalFunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return New(vm, context, nativeFunc, deleter, data, callNapi, nativeBindingsize);
}
Local<FunctionRef> FunctionRef::NewSendable(EcmaVM *vm,
InternalFunctionCallback nativeFunc,
NativePointerCallback deleter,
void *data,
bool callNapi,
size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSFunction> current(factory->NewSFunction(env, reinterpret_cast<void *>(nativeFunc)));
JSFunction::SetSFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize);
current->SetCallNapi(callNapi);
ASSERT(current->GetLexicalEnv(thread) == JSTaggedValue::Undefined());
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
}
Local<FunctionRef> FunctionRef::NewConcurrent(EcmaVM *vm, const Local<JSValueRef> &context,
InternalFunctionCallback nativeFunc, NativePointerCallback deleter, void *data, bool callNapi,
size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSFunction> current(factory->NewJSFunction(env, reinterpret_cast<void *>(nativeFunc)));
JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize, Concurrent::YES);
current->SetCallNapi(callNapi);
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
}
Local<FunctionRef> FunctionRef::NewConcurrent(EcmaVM *vm, InternalFunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return NewConcurrent(vm, context, nativeFunc, deleter, data, callNapi, nativeBindingsize);
}
Local<FunctionRef> FunctionRef::NewConcurrentWithName(EcmaVM *vm, const Local<JSValueRef> &context,
InternalFunctionCallback nativeFunc,
NativePointerCallback deleter, const char *name, void *data,
bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> functionName(factory->NewFromUtf8(name));
PropertyDescriptor nameDesc(thread, functionName, false, false, true);
ecmascript::PropertyAttributes attr(nameDesc);
attr.SetIsInlinedProps(true);
attr.SetOffset(0);
attr.SetRepresentation(ecmascript::Representation::TAGGED);
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetNormalFunctionClass());
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
ecmascript::Representation rep =
ecmascript::PropertyAttributes::TranslateToRep(nameDesc.GetValue().GetTaggedValue());
hclass = JSHClass::SetPropertyOfObjHClass<true>(thread, hclass, globalConst->GetHandledNameString(), attr, rep,
true, JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS);
JSHandle<JSFunction> func = factory->NewNativeFunctionByHClass(hclass, reinterpret_cast<void *>(nativeFunc),
ecmascript::FunctionKind::NORMAL_FUNCTION);
func->SetPropertyInlinedProps<true>(thread, 0, nameDesc.GetValue().GetTaggedValue());
JSFunction::SetFunctionExtraInfo(thread, func, nullptr, deleter, data, nativeBindingsize, Concurrent::YES);
ASSERT_PRINT(func->IsExtensible(), "Function must be extensible");
func->SetCallNapi(callNapi);
func->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(func));
}
Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, const Local<JSValueRef> &context,
FunctionCallback nativeFunc, NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetApiFunctionClassWithoutName());
JSHandle<JSFunction> current =
factory->NewConstructorJSApiFunctionByHClass(reinterpret_cast<void *>(Callback::RegisterCallback), hclass);
#else
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName());
JSHandle<JSFunction> current =
factory->NewJSFunctionByHClass(reinterpret_cast<void *>(Callback::RegisterCallback),
hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
#endif
JSFunction::InitClassFunction(thread, current, callNapi);
JSFunction::SetFunctionExtraInfo(thread, current, reinterpret_cast<void *>(nativeFunc),
deleter, data, nativeBindingsize);
Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return scope.Escape(result);
}
Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, FunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return NewClassFunction(vm, context, nativeFunc, deleter, data, callNapi, nativeBindingsize);
}
Local<FunctionRef> FunctionRef::NewConcurrentClassFunction(EcmaVM *vm, const Local<JSValueRef> &context,
InternalFunctionCallback nativeFunc, NativePointerCallback deleter, void *data, bool callNapi,
size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetApiFunctionClassWithoutName());
JSHandle<JSFunction> current =
factory->NewConstructorJSApiFunctionByHClass(reinterpret_cast<void *>(nativeFunc), hclass);
#else
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName());
JSHandle<JSFunction> current =
factory->NewJSFunctionByHClass(reinterpret_cast<void *>(nativeFunc),
hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
#endif
JSFunction::InitClassFunction(thread, current, callNapi);
JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize, Concurrent::YES);
Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return scope.Escape(result);
}
Local<FunctionRef> FunctionRef::NewConcurrentClassFunctionWithName(
const EcmaVM *vm, const Local<JSValueRef> &context, InternalFunctionCallback nativeFunc,
NativePointerCallback deleter, const char *name, void *data, bool callNapi, size_t propertyCount,
size_t staticPropCount, Local<panda::JSValueRef> *keys, PropertyAttribute *attrs, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
JSHandle<JSFunction> classFunc;
if (propertyCount <= MAX_PROPERTIES_ON_STACK) {
char descs[sizeof(PropertyDescriptor) * MAX_PROPERTIES_ON_STACK];
classFunc = JSNApiClassCreationHelper::CreateClassFuncWithProperties(
thread, name, nativeFunc, callNapi, propertyCount, staticPropCount, keys, attrs,
reinterpret_cast<PropertyDescriptor *>(&descs[0]));
} else {
PropertyDescriptor *descs =
reinterpret_cast<PropertyDescriptor *>(malloc(sizeof(PropertyDescriptor) * propertyCount));
if (descs != nullptr) {
classFunc = JSNApiClassCreationHelper::CreateClassFuncWithProperties(
thread, name, nativeFunc, callNapi, propertyCount, staticPropCount, keys, attrs, descs);
free(descs);
} else {
LOG_FULL(FATAL) << "malloc failed in NewConcurrentClassFunctionWithName";
}
}
classFunc->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
JSFunction::SetFunctionExtraInfo(thread, classFunc, nullptr, deleter, data, nativeBindingsize, Concurrent::YES);
Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(classFunc));
return scope.Escape(result);
}
Local<FunctionRef> FunctionRef::NewConcurrentClassFunction(EcmaVM *vm, InternalFunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return NewConcurrentClassFunction(vm, context, nativeFunc, deleter, data, callNapi, nativeBindingsize);
}
Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, const Local<JSValueRef> &context,
InternalFunctionCallback nativeFunc, NativePointerCallback deleter, void *data, bool callNapi,
size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetApiFunctionClassWithoutName());
JSHandle<JSFunction> current =
factory->NewConstructorJSApiFunctionByHClass(reinterpret_cast<void *>(nativeFunc), hclass);
#else
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutName());
JSHandle<JSFunction> current =
factory->NewJSFunctionByHClass(reinterpret_cast<void *>(nativeFunc),
hclass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
#endif
JSFunction::InitClassFunction(thread, current, callNapi);
JSFunction::SetFunctionExtraInfo(thread, current, nullptr, deleter, data, nativeBindingsize);
Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(current));
current->SetLexicalEnv(thread, JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context)));
return scope.Escape(result);
}
Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, InternalFunctionCallback nativeFunc,
NativePointerCallback deleter, void *data, bool callNapi, size_t nativeBindingsize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread->GetGlobalEnv()));
return NewClassFunction(vm, context, nativeFunc, deleter, data, callNapi, nativeBindingsize);
}
Local<FunctionRef> FunctionRef::NewSendableClassFunction(const EcmaVM *vm,
InternalFunctionCallback nativeFunc,
NativePointerCallback deleter,
void *data,
Local<StringRef> name,
SendablePropertiesInfos &infos,
Local<FunctionRef> parent,
bool callNapi,
size_t nativeBindingSize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
JSNapiSendable sendable(thread, infos, name);
JSHandle<JSHClass> prototypeHClass = JSHClass::CreateSPrototypeHClass(thread, sendable.GetNonStaticDescs());
JSHandle<JSObject> prototype = factory->NewSharedOldSpaceJSObject(prototypeHClass);
JSHandle<JSHClass> constructorHClass = JSHClass::CreateSConstructorHClass(thread, sendable.GetStaticDescs());
JSHandle<JSFunction> constructor = factory->NewSFunctionByHClass(
reinterpret_cast<void *>(nativeFunc), constructorHClass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
sendable.SetSConstructor(constructor);
JSObject::SetSProperties(thread, prototype, sendable.GetNonStaticDescs());
JSObject::SetSProperties(thread, JSHandle<JSObject>::Cast(constructor), sendable.GetStaticDescs());
if (parent->IsHole()) {
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
prototypeHClass->SetPrototype(thread, env->GetSObjectFunctionPrototype());
constructorHClass->SetPrototype(thread, env->GetSFunctionPrototype());
} else if (parent->IsNull()) {
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
prototypeHClass->SetPrototype(thread, JSTaggedValue::Null());
constructorHClass->SetPrototype(thread, env->GetSFunctionPrototype());
} else {
auto parentPrototype = parent->GetFunctionPrototype(vm);
prototypeHClass->SetPrototype(thread, JSNApiHelper::ToJSHandle(parentPrototype));
constructorHClass->SetPrototype(thread, JSNApiHelper::ToJSHandle(parent));
}
prototypeHClass->SetExtensible(false);
constructor->SetHomeObject(thread, prototype);
constructor->SetProtoOrHClass(thread, prototype);
ASSERT(constructor->GetLexicalEnv(thread) == JSTaggedValue::Undefined());
constructor->SetCallNapi(callNapi);
JSFunction::SetSFunctionExtraInfo(thread, constructor, nullptr, deleter, data, nativeBindingSize);
JSHClass *parentIHClass{nullptr};
if (!parent->IsHole() && !parent->IsNull()) {
JSHandle<JSFunction> parentHandle(JSNApiHelper::ToJSHandle(parent));
parentIHClass = reinterpret_cast<JSHClass *>(parentHandle->GetProtoOrHClass(thread).GetTaggedObject());
}
JSHandle<JSHClass> iHClass = JSHClass::CreateSHClass(thread, sendable.GetInstanceDescs(), parentIHClass);
iHClass->SetPrototype(thread, JSHandle<JSTaggedValue>(prototype));
iHClass->SetExtensible(false);
constructor->SetProtoOrHClass(thread, iHClass);
constructorHClass->SetExtensible(false);
Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(constructor));
return scope.Escape(result);
}
Local<JSValueRef> FunctionRef::Call(const EcmaVM *vm, Local<JSValueRef> thisObj,
const Local<JSValueRef> argv[],
int32_t length,
bool clearSingleStepper)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
FunctionCallScope callScope(EcmaVM::ConstCast(vm));
if (!IsFunction(vm)) {
return JSValueRef::Undefined(vm);
}
if (LIKELY(clearSingleStepper)) {
vm->GetJsDebuggerManager()->ClearSingleStepper();
}
JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(func, ERROR);
JSHandle<JSTaggedValue> thisValue = JSNApiHelper::ToJSHandle(thisObj);
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, length);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
for (int32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]);
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(arg.GetTaggedValue().GetRawData());
#endif
info->SetCallArg(i, arg.GetTaggedValue());
}
JSTaggedValue result = JSFunction::Call(info);
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
}
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> resultValue(thread, result);
EcmaVM::ClearKeptObjects(thread);
vm->GetJsDebuggerManager()->NotifyReturnNative();
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
}
JSValueRef* FunctionRef::CallForNapi(const EcmaVM *vm, JSValueRef *thisObj,
JSValueRef *const argv[],
int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, *JSValueRef::Hole(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue result;
FunctionCallScope callScope(EcmaVM::ConstCast(vm));
ASSERT(IsFunction(vm));
{
LocalScope scope(vm);
ecmascript::tooling::JsDebuggerManager *dm = vm->GetJsDebuggerManager();
bool isDebugApp = dm->IsDebugApp();
if (isDebugApp) {
dm->ClearSingleStepper();
}
JSTaggedValue func = *reinterpret_cast<JSTaggedValue *>(this);
JSTaggedValue undefined = thread->GlobalConstants()->GetUndefined();
JSTaggedValue thisValue = undefined;
if (thisObj != nullptr) {
thisValue = *reinterpret_cast<JSTaggedValue *>(thisObj);
}
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, length);
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Hole(vm));
for (int32_t i = 0; i < length; i++) {
if (argv[i]) {
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(JSNApiHelper::ToJSTaggedValue(argv[i]).GetRawData());
#endif
info->SetCallArg(i, JSNApiHelper::ToJSTaggedValue(argv[i]));
}
}
if (LIKELY(thread->IsAsmInterpreter())) {
STACK_LIMIT_CHECK(thread, reinterpret_cast<JSValueRef *>(*JSValueRef::Hole(vm)));
auto *hclass = func.GetTaggedObject()->GetClass();
if (hclass->IsClassConstructor()) {
RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot call",
reinterpret_cast<JSValueRef *>(*JSValueRef::Hole(vm)));
}
result = ecmascript::InterpreterAssembly::Execute(info);
} else {
result = JSFunction::Call(info);
}
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Hole(vm));
EcmaVM::ClearKeptObjects(thread);
if (isDebugApp && dm->IsMixedDebugEnabled()) {
dm->NotifyReturnNative();
}
}
JSHandle<JSTaggedValue> resultValue(thread, result);
return reinterpret_cast<JSValueRef *>(resultValue.GetAddress());
}
Local<JSValueRef> FunctionRef::Constructor(const EcmaVM *vm,
const Local<JSValueRef> argv[],
int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
FunctionCallScope callScope(EcmaVM::ConstCast(vm));
if (!IsFunction(vm)) {
return JSValueRef::Undefined(vm);
}
JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(func, ERROR);
JSHandle<JSTaggedValue> newTarget = func;
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, newTarget, length);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
for (int32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> arg = JSNApiHelper::ToJSHandle(argv[i]);
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(arg.GetTaggedValue().GetRawData());
#endif
info->SetCallArg(i, arg.GetTaggedValue());
}
JSTaggedValue result = JSFunction::Construct(info);
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> resultValue(thread, result);
return JSNApiHelper::ToLocal<JSValueRef>(resultValue);
}
JSValueRef* FunctionRef::ConstructorOptimize(const EcmaVM *vm,
JSValueRef* argv[],
int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, *JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue result;
FunctionCallScope callScope(EcmaVM::ConstCast(vm));
ASSERT(IsFunction(vm));
{
LocalScope scope(vm);
JSTaggedValue func = *reinterpret_cast<JSTaggedValue*>(this);
JSTaggedValue newTarget = func;
JSTaggedValue undefined = thread->GlobalConstants()->GetUndefined();
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, newTarget, length);
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
for (int32_t i = 0; i < length; ++i) {
JSTaggedValue arg =
argv[i] == nullptr ? JSTaggedValue::Undefined() : JSNApiHelper::ToJSTaggedValue(argv[i]);
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(arg.GetRawData());
#endif
info->SetCallArg(i, arg);
}
result = JSFunction::ConstructInternal(info);
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
}
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
JSHandle<JSTaggedValue> resultValue(thread, result);
return reinterpret_cast<JSValueRef*>(resultValue.GetAddress());
}
Local<JSValueRef> FunctionRef::GetFunctionPrototype(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> func = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(func, FATAL);
JSHandle<JSTaggedValue> prototype(thread, JSHandle<JSFunction>(func)->GetFunctionPrototype(thread));
return JSNApiHelper::ToLocal<JSValueRef>(prototype);
}
bool FunctionRef::Inherit(const EcmaVM *vm, Local<FunctionRef> parent)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> parentValue = JSNApiHelper::ToJSHandle(parent);
JSHandle<JSObject> parentHandle = JSHandle<JSObject>::Cast(parentValue);
JSHandle<JSObject> thisHandle = JSHandle<JSObject>::Cast(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(thisHandle, ERROR);
bool res = JSObject::SetPrototype(thread, thisHandle, parentValue);
if (!res) {
return false;
}
JSHandle<JSTaggedValue> parentPrototype(thread, JSFunction::PrototypeGetter(thread, parentHandle));
JSHandle<JSTaggedValue> thisPrototype(thread, JSFunction::PrototypeGetter(thread, thisHandle));
return JSObject::SetPrototype(thread, JSHandle<JSObject>::Cast(thisPrototype), parentPrototype);
}
void FunctionRef::SetName(const EcmaVM *vm, Local<StringRef> name)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSFunction *func = JSFunction::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject());
JSTaggedValue key = JSNApiHelper::ToJSTaggedValue(*name);
JSFunction::SetFunctionNameNoPrefix(thread, func, key);
}
Local<StringRef> FunctionRef::GetName(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this));
JSHandle<JSTaggedValue> name = JSFunctionBase::GetFunctionName(thread, func);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<StringRef>(name));
}
Local<StringRef> FunctionRef::GetSourceCode(const EcmaVM *vm, int lineNumber)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this));
JSHandle<Method> method(thread, func->GetMethod(thread));
const JSPandaFile *jsPandaFile = method->GetJSPandaFile(thread);
DebugInfoExtractor *debugExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile);
ecmascript::CString entry = JSPandaFile::ENTRY_FUNCTION_NAME;
if (!jsPandaFile->IsBundlePack()) {
JSFunction *function = JSFunction::Cast(func.GetTaggedValue().GetTaggedObject());
ecmascript::CString recordName = function->GetRecordName(thread);
ASSERT(!recordName.empty());
entry = recordName;
}
uint32_t mainMethodIndex = jsPandaFile->GetMainMethodIndex(entry);
JSMutableHandle<JSTaggedValue> sourceCodeHandle(thread, BuiltinsBase::GetTaggedString(thread, ""));
if (mainMethodIndex == 0) {
return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
}
const std::string &allSourceCode = debugExtractor->GetSourceCode(panda_file::File::EntityId(mainMethodIndex));
std::string sourceCode = StringHelper::GetSpecifiedLine(allSourceCode, lineNumber);
uint32_t codeLen = sourceCode.length();
if (codeLen == 0) {
return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
}
if (sourceCode[codeLen - 1] == '\r') {
sourceCode = sourceCode.substr(0, codeLen - 1);
}
sourceCodeHandle.Update(BuiltinsBase::GetTaggedString(thread, sourceCode.c_str()));
return scope.Escape(JSNApiHelper::ToLocal<StringRef>(sourceCodeHandle));
}
bool FunctionRef::IsNative(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSFunctionBase> func(thread, JSNApiHelper::ToJSTaggedValue(this));
JSHandle<Method> method(thread, func->GetMethod(thread));
return method->IsNativeWithCallField();
}
void FunctionRef::SetData(const EcmaVM *vm, void *data, NativePointerCallback deleter, [[maybe_unused]] bool callNapi)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> funcValue = JSNApiHelper::ToJSHandle(this);
JSHandle<JSFunction> function(funcValue);
if (function->IsJSShared()) {
JSFunction::SetSFunctionExtraInfo(thread, function, nullptr, deleter, data, 0);
} else {
JSFunction::SetFunctionExtraInfo(thread, function, nullptr, deleter, data, 0);
}
}
void* FunctionRef::GetData(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> funcValue = JSNApiHelper::ToJSHandle(this);
JSHandle<JSFunctionBase> function(funcValue);
JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo(thread);
if (!extraInfoValue.IsNativePointer()) {
return nullptr;
}
auto extraInfo = JSNativePointer::Cast(extraInfoValue.GetTaggedObject());
return extraInfo->GetData();
}
Local<ArrayRef> ArrayRef::New(const EcmaVM *vm, uint32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedNumber arrayLen(length);
JSHandle<JSTaggedValue> array = JSArray::ArrayCreate(thread, arrayLen);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<ArrayRef>(array);
}
uint32_t ArrayRef::Length(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
return JSArray::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetArrayLength();
}
Local<JSValueRef> ArrayRef::GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(obj);
JSHandle<JSTaggedValue> result = JSArray::FastGetPropertyByValue(thread, object, index);
return JSNApiHelper::ToLocal<JSValueRef>(result);
}
bool ArrayRef::SetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> objectHandle = JSNApiHelper::ToJSHandle(obj);
JSHandle<JSTaggedValue> valueHandle = JSNApiHelper::ToJSHandle(value);
return JSArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle);
}
Local<SendableArrayRef> SendableArrayRef::New(const EcmaVM *vm, uint32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedNumber arrayLen(length);
JSHandle<JSTaggedValue> array = ecmascript::JSSharedArray::ArrayCreate(thread, arrayLen);
JSHandle<JSTaggedValue> initialValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
for (uint32_t i = 0; i < length; i++) {
key.Update(JSTaggedValue(i));
JSObject::CreateDataPropertyOrThrow(
thread, JSHandle<JSObject>(array), key, initialValue, ecmascript::JSShared::SCheckMode::SKIP);
}
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<SendableArrayRef>(array);
}
uint32_t SendableArrayRef::Length(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
return ecmascript::JSSharedArray::Cast(JSNApiHelper::ToJSTaggedValue(this).GetTaggedObject())->GetArrayLength();
}
Local<JSValueRef> SendableArrayRef::GetValueAt(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> object = JSNApiHelper::ToJSHandle(obj);
[[maybe_unused]] ecmascript::ConcurrentApiScope<ecmascript::JSSharedArray> scope(thread, object);
JSHandle<JSTaggedValue> result = ecmascript::JSSharedArray::FastGetPropertyByValue(thread, object, index);
return JSNApiHelper::ToLocal<JSValueRef>(result);
}
bool SendableArrayRef::SetProperty(const EcmaVM *vm, Local<JSValueRef> obj, uint32_t index, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> objectHandle = JSNApiHelper::ToJSHandle(obj);
JSHandle<JSTaggedValue> valueHandle = JSNApiHelper::ToJSHandle(value);
return ecmascript::JSSharedArray::SetProperty(
thread, objectHandle, index, valueHandle, true, ecmascript::SCheckMode::CHECK);
}
#define EXCEPTION_ERROR_NEW(name, type) \
Local<JSValueRef> Exception::name(const EcmaVM *vm, Local<StringRef> message) \
{ \
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); \
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread()); \
ObjectFactory *factory = vm->GetFactory(); \
\
JSHandle<EcmaString> messageValue(JSNApiHelper::ToJSHandle(message)); \
JSHandle<JSTaggedValue> result(factory->NewJSError(ErrorType::type, \
messageValue, ecmascript::StackCheck::NO)); \
return JSNApiHelper::ToLocal<JSValueRef>(result); \
}
EXCEPTION_ERROR_ALL(EXCEPTION_ERROR_NEW)
#undef EXCEPTION_ERROR_NEW
FunctionCallScope::FunctionCallScope(EcmaVM *vm) : vm_(vm)
{
vm_->IncreaseCallDepth();
}
FunctionCallScope::~FunctionCallScope()
{
vm_->DecreaseCallDepth();
if (vm_->IsTopLevelCallDepth()) {
ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread());
vm_->ExecutePromisePendingJob();
}
}
JSExecutionScope::JSExecutionScope([[maybe_unused]] const EcmaVM *vm)
{
}
JSExecutionScope::~JSExecutionScope()
{
lastCurrentThread_ = nullptr;
isRevert_ = false;
}
JsiNativeScope::JsiNativeScope(const EcmaVM *vm)
{
thread_ = vm->GetAssociatedJSThread();
#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT
if (vm->IsCollectingScopeLockStats()) {
const_cast<EcmaVM*>(vm)->IncreaseEnterJsiNativeScopeCount();
const_cast<EcmaVM*>(vm)->IncreaseUpdateThreadStateTransCount();
}
#endif
if (LIKELY(!vm->IsEnableCMCGC())) {
oldThreadState_ = static_cast<uint16_t>(thread_->TransferToNonRunning(ecmascript::ThreadState::NATIVE));
hasSwitchState_ = oldThreadState_ != static_cast<uint16_t>(ecmascript::ThreadState::NATIVE);
} else {
isEnableCMCGC_ = true;
hasSwitchState_ = thread_->GetThreadHolder()->TransferToNativeIfInRunning();
}
}
JsiNativeScope::~JsiNativeScope()
{
if (hasSwitchState_) {
if (LIKELY(!isEnableCMCGC_)) {
thread_->TransferInNonRunning(static_cast<ecmascript::ThreadState>(oldThreadState_));
} else {
thread_->GetThreadHolder()->TransferToRunning();
}
}
}
JsiFastNativeScope::JsiFastNativeScope(const EcmaVM *vm)
{
thread_ = vm->GetAssociatedJSThread();
#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT
if (vm->IsCollectingScopeLockStats()) {
const_cast<EcmaVM*>(vm)->IncreaseEnterFastNativeScopeCount();
const_cast<EcmaVM*>(vm)->IncreaseUpdateThreadStateTransCount();
}
#endif
if (LIKELY(!vm->IsEnableCMCGC())) {
oldThreadState_ = static_cast<uint16_t>(thread_->TransferToRunningIfNonRunning());
hasSwitchState_ = oldThreadState_ != static_cast<uint16_t>(ecmascript::ThreadState::RUNNING);
} else {
isEnableCMCGC_ = true;
#ifdef PANDA_JS_ETS_HYBRID_MODE
extraCoroutineSwitchedForInterop_ = InterOpCoroutineToNative(thread_->GetThreadHolder());
#endif
hasSwitchState_ = thread_->GetThreadHolder()->TransferToRunningIfInNative();
}
}
JsiFastNativeScope::~JsiFastNativeScope()
{
if (hasSwitchState_) {
if (LIKELY(!isEnableCMCGC_)) {
thread_->TransferToNonRunningInRunning(static_cast<ecmascript::ThreadState>(oldThreadState_));
} else {
thread_->GetThreadHolder()->TransferToNative();
}
}
#if defined(PANDA_JS_ETS_HYBRID_MODE)
if (isEnableCMCGC_ && extraCoroutineSwitchedForInterop_) {
InterOpCoroutineToRunning(thread_->GetThreadHolder());
}
#endif
}
void *JsiRuntimeCallInfo::GetData()
{
ecmascript::ThreadManagedScope managedScope(thread_);
JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(reinterpret_cast<EcmaRuntimeCallInfo *>(this));
if (!constructor->IsJSFunction()) {
return nullptr;
}
JSHandle<JSFunctionBase> function(constructor);
JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo(thread_);
if (!extraInfoValue.IsJSNativePointer()) {
return nullptr;
}
return JSNativePointer::Cast(extraInfoValue.GetTaggedObject())->GetData();
}
EcmaVM *JsiRuntimeCallInfo::GetVM() const
{
return thread_->GetEcmaVM();
}
PatchErrorCode JSNApi::LoadPatch(EcmaVM *vm, const std::string &patchFileName, const std::string &baseFileName)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, PatchErrorCode::INTERNAL_ERROR);
ecmascript::ThreadManagedScope managedScope(thread);
ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
return quickFixManager->LoadPatch(thread, patchFileName, baseFileName);
}
PatchErrorCode JSNApi::LoadPatch(EcmaVM *vm,
const std::string &patchFileName, uint8_t *patchBuffer, size_t patchSize,
const std::string &baseFileName, uint8_t *baseBuffer, size_t baseSize)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, PatchErrorCode::INTERNAL_ERROR);
ecmascript::ThreadManagedScope managedScope(thread);
ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
return quickFixManager->LoadPatch(
thread, patchFileName, patchBuffer, patchSize, baseFileName, baseBuffer, baseSize);
}
PatchErrorCode JSNApi::UnloadPatch(EcmaVM *vm, const std::string &patchFileName)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, PatchErrorCode::INTERNAL_ERROR);
ecmascript::ThreadManagedScope managedScope(thread);
ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
return quickFixManager->UnloadPatch(thread, patchFileName);
}
* check whether the exception is caused by quickfix methods.
*/
bool JSNApi::IsQuickFixCausedException(EcmaVM *vm, Local<ObjectRef> exception, const std::string &patchFileName)
{
if (exception.IsEmpty()) {
return false;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
JSHandle<JSTaggedValue> exceptionInfo = JSNApiHelper::ToJSHandle(exception);
return quickFixManager->IsQuickFixCausedException(thread, exceptionInfo, patchFileName);
}
* register quickfix query function.
*/
void JSNApi::RegisterQuickFixQueryFunc(EcmaVM *vm, std::function<bool(std::string baseFileName,
std::string &patchFileName,
uint8_t **patchBuffer,
size_t &patchSize)> callBack)
{
CROSS_THREAD_CHECK(vm);
ecmascript::QuickFixManager *quickFixManager = vm->GetQuickFixManager();
quickFixManager->RegisterQuickFixQueryFunc(callBack);
}
bool JSNApi::IsBundle(EcmaVM *vm)
{
return vm->IsBundlePack();
}
void JSNApi::SetBundle(EcmaVM *vm, bool value)
{
vm->SetIsBundlePack(value);
}
bool JSNApi::IsNormalizedOhmUrlPack(EcmaVM *vm)
{
return vm->IsNormalizedOhmUrlPack();
}
bool JSNApi::IsOhmUrl(const std::string &srcName)
{
return ModulePathHelper::IsOhmUrl(srcName.c_str());
}
void JSNApi::SetModuleInfo(EcmaVM *vm, const std::string &assetPath, const std::string &entryPoint)
{
SetAssetPath(vm, assetPath);
size_t pos = entryPoint.find_first_of("/");
if (pos != std::string::npos) {
SetBundleName(vm, entryPoint.substr(0, pos));
ecmascript::CString moduleName = ModulePathHelper::GetModuleName(entryPoint.c_str());
if (!moduleName.empty()) {
SetModuleName(vm, moduleName.c_str());
return;
}
}
std::string errmsg = "SetModuleInfo: entryPoint:" + entryPoint + "is invalid.";
LOG_ECMA(ERROR) << errmsg;
Local<StringRef> message = StringRef::NewFromUtf8(vm, errmsg.c_str());
Local<JSValueRef> error = Exception::Error(vm, message);
JSNApi::ThrowException(vm, error);
}
void JSNApi::SetAssetPath(EcmaVM *vm, const std::string &assetPath)
{
ecmascript::CString path = assetPath.c_str();
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
if (!ModulePathHelper::ValidateAbcPath(path, ecmascript::ValidateFilePath::ABC)) {
LOG_FULL(FATAL) << "Invalid input assetPath: " << assetPath.c_str();
}
#endif
vm->SetAssetPath(path);
}
void JSNApi::SetLoop(EcmaVM *vm, void *loop)
{
vm->SetLoop(loop);
}
void JSNApi::SetWeakFinalizeTaskCallback(EcmaVM *vm, const WeakFinalizeTaskCallback &callback)
{
vm->GetAssociatedJSThread()->SetWeakFinalizeTaskCallback(callback);
}
void JSNApi::SetAsyncCleanTaskCallback(EcmaVM *vm, const NativePointerTaskCallback &callback)
{
vm->GetAssociatedJSThread()->SetAsyncCleanTaskCallback(callback);
}
void JSNApi::SetTriggerGCTaskCallback(EcmaVM *vm, const TriggerGCTaskCallback& callback)
{
vm->GetHeap()->GetIdleGCTrigger()->SetTriggerGCTaskCallback(callback);
}
std::string JSNApi::GetAssetPath(EcmaVM *vm)
{
return vm->GetAssetPath().c_str();
}
void JSNApi::SetMockModuleList(EcmaVM *vm, const std::map<std::string, std::string> &list)
{
vm->SetMockModuleList(list);
}
void JSNApi::SetHmsModuleList(EcmaVM *vm, const std::vector<panda::HmsMap> &list)
{
vm->SetHmsModuleList(list);
}
void JSNApi::SetPkgAliasList(EcmaVM *vm, const std::map<std::string, std::string> &list)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CString> pkgAliasList;
for (auto it = list.begin(); it != list.end(); ++it) {
pkgAliasList.emplace(it->first.c_str(), it->second.c_str());
}
vm->SetPkgAliasList(pkgAliasList);
}
void JSNApi::UpdatePkgAliasList(EcmaVM *vm, const std::map<std::string, std::string> &list)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CString> pkgAliasList;
for (auto &[alias, pkgName]: list) {
pkgAliasList.emplace(alias, pkgName);
}
vm->UpdatePkgAliasList(pkgAliasList);
ecmascript::CMap<uint32_t, EcmaVM *> workerList = vm->GetWorkList();
for (auto &[workerId, workerVm]: workerList) {
workerVm->UpdatePkgAliasList(pkgAliasList);
}
}
void JSNApi::SetPkgNameList(EcmaVM *vm, const std::map<std::string, std::string> &list)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CString> pkgNameList;
for (auto it = list.begin(); it != list.end(); ++it) {
pkgNameList.emplace(it->first.c_str(), it->second.c_str());
}
vm->SetPkgNameList(pkgNameList);
}
void JSNApi::UpdatePkgNameList(EcmaVM *vm, const std::map<std::string, std::string> &list)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CString> pkgNameList;
for (auto &[moduleName, pkgName]: list) {
pkgNameList.emplace(moduleName, pkgName);
}
vm->UpdatePkgNameList(pkgNameList);
ecmascript::CMap<uint32_t, EcmaVM *> workerList = vm->GetWorkList();
for (auto &[workerId, workerVm]: workerList) {
workerVm->UpdatePkgNameList(pkgNameList);
}
}
std::string JSNApi::GetPkgName(EcmaVM *vm, const std::string &moduleName)
{
return vm->GetPkgName(moduleName.c_str()).c_str();
}
void JSNApi::SetpkgContextInfoList(EcmaVM *vm, const std::map<std::string,
std::vector<std::vector<std::string>>> &list)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CMap<ecmascript::CString,
ecmascript::CVector<ecmascript::CString>>> pkgContextInfoList;
for (auto it = list.begin(); it != list.end(); it++) {
const std::vector<std::vector<std::string>> vec = it->second;
ecmascript::CMap<ecmascript::CString, ecmascript::CVector<ecmascript::CString>> map;
for (size_t i = 0; i < vec.size(); i++) {
ecmascript::CString pkgName = vec[i][0].c_str();
ecmascript::CVector<ecmascript::CString> pkgContextInfo;
for (size_t j = 1; j < vec[i].size(); j++) {
pkgContextInfo.emplace_back(vec[i][j].c_str());
}
map.emplace(pkgName, pkgContextInfo);
}
pkgContextInfoList.emplace(it->first.c_str(), map);
}
vm->SetpkgContextInfoList(pkgContextInfoList);
}
void JSNApi::UpdatePkgContextInfoList(EcmaVM *vm,
const std::map<std::string, std::vector<std::vector<std::string>>> &list)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CMap<ecmascript::CString,
ecmascript::CVector<ecmascript::CString>>> pkgContextInfoList;
for (auto &[moduleName, pkgContextInfos]: list) {
ecmascript::CMap<ecmascript::CString, ecmascript::CVector<ecmascript::CString>> map;
for (auto &datas: pkgContextInfos) {
if (datas.empty()) {
continue;
}
ecmascript::CString pkgName = datas[0].c_str();
ecmascript::CVector<ecmascript::CString> pkgContextInfo;
for (size_t i = 1; i < datas.size(); i++) {
pkgContextInfo.emplace_back(datas[i].c_str());
}
map.emplace(pkgName, pkgContextInfo);
}
pkgContextInfoList.emplace(moduleName, map);
}
vm->UpdatePkgContextInfoList(pkgContextInfoList);
ecmascript::CMap<uint32_t, EcmaVM *> workerList = vm->GetWorkList();
for (auto &[workerId, workerVm]: workerList) {
workerVm->UpdatePkgContextInfoList(pkgContextInfoList);
}
}
void JSNApi::SetPkgContextInfoList(EcmaVM *vm, const std::unordered_map<std::string,
std::pair<std::unique_ptr<uint8_t[]>, size_t>> &pkgInfoMap)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CMap<ecmascript::CString,
ecmascript::CVector<ecmascript::CString>>> pkgContextInfoList;
ecmascript::CMap <ecmascript::CString, ecmascript::CString> pkgAliasList;
ecmascript::CUnorderedMap<ecmascript::CString, ecmascript::CUnorderedMap<ecmascript::CString,
ecmascript::CUnorderedSet<ecmascript::CString>>> ohExportsList;
ecmascript::ohos::ModulePkgParser::ParseModulePkgJson(vm, pkgInfoMap, pkgContextInfoList, pkgAliasList,
ohExportsList);
vm->SetpkgContextInfoList(pkgContextInfoList);
vm->SetPkgAliasList(pkgAliasList);
vm->SetOhExportsList(ohExportsList);
}
void JSNApi::UpdatePkgContextInfoList(EcmaVM *vm, const std::unordered_map<std::string,
std::pair<std::unique_ptr<uint8_t[]>, size_t>> &pkgInfoMap)
{
ecmascript::CMap<ecmascript::CString, ecmascript::CMap<ecmascript::CString,
ecmascript::CVector<ecmascript::CString>>> pkgContextInfoList;
ecmascript::CMap <ecmascript::CString, ecmascript::CString> pkgAliasList;
ecmascript::CUnorderedMap<ecmascript::CString, ecmascript::CUnorderedMap<ecmascript::CString,
ecmascript::CUnorderedSet<ecmascript::CString>>> ohExportsMap;
ecmascript::ohos::ModulePkgParser::ParseModulePkgJson(vm, pkgInfoMap, pkgContextInfoList, pkgAliasList,
ohExportsMap);
vm->UpdatePkgContextInfoList(pkgContextInfoList);
vm->UpdatePkgAliasList(pkgAliasList);
vm->UpdateOhExportsList(ohExportsMap);
ecmascript::CMap<uint32_t, EcmaVM *> workerList = vm->GetWorkList();
for (auto &[_, workerVm]: workerList) {
workerVm->UpdatePkgContextInfoList(pkgContextInfoList);
workerVm->UpdatePkgAliasList(pkgAliasList);
workerVm->UpdateOhExportsList(ohExportsMap);
}
}
void JSNApi::SetExecuteBufferMode(const EcmaVM *vm)
{
ecmascript::ModuleManager *moduleManager =
vm->GetAssociatedJSThread()->GetModuleManager();
moduleManager->SetExecuteMode(ecmascript::ModuleExecuteMode::ExecuteBufferMode);
}
void JSNApi::SetStopPreLoadSoCallback(EcmaVM *vm, const StopPreLoadSoCallback &callback)
{
vm->AddStopPreLoadCallback(callback);
}
bool JSNApi::InitForConcurrentThread(EcmaVM *vm, ConcurrentCallback cb, void *data)
{
vm->SetConcurrentCallback(cb, data);
return true;
}
bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local<JSValueRef> function, void *taskInfo)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<JSTaggedValue> funcVal = JSNApiHelper::ToJSHandle(function);
JSHandle<JSFunction> transFunc = JSHandle<JSFunction>::Cast(funcVal);
if (transFunc->GetFunctionKind(thread) != ecmascript::FunctionKind::CONCURRENT_FUNCTION) {
LOG_ECMA(ERROR) << "Function is not concurrent";
return false;
}
JSFunction::SetFunctionExtraInfo(thread, transFunc, nullptr, nullptr, taskInfo);
transFunc->SetTaskConcurrentFuncFlag(1);
thread->SetTaskInfo(reinterpret_cast<uintptr_t>(taskInfo));
thread->SetIsInConcurrentScope(true);
return true;
}
void* JSNApi::GetCurrentTaskInfo(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
return reinterpret_cast<void*>(thread->GetTaskInfo());
}
void JSNApi::ClearCurrentTaskInfo(const EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
thread->SetTaskInfo(reinterpret_cast<uintptr_t>(nullptr));
thread->SetIsInConcurrentScope(false);
}
void JSNApi::SetLargeHeap(bool isLargeHeap)
{
LOG_ECMA(DEBUG) << "Set large heap: " << isLargeHeap;
auto instance = ecmascript::Runtime::GetInstance();
ASSERT(instance != nullptr);
instance->SetEnableLargeHeap(isLargeHeap);
}
void JSNApi::SetBundleName(EcmaVM *vm, const std::string &bundleName)
{
ecmascript::CString name = bundleName.c_str();
vm->SetBundleName(name);
}
std::string JSNApi::GetBundleName(EcmaVM *vm)
{
return vm->GetBundleName().c_str();
}
void JSNApi::SetModuleName(EcmaVM *vm, const std::string &moduleName)
{
ecmascript::CString name = moduleName.c_str();
ecmascript::pgo::PGOProfilerManager::GetInstance()->SetModuleName(moduleName);
vm->SetModuleName(name);
}
std::string JSNApi::GetModuleName(EcmaVM *vm)
{
return vm->GetModuleName().c_str();
}
void JSNApi::SetThreadName(EcmaVM *vm, const std::string &name)
{
CROSS_THREAD_CHECK(vm);
vm->GetJSThread()->SetThreadName(name);
}
std::pair<std::string, std::string> JSNApi::GetCurrentModuleInfo(EcmaVM *vm, bool needRecordName)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return vm->GetCurrentModuleInfo(needRecordName);
}
std::string JSNApi::NormalizePath(const std::string &string)
{
return PathHelper::NormalizePath(string.c_str()).c_str();
}
void JSNApi::AllowCrossThreadExecution(EcmaVM *vm)
{
LOG_ECMA(WARN) << "enable cross thread execution";
vm->GetAssociatedJSThread()->SetCrossThreadExecution(true);
}
bool JSNApi::CheckAndSetAllowCrossThreadExecution(EcmaVM *vm)
{
if (ecmascript::g_isEnableCMCGC) {
return false;
} else {
if (vm->GetHeap()->InGC() || SharedHeap::GetInstance()->InGC()) {
return false;
}
LOG_ECMA(WARN) << "enable cross thread execution when not in gc process";
vm->GetAssociatedJSThread()->SetCrossThreadExecution(true);
return true;
}
}
void JSNApi::DisallowCrossThreadExecution(EcmaVM *vm)
{
LOG_ECMA(WARN) << "disable cross thread execution";
vm->GetAssociatedJSThread()->SetCrossThreadExecution(false);
}
void* JSNApi::GetEnv(EcmaVM *vm)
{
JSThread *thread = vm->GetJSThread();
return thread->GetEnv();
}
void JSNApi::SetEnv(EcmaVM *vm, void *env)
{
JSThread *thread = vm->GetJSThread();
thread->SetEnv(env);
}
void JSNApi::SynchronizVMInfo(EcmaVM *vm, const EcmaVM *hostVM)
{
std::atomic_thread_fence(std::memory_order_seq_cst);
vm->SetBundleName(hostVM->GetBundleName());
vm->SetModuleName(hostVM->GetModuleName());
vm->SetAssetPath(hostVM->GetAssetPath());
vm->SetIsBundlePack(hostVM->IsBundlePack());
vm->SetPkgNameList(const_cast<EcmaVM *>(hostVM)->GetPkgNameList());
vm->SetPkgAliasList(const_cast<EcmaVM *>(hostVM)->GetPkgAliasList());
vm->SetpkgContextInfoList(const_cast<EcmaVM *>(hostVM)->GetPkgContextInfoList());
vm->SetOhExportsList(const_cast<EcmaVM *>(hostVM)->GetOhExportList());
ecmascript::ModuleManager *vmModuleManager =
vm->GetAssociatedJSThread()->GetModuleManager();
ecmascript::ModuleManager *hostVMModuleManager =
hostVM->GetAssociatedJSThread()->GetModuleManager();
vmModuleManager->SetExecuteMode(hostVMModuleManager->GetExecuteMode());
vm->SetResolveBufferCallback(hostVM->GetResolveBufferCallback());
vm->SetResolveBufferCallbackForHybridApp(hostVM->GetResolveBufferCallbackForHybridApp());
}
bool JSNApi::GetEnableAsmInterpreter(const EcmaVM *vm)
{
if (vm == nullptr) {
return false;
}
return const_cast<EcmaVM *>(vm)->GetJSOptions().GetEnableAsmInterpreter();
}
std::string JSNApi::GetStubFile(const EcmaVM *vm)
{
if (vm == nullptr) {
return "";
}
return const_cast<EcmaVM *>(vm)->GetJSOptions().GetStubFile();
}
bool JSNApi::IsProfiling(EcmaVM *vm)
{
return vm->GetProfilerState();
}
void JSNApi::SetProfilerState(const EcmaVM *vm, bool value)
{
const_cast<EcmaVM*>(vm)->SetProfilerState(value);
}
void JSNApi::SetSourceMapTranslateCallback(EcmaVM *vm, SourceMapTranslateCallback callback)
{
vm->SetSourceMapTranslateCallback(callback);
}
void JSNApi::SetSourceMapCallback(EcmaVM *vm, SourceMapCallback callback)
{
vm->SetSourceMapCallback(callback);
}
void JSNApi::GetStackBeforeCallNapiSuccess([[maybe_unused]] EcmaVM *vm,
[[maybe_unused]] bool &getStackBeforeCallNapiSuccess)
{
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
JSThread *thread = vm->GetJSThread();
if (thread->GetIsProfiling()) {
ecmascript::ThreadManagedScope managedScope(thread);
getStackBeforeCallNapiSuccess = vm->GetProfiler()->GetStackBeforeCallNapi(thread);
}
#endif
}
void JSNApi::GetStackAfterCallNapi([[maybe_unused]] EcmaVM *vm)
{
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
JSThread *thread = vm->GetJSThread();
if (thread->GetIsProfiling()) {
ecmascript::ThreadManagedScope managedScope(thread);
vm->GetProfiler()->GetStackAfterCallNapi(thread);
}
#endif
}
EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option)
{
JSRuntimeOptions runtimeOptions;
runtimeOptions.SetArkProperties(option.GetArkProperties());
runtimeOptions.SetMemConfigProperty(option.GetMemConfigProperty());
runtimeOptions.SetArkBundleName(option.GetArkBundleName());
runtimeOptions.SetLongPauseTime(option.GetLongPauseTime());
runtimeOptions.SetGcThreadNum(option.GetGcThreadNum());
runtimeOptions.SetIsWorker(option.GetIsWorker());
runtimeOptions.SetIsRestrictedWorker(option.GetIsRestrictedWorker());
#if !defined(PANDA_TARGET_IOS)
runtimeOptions.SetEnableAsmInterpreter(option.GetEnableAsmInterpreter());
#else
runtimeOptions.SetEnableAsmInterpreter(false);
#endif
runtimeOptions.SetEnableBuiltinsLazy(option.GetEnableBuiltinsLazy());
runtimeOptions.SetAsmOpcodeDisableRange(option.GetAsmOpcodeDisableRange());
#ifdef ANDROID_PLATFORM
if (!option.GetStubFile().empty()) {
runtimeOptions.SetStubFile(option.GetStubFile());
}
#endif
runtimeOptions.SetEnableAOT(option.GetEnableAOT());
runtimeOptions.SetEnablePGOProfiler(option.GetEnableProfile());
runtimeOptions.SetPGOProfilerPath(option.GetProfileDir());
runtimeOptions.SetLogLevel(common::Log::LevelToString(common::Log::ConvertFromRuntime(option.GetLogLevel())));
runtimeOptions.SetEnableArkTools(option.GetEnableArkTools());
runtimeOptions.SetLargeHeap(option.GetLargeHeap());
return CreateEcmaVM(runtimeOptions);
}
EcmaVM *JSNApi::CreateEcmaVM(const JSRuntimeOptions &options)
{
return EcmaVM::Create(options);
}
void JSNApi::DestroyJSVM(EcmaVM *ecmaVm)
{
if (UNLIKELY(ecmaVm == nullptr)) {
return;
}
ecmaVm->GetJSThread()->ManagedCodeBegin();
EcmaVM::Destroy(ecmaVm);
}
void JSNApi::IgnoreFinalizeCallback(EcmaVM *ecmaVm)
{
CROSS_THREAD_CHECK(ecmaVm);
ecmascript::ThreadManagedScope scope(thread);
if (ecmascript::g_isEnableCMCGC) {
thread->IgnoreFinalizeCallback();
}
}
void JSNApi::RegisterUncatchableErrorHandler(EcmaVM *ecmaVm, const UncatchableErrorHandler &handler)
{
ecmaVm->RegisterUncatchableErrorHandler(handler);
}
JSNApi::UncatchableErrorHandler JSNApi::GetUncatchableErrorHandler(const EcmaVM *ecmaVm)
{
return ecmaVm->GetUncatchableErrorHandler();
}
void JSNApi::TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType)
{
TriggerGC(vm, ecmascript::GCReason::EXTERNAL_TRIGGER, gcType);
}
void JSNApi::TriggerGC(const EcmaVM *vm, ecmascript::GCReason reason, TRIGGER_GC_TYPE gcType)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
if (thread != nullptr && vm->IsInitialized()) {
#if defined(ENABLE_EXCEPTION_BACKTRACE)
if (thread->IsMainThreadFast()) {
LOG_ECMA(INFO) << "JSNApi::TriggerGC gcType: " << static_cast<int>(gcType);
std::ostringstream stack;
ecmascript::Backtrace(stack, true);
LOG_ECMA(INFO) << stack.str();
}
#endif
if (ecmascript::g_isEnableCMCGC) {
common::GCReason cmcReason = common::GC_REASON_USER;
bool async = true;
if (gcType == TRIGGER_GC_TYPE::FULL_GC || gcType == TRIGGER_GC_TYPE::SHARED_FULL_GC ||
reason == ecmascript::GCReason::ALLOCATION_FAILED) {
cmcReason = common::GC_REASON_BACKUP;
async = false;
}
common::BaseRuntime::RequestGC(cmcReason, async, common::GC_TYPE_FULL);
} else {
auto sHeap = ecmascript::SharedHeap::GetInstance();
switch (gcType) {
case TRIGGER_GC_TYPE::SEMI_GC:
vm->CollectGarbage(vm->GetHeap()->SelectGCType(), reason);
break;
case TRIGGER_GC_TYPE::OLD_GC:
vm->CollectGarbage(ecmascript::TriggerGCType::OLD_GC, reason);
break;
case TRIGGER_GC_TYPE::FULL_GC:
vm->CollectGarbage(ecmascript::TriggerGCType::FULL_GC, reason);
break;
case TRIGGER_GC_TYPE::SHARED_GC:
sHeap->CollectGarbage<ecmascript::TriggerGCType::SHARED_GC,
ecmascript::GCReason::EXTERNAL_TRIGGER>(thread);
break;
case TRIGGER_GC_TYPE::SHARED_FULL_GC:
sHeap->CollectGarbage<ecmascript::TriggerGCType::SHARED_FULL_GC,
ecmascript::GCReason::EXTERNAL_TRIGGER>(thread);
break;
default:
break;
}
}
}
}
void JSNApi::HintGC(const EcmaVM *vm, MemoryReduceDegree degree, ecmascript::GCReason reason)
{
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
if (thread != nullptr && vm->IsInitialized()) {
const_cast<ecmascript::Heap *>(vm->GetHeap())->CheckAndTriggerHintGC(degree, reason);
}
}
void JSNApi::TriggerIdleGC(const EcmaVM *vm, TRIGGER_IDLE_GC_TYPE gcType)
{
CROSS_THREAD_CHECK(vm);
if (thread != nullptr && vm->IsInitialized()) {
ecmascript::ThreadManagedScope managedScope(thread);
vm->GetHeap()->GetIdleGCTrigger()->TryTriggerIdleGC(gcType);
}
}
size_t JSNApi::GetEcmaVMExpectedMemoryReclamationSize(const EcmaVM *vm)
{
if (vm == nullptr) {
LOG_ECMA(ERROR) << "get expected memory reclamation size but vm is nullptr";
return 0;
}
return vm->GetHeap()->GetIdleGCTrigger()->GetExpectedMemoryReclamationSize();
}
void JSNApi::SetStartIdleMonitorCallback(const StartIdleMonitorCallback& callback)
{
startIdleMonitorCallback_ = callback;
}
StartIdleMonitorCallback JSNApi::GetStartIdleMonitorCallback()
{
return startIdleMonitorCallback_;
}
void JSNApi::SetNotifyDeferFreezeCallback(const NotifyDeferFreezeCallback& callback)
{
ecmascript::Runtime::GetInstance()->SetNotifyDeferFreezeCallback(callback);
}
void JSNApi::ThrowException(const EcmaVM *vm, Local<JSValueRef> error)
{
auto thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
if (thread->HasPendingException()) {
LOG_ECMA(DEBUG) << "An exception has already occurred before, keep old exception here.";
return;
}
thread->SetException(JSNApiHelper::ToJSTaggedValue(*error));
}
void JSNApi::PrintExceptionInfo(const EcmaVM *vm)
{
JSThread* thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] ecmascript::EcmaHandleScope handleScope(thread);
if (!HasPendingException(vm)) {
return;
}
Local<ObjectRef> exception = GetAndClearUncaughtException(vm);
JSHandle<JSTaggedValue> exceptionHandle = JSNApiHelper::ToJSHandle(exception);
if (exceptionHandle->IsJSError()) {
ecmascript::base::ErrorHelper::PrintJSErrorInfo(thread, exceptionHandle);
ThrowException(vm, exception);
return;
}
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, exceptionHandle);
ecmascript::CString string = ConvertToString(thread, *result);
LOG_ECMA(WARN) << string;
ThrowException(vm, exception);
}
void JSNApi::SetOnErrorCallback(EcmaVM *vm, OnErrorCallback cb, void* data)
{
JSThread* thread = vm->GetJSThread();
thread->SetOnErrorCallback(cb, data);
}
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER) && !defined(PANDA_TARGET_IOS)
bool JSNApi::StartDebuggerCheckParameters(EcmaVM *vm, const DebugOption &option, int32_t instanceId,
const DebuggerPostTask &debuggerPostTask)
{
if (vm == nullptr) {
LOG_ECMA(ERROR) << "[StartDebugger] vm is nullptr";
return false;
}
if (option.port < 0) {
LOG_ECMA(ERROR) << "[StartDebugger] option.port is -1" ;
return false;
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
const auto &handler = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
if (handler.IsValid()) {
LOG_ECMA(ERROR) << "[StartDebugger] handler has already loaded";
return false;
}
if (option.libraryPath == nullptr) {
LOG_ECMA(ERROR) << "[StartDebugger] option.libraryPath is nullptr";
return false;
}
auto handle = panda::os::library_loader::Load(std::string(option.libraryPath));
if (!handle) {
LOG_ECMA(ERROR) << "[StartDebugger] Load library fail: " << option.libraryPath << " " << errno;
return false;
}
auto sym = panda::os::library_loader::ResolveSymbol(handle.Value(), "StartDebug");
if (!sym) {
LOG_ECMA(ERROR) << "[StartDebugger] Resolve symbol fail: " << sym.Error().ToString();
return false;
}
using StartDebugger = bool (*)(
const std::string &, EcmaVM *, bool, int32_t, const DebuggerPostTask &, int);
vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode);
vm->GetJsDebuggerManager()->SetIsDebugApp(true);
vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(handle.Value()));
vm->GetJsDebuggerManager()->SetFaApp(option.isFaApp);
bool ret = reinterpret_cast<StartDebugger>(sym.Value())(
"PandaDebugger", vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
if (!ret) {
vm->GetJsDebuggerManager()->SetDebugMode(false);
panda::os::library_loader::LibraryHandle libraryHandle(nullptr);
vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(libraryHandle));
}
return ret;
}
#endif
bool JSNApi::StartDebugger([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] const DebugOption &option,
[[maybe_unused]] int32_t instanceId,
[[maybe_unused]] const DebuggerPostTask &debuggerPostTask)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
#if !defined(PANDA_TARGET_IOS)
LOG_ECMA(INFO) << "JSNApi::StartDebugger, isDebugMode = " << option.isDebugMode
<< ", port = " << option.port << ", instanceId = " << instanceId;
return StartDebuggerCheckParameters(vm, option, instanceId, debuggerPostTask);
#else
if (vm == nullptr) {
return false;
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode);
vm->GetJsDebuggerManager()->SetFaApp(option.isFaApp);
bool ret = OHOS::ArkCompiler::Toolchain::StartDebug(
DEBUGGER_NAME, vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
if (!ret) {
vm->GetJsDebuggerManager()->SetDebugMode(false);
}
return ret;
#endif
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
bool JSNApi::StartDebuggerForOldProcess([[maybe_unused]] EcmaVM *vm, [[maybe_unused]] const DebugOption &option,
[[maybe_unused]] int32_t instanceId,
[[maybe_unused]] const DebuggerPostTask &debuggerPostTask)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
#if !defined(PANDA_TARGET_IOS)
LOG_ECMA(INFO) << "JSNApi::StartDebuggerForOldProcess, isDebugMode = " << option.isDebugMode
<< ", instanceId = " << instanceId;
if (vm == nullptr) {
LOG_ECMA(ERROR) << "[StartDebuggerForOldProcess] vm is nullptr";
return false;
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
const auto &handle = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
if (!handle.IsValid()) {
LOG_ECMA(ERROR) << "[StartDebuggerForOldProcess] Get library handle fail: " << option.libraryPath;
return false;
}
using StartDebug = bool (*)(
const std::string &, EcmaVM *, bool, int32_t, const DebuggerPostTask &, int);
auto sym = panda::os::library_loader::ResolveSymbol(handle, "StartDebug");
if (!sym) {
LOG_ECMA(ERROR) << "[StartDebuggerForOldProcess] Resolve symbol fail: " << sym.Error().ToString();
return false;
}
bool ret = reinterpret_cast<StartDebug>(sym.Value())(
"PandaDebugger", vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
if (!ret) {
vm->GetJsDebuggerManager()->SetDebugMode(false);
panda::os::library_loader::LibraryHandle libraryHandle(nullptr);
vm->GetJsDebuggerManager()->SetDebugLibraryHandle(std::move(libraryHandle));
}
return ret;
#else
if (vm == nullptr) {
LOG_ECMA(ERROR) << "[StartDebuggerForOldProcess] vm is nullptr";
return false;
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
vm->GetJsDebuggerManager()->SetDebugMode(option.isDebugMode);
bool ret = OHOS::ArkCompiler::Toolchain::StartDebug(
DEBUGGER_NAME, vm, option.isDebugMode, instanceId, debuggerPostTask, option.port);
if (!ret) {
vm->GetJsDebuggerManager()->SetDebugMode(false);
}
return ret;
#endif
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
bool JSNApi::StartDebuggerForSocketPair([[maybe_unused]] int tid, [[maybe_unused]] int socketfd)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
LOG_ECMA(INFO) << "JSNApi::StartDebuggerForSocketPair, tid = " << tid << ", socketfd = " << socketfd;
JsDebuggerManager *jsDebuggerManager = JsDebuggerManager::GetJsDebuggerManager(tid);
if (jsDebuggerManager == nullptr) {
LOG_ECMA(ERROR) << "[StartDebuggerForSocketPair] jsDebuggerManager is nullptr";
return false;
}
const auto &handle = jsDebuggerManager->GetDebugLibraryHandle();
if (!handle.IsValid()) {
LOG_ECMA(ERROR) << "[StartDebuggerForSocketPair] Get library handle fail";
return false;
}
using StartDebugForSocketpair = bool (*)(int, int, bool);
auto sym = panda::os::library_loader::ResolveSymbol(handle, "StartDebugForSocketpair");
if (!sym) {
LOG_ECMA(ERROR) << "[StartDebuggerForSocketPair] Resolve symbol fail: " << sym.Error().ToString();
return false;
}
bool ret = reinterpret_cast<StartDebugForSocketpair>(sym.Value())(tid, socketfd, false);
if (!ret) {
jsDebuggerManager->SetDebugMode(false);
panda::os::library_loader::LibraryHandle libraryHandle(nullptr);
jsDebuggerManager->SetDebugLibraryHandle(std::move(libraryHandle));
}
return ret;
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
bool JSNApi::NotifyDebugMode([[maybe_unused]] int tid,
[[maybe_unused]] EcmaVM *vm,
[[maybe_unused]] const DebugOption &option,
[[maybe_unused]] int32_t instanceId,
[[maybe_unused]] const DebuggerPostTask &debuggerPostTask,
[[maybe_unused]] bool debugApp)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
LOG_ECMA(INFO) << "JSNApi::NotifyDebugMode, tid = " << tid << ", debugApp = " << debugApp
<< ", isDebugMode = " << option.isDebugMode << ", instanceId = " << instanceId;
if (vm == nullptr) {
LOG_ECMA(ERROR) << "[NotifyDebugMode] vm is nullptr";
return false;
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
bool ret = false;
if (!debugApp) {
return true;
}
if (option.libraryPath == nullptr) {
LOG_ECMA(ERROR) << "[NotifyDebugMode] option.libraryPath is nullptr";
return false;
}
JsDebuggerManager *jsDebuggerManager = vm->GetJsDebuggerManager();
auto handle = panda::os::library_loader::Load(std::string(option.libraryPath));
if (!handle) {
LOG_ECMA(ERROR) << "[NotifyDebugMode] Load library fail: " << option.libraryPath << " " << errno;
return false;
}
JsDebuggerManager::AddJsDebuggerManager(tid, jsDebuggerManager);
jsDebuggerManager->SetDebugLibraryHandle(std::move(handle.Value()));
jsDebuggerManager->SetDebugMode(option.isDebugMode && debugApp);
jsDebuggerManager->SetIsDebugApp(debugApp);
jsDebuggerManager->SetFaApp(option.isFaApp);
#ifdef PANDA_TARGET_ARM32
ret = StartDebuggerForOldProcess(vm, option, instanceId, debuggerPostTask);
#else
ret = true;
#endif
using StoreDebuggerInfo = void (*)(int, EcmaVM *, const DebuggerPostTask &);
auto symOfStoreDebuggerInfo = panda::os::library_loader::ResolveSymbol(
jsDebuggerManager->GetDebugLibraryHandle(), "StoreDebuggerInfo");
if (!symOfStoreDebuggerInfo) {
LOG_ECMA(ERROR) << "[NotifyDebugMode] Resolve StoreDebuggerInfo symbol fail: " <<
symOfStoreDebuggerInfo.Error().ToString();
return false;
}
reinterpret_cast<StoreDebuggerInfo>(symOfStoreDebuggerInfo.Value())(tid, vm, debuggerPostTask);
#ifndef PANDA_TARGET_ARM32
using InitializeDebuggerForSocketpair = bool(*)(void*, bool);
auto sym = panda::os::library_loader::ResolveSymbol(
jsDebuggerManager->GetDebugLibraryHandle(), "InitializeDebuggerForSocketpair");
if (!sym) {
LOG_ECMA(ERROR) << "[NotifyDebugMode] Resolve InitializeDebuggerForSocketpair symbol fail: "
<< sym.Error().ToString();
return false;
}
if (!reinterpret_cast<InitializeDebuggerForSocketpair>(sym.Value())(vm, false)) {
LOG_ECMA(ERROR) << "[NotifyDebugMode] InitializeDebuggerForSocketpair fail";
return false;
}
#endif
if (option.isDebugMode) {
using WaitForDebugger = void (*)(EcmaVM *);
auto symOfWaitForDebugger = panda::os::library_loader::ResolveSymbol(
jsDebuggerManager->GetDebugLibraryHandle(), "WaitForDebugger");
if (!symOfWaitForDebugger) {
LOG_ECMA(ERROR) << "[NotifyDebugMode] Resolve symbol WaitForDebugger fail: " <<
symOfWaitForDebugger.Error().ToString();
return false;
}
reinterpret_cast<WaitForDebugger>(symOfWaitForDebugger.Value())(vm);
}
auto anFileDataMgr = ecmascript::AnFileDataManager::GetInstance();
if (anFileDataMgr != nullptr && anFileDataMgr->SafeGetStubFileInfo()) {
anFileDataMgr->SafeGetStubFileInfo()->RegisterToDebugger();
}
return ret;
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
bool JSNApi::StoreDebugInfo([[maybe_unused]] int tid,
[[maybe_unused]] EcmaVM *vm,
[[maybe_unused]] const DebugOption &option,
[[maybe_unused]] const DebuggerPostTask &debuggerPostTask,
[[maybe_unused]] bool debugApp)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
LOG_ECMA(INFO) << "JSNApi::StoreDebugInfo, tid = " << tid;
if (vm == nullptr) {
LOG_ECMA(ERROR) << "[StoreDebugInfo] vm is nullptr";
return false;
}
JsDebuggerManager *jsDebuggerManager = vm->GetJsDebuggerManager();
const auto &handler = jsDebuggerManager->GetDebugLibraryHandle();
if (handler.IsValid()) {
LOG_ECMA(INFO) << "[StoreDebugInfo] handler has already loaded";
return false;
}
if (option.libraryPath == nullptr) {
LOG_ECMA(ERROR) << "[StoreDebugInfo] option.libraryPath is nullptr";
return false;
}
auto handle = panda::os::library_loader::Load(std::string(option.libraryPath));
if (!handle) {
LOG_ECMA(ERROR) << "[StoreDebugInfo] Load library fail: " << option.libraryPath << " " << errno;
return false;
}
JsDebuggerManager::AddJsDebuggerManager(tid, jsDebuggerManager);
jsDebuggerManager->SetDebugLibraryHandle(std::move(handle.Value()));
jsDebuggerManager->SetDebugMode(option.isDebugMode && debugApp);
jsDebuggerManager->SetIsDebugApp(debugApp);
using StoreDebuggerInfo = void (*)(int, EcmaVM *, const DebuggerPostTask &);
auto symOfStoreDebuggerInfo = panda::os::library_loader::ResolveSymbol(
jsDebuggerManager->GetDebugLibraryHandle(), "StoreDebuggerInfo");
if (!symOfStoreDebuggerInfo) {
LOG_ECMA(ERROR) << "[StoreDebugInfo] Resolve StoreDebuggerInfo symbol fail: " <<
symOfStoreDebuggerInfo.Error().ToString();
return false;
}
reinterpret_cast<StoreDebuggerInfo>(symOfStoreDebuggerInfo.Value())(tid, vm, debuggerPostTask);
bool ret = false;
using InitializeDebuggerForSocketpair = bool(*)(void*, bool);
auto sym = panda::os::library_loader::ResolveSymbol(handler, "InitializeDebuggerForSocketpair");
if (!sym) {
LOG_ECMA(ERROR) << "[InitializeDebuggerForSocketpair] Resolve symbol fail: " << sym.Error().ToString();
return false;
}
ret = reinterpret_cast<InitializeDebuggerForSocketpair>(sym.Value())(vm, false);
if (!ret) {
vm->GetJsDebuggerManager()->SetDebugMode(false);
return false;
}
return ret;
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
bool JSNApi::StopDebugger([[maybe_unused]] EcmaVM *vm)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
#if !defined(PANDA_TARGET_IOS)
LOG_ECMA(DEBUG) << "JSNApi::StopDebugger";
if (vm == nullptr) {
LOG_ECMA(ERROR) << "[StopDebugger] vm is nullptr";
return false;
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
const auto &handle = vm->GetJsDebuggerManager()->GetDebugLibraryHandle();
using StopDebug = void (*)(void *, bool);
auto sym = panda::os::library_loader::ResolveSymbol(handle, "StopDebug");
if (!sym) {
LOG_ECMA(WARN) << sym.Error().ToString();
return false;
}
reinterpret_cast<StopDebug>(sym.Value())(vm, false);
vm->GetJsDebuggerManager()->SetDebugMode(false);
uint32_t tid = vm->GetTid();
JsDebuggerManager::DeleteJsDebuggerManager(tid);
return true;
#else
if (vm == nullptr) {
LOG_ECMA(ERROR) << "[StopDebugger] vm is nullptr";
return false;
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
OHOS::ArkCompiler::Toolchain::StopDebug(vm);
vm->GetJsDebuggerManager()->SetDebugMode(false);
return true;
#endif
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
bool JSNApi::StopDebugger([[maybe_unused]] int tid)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
LOG_ECMA(DEBUG) << "JSNApi::StopDebugger, tid = " << tid;
JsDebuggerManager *jsDebuggerManager = JsDebuggerManager::GetJsDebuggerManager(tid);
if (jsDebuggerManager == nullptr) {
LOG_ECMA(ERROR) << "[StopDebugger] jsDebuggerManager is nullptr";
return false;
}
const auto &handle = jsDebuggerManager->GetDebugLibraryHandle();
using StopOldDebug = void (*)(int, const std::string &);
auto sym = panda::os::library_loader::ResolveSymbol(handle, "StopOldDebug");
if (!sym) {
LOG_ECMA(ERROR) << sym.Error().ToString();
return false;
}
reinterpret_cast<StopOldDebug>(sym.Value())(tid, "PandaDebugger");
return true;
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
bool JSNApi::IsMixedDebugEnabled([[maybe_unused]] const EcmaVM *vm)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
return vm->GetJsDebuggerManager()->IsMixedDebugEnabled();
#else
return false;
#endif
}
bool JSNApi::IsDebugModeEnabled([[maybe_unused]] const EcmaVM *vm)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
if (vm != nullptr && vm->GetJsDebuggerManager() != nullptr) {
return vm->GetJsDebuggerManager()->IsDebugMode();
}
return false;
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
return false;
#endif
}
void JSNApi::NotifyNativeCalling([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const void *nativeAddress)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
vm->GetJsDebuggerManager()->GetNotificationManager()->NativeCallingEvent(nativeAddress);
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
#endif
}
void JSNApi::NotifyNativeReturn([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] const void *nativeAddress)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
vm->GetJsDebuggerManager()->GetNotificationManager()->NativeReturnEvent(nativeAddress);
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
#endif
}
void JSNApi::NotifyLoadModule([[maybe_unused]] const EcmaVM *vm)
{
#if defined(ECMASCRIPT_SUPPORT_DEBUGGER)
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
vm->GetJsDebuggerManager()->ClearSingleStepper();
#else
LOG_ECMA(ERROR) << "Not support arkcompiler debugger";
#endif
}
void JSNApi::NotifyUIIdle(const EcmaVM *vm, [[maybe_unused]] int idleTime)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
vm->GetHeap()->GetIdleGCTrigger()->NotifyVsyncIdleStart();
}
bool JSNApi::NotifyLooperIdleStart(const EcmaVM *vm, int64_t timestamp, int idleTime)
{
if (vm->IsPostForked()) {
return vm->GetHeap()->GetIdleGCTrigger()->NotifyLooperIdleStart(timestamp, idleTime);
}
return false;
}
void JSNApi::NotifyLooperIdleEnd(const EcmaVM *vm, int64_t timestamp)
{
if (vm->IsPostForked()) {
vm->GetHeap()->GetIdleGCTrigger()->NotifyLooperIdleEnd(timestamp);
}
}
bool JSNApi::IsJSMainThreadOfEcmaVM(const EcmaVM *vm)
{
return vm->GetJSThread()->IsMainThreadFast();
}
void JSNApi::SetDeviceDisconnectCallback(EcmaVM *vm, DeviceDisconnectCallback cb)
{
vm->SetDeviceDisconnectCallback(cb);
}
bool JSNApi::KeyIsNumber(const char* utf8)
{
const char *ptr = utf8;
for (char c = *ptr; c; c = *++ptr) {
if (c >= '0' && c <= '9') {
continue;
} else {
return false;
}
}
return true;
}
bool JSNApi::IsSerializationTimeoutCheckEnabled(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
if (const_cast<EcmaVM *>(vm)->GetJSOptions().EnableSerializationTimeoutCheck()) {
return thread->IsMainThread();
}
auto jsDebuggerManager = vm->GetJsDebuggerManager();
if (jsDebuggerManager != nullptr) {
if (jsDebuggerManager->IsSerializationTimeoutCheckEnabled()) {
return thread->IsMainThread();
}
}
return false;
}
void JSNApi::GenerateTimeoutTraceIfNeeded(const EcmaVM *vm, std::chrono::system_clock::time_point &start,
std::chrono::system_clock::time_point &end, bool isSerialization)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
auto threshold = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::milliseconds(vm->GetJsDebuggerManager()->GetSerializationCheckThreshold())).count();
LOG_ECMA(DEBUG) << "JSNAPI::" << (isSerialization ? "SerializeValue" : "DeserializeValue") << " tid: "
<< thread->GetThreadId() << " threshold: " << threshold << " duration: " << duration;
if (duration >= threshold) {
std::stringstream tagMsg;
auto startTimeMS = std::chrono::time_point_cast<std::chrono::nanoseconds>(start);
tagMsg << (isSerialization ? "SerializationTimeout::tid=" : "DeserializationTimeout::tid=");
tagMsg << thread->GetThreadId();
tagMsg << (isSerialization ? ";task=serialization;startTime=" : ";task=deserialization;startTime=");
tagMsg << startTimeMS.time_since_epoch().count() << ";duration=" << duration;
ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, tagMsg.str().c_str(), "");
}
}
void JSNApi::LoadAotFile(EcmaVM *vm, const std::string &moduleName)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
std::string aotFileName = ecmascript::AOTFileManager::GetAOTFileFullPath(vm, moduleName);
if (aotFileName.empty()) {
LOG_ECMA(INFO) << "can not find aot file";
return;
}
if (isForked_) {
vm->DisablePGOProfilerWithAOTFile(aotFileName);
}
LOG_ECMA(INFO) << "start to load aot file: " << aotFileName;
vm->LoadAOTFiles(aotFileName);
}
bool JSNApi::ExecuteForAbsolutePath(const EcmaVM *vm, const std::string &fileName, const std::string &entry,
bool needUpdate, const ecmascript::ExecuteTypes &executeType)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
LOG_ECMA(DEBUG) << "start to execute absolute path ark file: " << fileName;
ecmascript::ThreadManagedScope scope(thread);
if (!ecmascript::JSPandaFileExecutor::ExecuteFromAbsolutePathAbcFile(
thread, fileName.c_str(), entry, needUpdate, executeType)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
LOG_ECMA(ERROR) << "Cannot execute absolute path ark file '" << fileName
<< "' with entry '" << entry << "'" << std::endl;
return false;
}
return true;
}
bool JSNApi::Execute(const EcmaVM *vm, const std::string &fileName, const std::string &entry,
bool needUpdate, const ecmascript::ExecuteTypes &executeType)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
LOG_ECMA(DEBUG) << "start to execute ark file: " << fileName;
ecmascript::ThreadManagedScope scope(thread);
if (!ecmascript::JSPandaFileExecutor::ExecuteFromAbcFile(
thread, fileName.c_str(), entry, needUpdate, executeType)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
LOG_ECMA(ERROR) << "Cannot execute ark file '" << fileName
<< "' with entry '" << entry << "'" << std::endl;
return false;
}
return true;
}
bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry,
const std::string &filename, bool needUpdate, [[maybe_unused]] void* fileMapper)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
LOG_ECMA(DEBUG) << "start to execute ark buffer: " << filename;
ecmascript::ThreadManagedScope scope(thread);
if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(thread, data, size, entry, filename.c_str(), needUpdate)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename
<< "' with entry '" << entry << "'" << std::endl;
return false;
}
return true;
}
int JSNApi::ExecuteWithSingletonPatternFlag(EcmaVM *vm, const std::string &bundleName,
const std::string &moduleName, const std::string &ohmurl, bool isSingletonPattern)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, ecmascript::JSPandaFileExecutor::ROUTE_INTERNAL_ERROR);
ecmascript::ThreadManagedScope scope(thread);
int result = ecmascript::JSPandaFileExecutor::ExecuteAbcFileWithSingletonPatternFlag(thread, bundleName.c_str(),
moduleName.c_str(), ohmurl.c_str(), isSingletonPattern);
if (!result) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
}
return result;
}
bool JSNApi::IsExecuteModuleInAbcFile(EcmaVM *vm, const std::string &bundleName,
const std::string &moduleName, const std::string &ohmurl)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope scope(thread);
bool result = ecmascript::JSPandaFileExecutor::IsExecuteModuleInAbcFile(thread, bundleName.c_str(),
moduleName.c_str(), ohmurl.c_str());
if (thread->HasPendingException()) {
thread->ClearException();
}
return result;
}
* srcFilename: data/storage/el1/bundle/modulename/ets/modules.abc
* ohmUrl : @normalized:N&moduleName&bundleName&entryPath&
*/
bool JSNApi::FindModuleInAbcFile(EcmaVM *vm, const std::string &srcFilename, const std::string &ohmUrl)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope scope(thread);
bool result = ecmascript::JSPandaFileExecutor::FindModuleInAbcFile(thread, srcFilename.c_str(), ohmUrl.c_str());
return result;
}
bool JSNApi::ExecuteModuleBuffer(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &filename,
bool needUpdate)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
LOG_ECMA(DEBUG) << "start to execute module buffer: " << filename;
ecmascript::ThreadManagedScope scope(thread);
if (!ecmascript::JSPandaFileExecutor::ExecuteModuleBuffer(thread, data, size, filename.c_str(), needUpdate)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
LOG_ECMA(ERROR) << "Cannot execute module buffer file '" << filename;
return false;
}
return true;
}
* srcFilename: data/storage/el1/bundle/modulename/ets/modules.abc
* ohmUrl : 1. @bundle:bundleName/moduleName@namespace/ets/pages/Index
* 2. @package:pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/xxx
* 3. @normalized:N&moduleName&bundleName&entryPath&version
* 4. @normalized:N&moduleName&bundleName&entryPath&
*/
bool JSNApi::ExecuteSecureWithOhmUrl(EcmaVM *vm, uint8_t *data, int32_t size, const std::string &srcFilename,
const std::string &ohmUrl)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
LOG_ECMA(INFO) << "start to execute ark buffer with secure memory use file: " << srcFilename <<
", entrypoint: " << ohmUrl;
ecmascript::ThreadManagedScope scope(thread);
ecmascript::CString filename = PathHelper::NormalizePath(srcFilename.c_str());
#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS)
if (!ModulePathHelper::ValidateAbcPath(filename, ecmascript::ValidateFilePath::ETS_MODULES)) {
LOG_FULL(FATAL) << "ExecuteSecureWithOhmUrl: Invalid input filePath: " << srcFilename <<
", input OhmUrl:" << ohmUrl;
}
#endif
ecmascript::CString entryPoint;
if (!ModulePathHelper::CheckAndGetRecordName(thread, ohmUrl.c_str(), entryPoint)) {
LOG_FULL(FATAL) << "ExecuteSecureWithOhmUrl: Invalid input OhmUrl: " << ohmUrl <<
", input filePath:" << filename;
}
if (!ecmascript::JSPandaFileExecutor::ExecuteSecureWithOhmUrl(thread, data, size, filename, entryPoint)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << srcFilename
<< "' with entry '" << ohmUrl << "'" << std::endl;
return false;
}
return true;
}
bool JSNApi::ExecuteSecure(EcmaVM *vm, uint8_t *data, int32_t size, const std::string &entry,
const std::string &filename, bool needUpdate, void *fileMapper)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
LOG_ECMA(INFO) << "start to execute ark buffer with secure memory: " << filename;
ecmascript::ThreadManagedScope scope(thread);
if (!ecmascript::JSPandaFileExecutor::ExecuteFromBufferSecure(
thread, data, size, entry, filename.c_str(), needUpdate, fileMapper)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
LOG_ECMA(ERROR) << "Cannot execute ark buffer file '" << filename
<< "' with entry '" << entry << "'" << std::endl;
return false;
}
return true;
}
bool JSNApi::ExecuteModuleBufferSecure(EcmaVM *vm, uint8_t* data, int32_t size, const std::string &filename,
bool needUpdate, void *fileMapper)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
LOG_ECMA(INFO) << "start to execute module buffer with secure memory: " << filename;
ecmascript::ThreadManagedScope scope(thread);
if (!ecmascript::JSPandaFileExecutor::ExecuteModuleBufferSecure(thread, data, size, filename.c_str(),
needUpdate, fileMapper)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
thread->HandleUncaughtException();
}
LOG_ECMA(ERROR) << "Cannot execute module buffer file '" << filename;
return false;
}
return true;
}
void JSNApi::PreFork(EcmaVM *vm)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
vm->PreFork();
}
void JSNApi::UpdateAOTCompileStatus(ecmascript::JSRuntimeOptions &jsOption, const RuntimeOption &option)
{
bool aotHasException = false;
for (const auto &value : option.GetAOTCompileStatusMap()) {
auto moduleCompileStatus = static_cast<RuntimeOption::AOTCompileStatus>(value.second);
if (moduleCompileStatus == RuntimeOption::AOTCompileStatus::COMPILE_FAILED ||
moduleCompileStatus == RuntimeOption::AOTCompileStatus::COMPILE_CRASH) {
aotHasException = true;
break;
}
}
jsOption.SetAOTHasException(aotHasException);
}
void JSNApi::PostFork(EcmaVM *vm, const RuntimeOption &option)
{
isForked_ = true;
JSRuntimeOptions &jsOption = vm->GetJSOptions();
jsOption.SetEnablePGOProfiler(option.GetEnableProfile());
jsOption.SetEnableJIT(option.GetEnableJIT());
jsOption.SetEnableDFXHiSysEvent(option.GetEnableDFXHiSysEvent());
jsOption.SetEnableBaselineJIT(option.GetEnableBaselineJIT());
jsOption.SetMaxAotMethodSize(JSRuntimeOptions::MAX_APP_COMPILE_METHOD_SIZE);
jsOption.SetArkTSMode(option.GetArkTSMode());
ecmascript::pgo::PGOProfilerManager::GetInstance()->SetBundleName(option.GetBundleName());
ecmascript::pgo::PGOProfilerManager::GetInstance()->SetMaxAotMethodSize(jsOption.GetMaxAotMethodSize());
JSRuntimeOptions runtimeOptions;
runtimeOptions.SetLogLevel(common::Log::LevelToString(common::Log::ConvertFromRuntime(option.GetLogLevel())));
common::Log::Initialize(runtimeOptions.GetLogOptions());
bool enableAOT = jsOption.GetEnableAOT() &&
!option.GetAnDir().empty() &&
EnableAotJitListHelper::GetInstance()->IsEnableAot(option.GetBundleName()) &&
!ecmascript::AotCrashInfo::IsAotEscaped();
if (enableAOT) {
ecmascript::AnFileDataManager::GetInstance()->SetDir(option.GetAnDir());
ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
}
UpdateAOTCompileStatus(jsOption, option);
LOG_ECMA(INFO) << "asmint: " << jsOption.GetEnableAsmInterpreter()
<< ", aot: " << enableAOT
<< ", jit: " << option.GetEnableJIT()
<< ", baseline jit: " << option.GetEnableBaselineJIT()
<< ", bundle name: " << option.GetBundleName()
<< ", arkTSMode: " << option.GetArkTSMode();
jsOption.SetEnableWarmStartupSmartGC(option.GetEnableWarmStartupSmartGC());
vm->PostFork(jsOption);
}
void JSNApi::UpdateArkTSMode(EcmaVM *vm, const std::string &arkTSMode)
{
JSRuntimeOptions &jsOption = vm->GetJSOptions();
jsOption.SetArkTSMode(arkTSMode);
}
void JSNApi::AddWorker(EcmaVM *hostVm, EcmaVM *workerVm)
{
if (hostVm != nullptr && workerVm != nullptr) {
hostVm->WorkersetInfo(workerVm);
workerVm->SetBundleName(hostVm->GetBundleName());
}
}
bool JSNApi::DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm)
{
if (hostVm != nullptr && workerVm != nullptr) {
return hostVm->DeleteWorker(workerVm);
}
return false;
}
Local<ObjectRef> JSNApi::GetUncaughtException(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToLocal<ObjectRef>(vm->GetEcmaUncaughtException());
}
Local<ObjectRef> JSNApi::GetAndClearUncaughtException(const EcmaVM *vm)
{
if (LIKELY(!HasPendingException(vm))) {
return Local<ObjectRef>();
}
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return JSNApiHelper::ToLocal<ObjectRef>(vm->GetAndClearEcmaUncaughtException());
}
bool JSNApi::HasPendingException(const EcmaVM *vm)
{
return vm->GetJSThread()->HasPendingException();
}
bool JSNApi::IsExecutingPendingJob(const EcmaVM *vm)
{
return EcmaVM::ConstCast(vm)->IsExecutingPendingJob();
}
bool JSNApi::HasPendingJob(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return EcmaVM::ConstCast(vm)->HasPendingJob();
}
void JSNApi::EnableUserUncaughtErrorHandler(EcmaVM *vm)
{
return vm->GetJSThread()->EnableUserUncaughtErrorHandler();
}
Local<ObjectRef> JSNApi::GetGlobalObject(const EcmaVM *vm)
{
auto thread = vm->GetJSThread();
ecmascript::ThreadManagedScope scope(thread);
JSHandle<GlobalEnv> globalEnv = vm->GetGlobalEnv();
JSHandle<JSTaggedValue> global(thread, globalEnv->GetGlobalObject());
return JSNApiHelper::ToLocal<ObjectRef>(global);
}
Local<ObjectRef> JSNApi::GetGlobalObject(const EcmaVM *vm, const Local<JSValueRef> &context)
{
JSThread* thread = vm->GetJSThread();
ecmascript::ThreadManagedScope scope(thread);
if (!context->IsJsGlobalEnv(vm)) {
LOG_ECMA(WARN) << "Attempted to call GetGlobalObject on a non-JsGlobalEnv object.";
return JSValueRef::Undefined(vm);
}
JSHandle<GlobalEnv> globalEnv = JSHandle<GlobalEnv>(JSNApiHelper::ToJSHandle(context));
JSHandle<JSTaggedValue> global(thread, globalEnv->GetGlobalObject());
return JSNApiHelper::ToLocal<ObjectRef>(global);
}
void JSNApi::ExecutePendingJob(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
EcmaVM::ConstCast(vm)->ExecutePromisePendingJob();
}
uintptr_t JSNApi::GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
{
if (localAddress == 0) {
return 0;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
return ecmascript::EcmaHandleScope::NewHandle(thread, value);
}
uintptr_t JSNApi::GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
{
if (localAddress == 0) {
return 0;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
JSTaggedType value = *(reinterpret_cast<JSTaggedType *>(localAddress));
return thread->NewGlobalHandle(value);
}
int JSNApi::GetStartRealTime(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
return vm->GetProcessStartRealtime();
}
void JSNApi::NotifyTaskBegin(const EcmaVM *vm)
{
const_cast<ecmascript::Heap *>(vm->GetHeap())->NotifyRecordMemorySize();
}
void JSNApi::NotifyTaskFinished(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
const_cast<ecmascript::Heap *>(vm->GetHeap())->CheckAndTriggerTaskFinishedGC();
}
bool JSNApi::IsMultiThreadCheckEnabled(const EcmaVM *vm)
{
return vm->GetThreadCheckStatus();
}
uint32_t JSNApi::GetCurrentThreadId()
{
return JSThread::GetCurrentThreadId();
}
void JSNApi::SetVMAPIVersion(EcmaVM *vm, const int32_t apiVersion)
{
vm->SetVMAPIVersion(static_cast<uint32_t>(apiVersion) % API_VERSION_MASK);
}
std::vector<ecmascript::HeapMemoryInfo> JSNApi::GetAllVMHeapMemoryInfo()
{
std::vector<ecmascript::HeapMemoryInfo> heapInfos;
auto runtime = ecmascript::Runtime::GetInstance();
ecmascript::SuspendAllScopeFromExternal suspendAllScope(nullptr);
runtime->GCIterateThreadList([&heapInfos](JSThread* thread) {
ecmascript::HeapMemoryInfo info;
info.threadId = thread->GetThreadId();
info.threadName = thread->GetThreadName();
info.heapType = "local";
info.heapObjectSize = 0;
auto threadVm = thread->GetEcmaVM();
ASSERT(threadVm != nullptr);
auto* heap = threadVm->GetHeap();
ASSERT(heap != nullptr);
size_t heapSize = heap->GetHeapObjectSize();
info.heapObjectSize = static_cast<uint32_t>(AlignUp(heapSize, 1_KB) / 1_KB);
heapInfos.push_back(info);
});
auto* sharedHeap = ecmascript::SharedHeap::GetInstance();
ecmascript::HeapMemoryInfo sharedInfo;
sharedInfo.threadId = 0;
sharedInfo.threadName = "[SharedHeap]";
sharedInfo.heapType = "shared";
size_t sharedSize = sharedHeap->GetHeapObjectSize();
sharedInfo.heapObjectSize = static_cast<uint32_t>(AlignUp(sharedSize, 1_KB) / 1_KB);
heapInfos.push_back(sharedInfo);
return heapInfos;
}
void JSNApi::UpdateStackInfo(EcmaVM *vm, void *currentStackInfo, uint32_t opKind)
{
vm->GetJSThread()->UpdateStackInfo(currentStackInfo, static_cast<ecmascript::JSThread::StackInfoOpKind>(opKind));
}
Local<JSValueRef> JSNApi::CreateContext(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
thread->SetMultiContextTriggered(true);
ObjectFactory *factory = vm->GetFactory();
JSHandle<GlobalEnv> globalEnv = factory->NewGlobalEnv();
auto notificationMgr = vm->GetJsDebuggerManager()->GetNotificationManager();
notificationMgr->SetDebuggerAccessorEvent(globalEnv);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(globalEnv));
}
Local<JSValueRef> JSNApi::GetCurrentContext(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<GlobalEnv> currentGlobalEnv = thread->GetGlobalEnv();
JSHandle<JSTaggedValue> envContext = JSHandle<JSTaggedValue>(currentGlobalEnv);
return JSNApiHelper::ToLocal<JSValueRef>(envContext);
}
int JSNApi::SwitchContext(const EcmaVM *vm, const Local<JSValueRef> &context)
{
if (context.IsEmpty()) {
return static_cast<int>(SwitchContextResult::EMPTY);
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, static_cast<int>(SwitchContextResult::FAILED));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSTaggedValue> contextValue = JSNApiHelper::ToJSHandle(context);
JSHandle<GlobalEnv> globalEnv = JSHandle<GlobalEnv>(contextValue);
thread->SetGlueGlobalEnv(globalEnv.GetTaggedValue());
return static_cast<int>(SwitchContextResult::SUCCESS);
}
uintptr_t JSNApi::SetWeak(const EcmaVM *vm, uintptr_t localAddress)
{
if (localAddress == 0) {
return 0;
}
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
CROSS_THREAD_CHECK(vm);
return thread->SetWeak(localAddress);
}
uintptr_t JSNApi::SetWeakCallback(const EcmaVM *vm, uintptr_t localAddress, void *ref,
WeakRefClearCallBack freeGlobalCallBack, WeakRefClearCallBack nativeFinalizeCallback)
{
if (localAddress == 0) {
return 0;
}
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
CROSS_THREAD_CHECK(vm);
return thread->SetWeak(localAddress, ref, freeGlobalCallBack, nativeFinalizeCallback);
}
uintptr_t JSNApi::ClearWeak(const EcmaVM *vm, uintptr_t localAddress)
{
if (localAddress == 0) {
return 0;
}
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
if (JSTaggedValue(reinterpret_cast<ecmascript::Node *>(localAddress)->GetObject())
.IsUndefined()) {
LOG_ECMA(ERROR) << "The object of weak reference has been recycled!";
return 0;
}
CROSS_THREAD_CHECK(vm);
return thread->ClearWeak(localAddress);
}
bool JSNApi::IsWeak(const EcmaVM *vm, uintptr_t localAddress)
{
if (localAddress == 0) {
return false;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
return thread->IsWeak(localAddress);
}
void JSNApi::DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr)
{
if (addr == 0 || !reinterpret_cast<ecmascript::Node *>(addr)->IsUsing()) {
return;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
thread->DisposeGlobalHandle(addr);
}
void *JSNApi::InterOpSerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer,
Local<JSValueRef> cloneList, bool defaultTransfer, bool defaultCloneShared)
{
if (!ecmascript::Runtime::GetInstance()->IsHybridVm()) {
return SerializeValue(vm, value, transfer, cloneList, defaultTransfer, defaultCloneShared);
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSTaggedValue> arkValue = JSNApiHelper::ToJSHandle(value);
JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer);
JSHandle<JSTaggedValue> arkCloneList = JSNApiHelper::ToJSHandle(cloneList);
bool serializationTimeoutCheckEnabled = IsSerializationTimeoutCheckEnabled(vm);
std::chrono::system_clock::time_point startTime;
std::chrono::system_clock::time_point endTime;
if (serializationTimeoutCheckEnabled) {
startTime = std::chrono::system_clock::now();
}
ecmascript::InterOpValueSerializer serializer(thread, defaultTransfer, defaultCloneShared);
std::unique_ptr<ecmascript::SerializeData> data;
if (serializer.WriteValue(thread, arkValue, arkTransfer, arkCloneList)) {
data = serializer.Release();
}
if (serializationTimeoutCheckEnabled) {
endTime = std::chrono::system_clock::now();
GenerateTimeoutTraceIfNeeded(vm, startTime, endTime, true);
}
if (data == nullptr) {
return nullptr;
} else {
return reinterpret_cast<void *>(data.release());
}
}
Local<JSValueRef> JSNApi::InterOpDeserializeValue(const EcmaVM *vm, void *recoder, void *hint)
{
if (!ecmascript::Runtime::GetInstance()->IsHybridVm()) {
return DeserializeValue(vm, recoder, hint);
}
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
EscapeLocalScope escapeScope(vm);
std::unique_ptr<ecmascript::SerializeData> data(reinterpret_cast<ecmascript::SerializeData *>(recoder));
ecmascript::InterOpValueDeserializer deserializer(thread, data.release(), hint);
bool serializationTimeoutCheckEnabled = IsSerializationTimeoutCheckEnabled(vm);
std::chrono::system_clock::time_point startTime;
std::chrono::system_clock::time_point endTime;
if (serializationTimeoutCheckEnabled) {
startTime = std::chrono::system_clock::now();
}
JSHandle<JSTaggedValue> result = deserializer.ReadValue();
if (serializationTimeoutCheckEnabled) {
endTime = std::chrono::system_clock::now();
GenerateTimeoutTraceIfNeeded(vm, startTime, endTime, false);
}
return escapeScope.Escape(JSNApiHelper::ToLocal<JSValueRef>(result));
}
void *JSNApi::SerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer,
Local<JSValueRef> cloneList, bool defaultTransfer,
bool defaultCloneShared, bool needSerializeStack)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSTaggedValue> arkValue = JSNApiHelper::ToJSHandle(value);
JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer);
JSHandle<JSTaggedValue> arkCloneList = JSNApiHelper::ToJSHandle(cloneList);
bool serializationTimeoutCheckEnabled = IsSerializationTimeoutCheckEnabled(vm);
std::chrono::system_clock::time_point startTime;
std::chrono::system_clock::time_point endTime;
if (serializationTimeoutCheckEnabled) {
startTime = std::chrono::system_clock::now();
}
ecmascript::ValueSerializer serializer(thread, defaultTransfer, defaultCloneShared, needSerializeStack);
std::unique_ptr<ecmascript::SerializeData> data;
if (serializer.WriteValue(thread, arkValue, arkTransfer, arkCloneList)) {
data = serializer.Release();
}
if (serializationTimeoutCheckEnabled) {
endTime = std::chrono::system_clock::now();
GenerateTimeoutTraceIfNeeded(vm, startTime, endTime, true);
}
if (data == nullptr) {
return nullptr;
} else {
return reinterpret_cast<void *>(data.release());
}
}
void *JSNApi::SerializeValueWithError(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer,
Local<JSValueRef> cloneList, std::string &error, bool defaultTransfer,
bool defaultCloneShared, bool needSerializeStack)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, nullptr);
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSTaggedValue> arkValue = JSNApiHelper::ToJSHandle(value);
JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer);
JSHandle<JSTaggedValue> arkCloneList = JSNApiHelper::ToJSHandle(cloneList);
bool serializationTimeoutCheckEnabled = IsSerializationTimeoutCheckEnabled(vm);
std::chrono::system_clock::time_point startTime;
std::chrono::system_clock::time_point endTime;
if (serializationTimeoutCheckEnabled) {
startTime = std::chrono::system_clock::now();
}
ecmascript::ValueSerializer serializer(thread, defaultTransfer, defaultCloneShared, needSerializeStack);
std::unique_ptr<ecmascript::SerializeData> data;
if (serializer.WriteValue(thread, arkValue, arkTransfer, arkCloneList)) {
data = serializer.Release();
}
if (serializationTimeoutCheckEnabled) {
endTime = std::chrono::system_clock::now();
GenerateTimeoutTraceIfNeeded(vm, startTime, endTime, true);
}
if (data == nullptr) {
error = serializer.Release()->GetErrorMessage();
return nullptr;
} else {
return reinterpret_cast<void *>(data.release());
}
}
void *JSNApi::SerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer,
Local<JSValueRef> cloneList, const SerializeOptions& options)
{
return SerializeValue(vm, value, transfer, cloneList,
options.defaultTransfer,
options.defaultCloneShared,
options.needSerializeStack);
}
void *JSNApi::SerializeValueWithError(const EcmaVM *vm, Local<JSValueRef> value, Local<JSValueRef> transfer,
Local<JSValueRef> cloneList, std::string &error,
const SerializeOptions& options)
{
return SerializeValueWithError(vm, value, transfer, cloneList, error,
options.defaultTransfer,
options.defaultCloneShared,
options.needSerializeStack);
}
Local<JSValueRef> JSNApi::DeserializeValue(const EcmaVM *vm, void *recoder, void *hint)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
EscapeLocalScope escapeScope(vm);
std::unique_ptr<ecmascript::SerializeData> data(reinterpret_cast<ecmascript::SerializeData *>(recoder));
ecmascript::BaseDeserializer deserializer(thread, data.release(), hint);
bool serializationTimeoutCheckEnabled = IsSerializationTimeoutCheckEnabled(vm);
std::chrono::system_clock::time_point startTime;
std::chrono::system_clock::time_point endTime;
if (serializationTimeoutCheckEnabled) {
startTime = std::chrono::system_clock::now();
}
JSHandle<JSTaggedValue> result = deserializer.ReadValue();
if (serializationTimeoutCheckEnabled) {
endTime = std::chrono::system_clock::now();
GenerateTimeoutTraceIfNeeded(vm, startTime, endTime, false);
}
return escapeScope.Escape(JSNApiHelper::ToLocal<JSValueRef>(result));
}
void JSNApi::DeleteSerializationData(void *data)
{
ecmascript::SerializeData *value = reinterpret_cast<ecmascript::SerializeData *>(data);
delete value;
value = nullptr;
}
void HostPromiseRejectionTracker(const EcmaVM *vm,
const JSHandle<JSPromise> promise,
const JSHandle<JSTaggedValue> reason,
const ecmascript::PromiseRejectionEvent operation,
void* data)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::PromiseRejectCallback promiseRejectCallback = vm->GetPromiseRejectCallback();
if (promiseRejectCallback != nullptr) {
Local<JSValueRef> promiseVal = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>::Cast(promise));
PromiseRejectInfo promiseRejectInfo(promiseVal, JSNApiHelper::ToLocal<JSValueRef>(reason),
static_cast<PromiseRejectInfo::PROMISE_REJECTION_EVENT>(operation), data);
promiseRejectCallback(reinterpret_cast<void*>(&promiseRejectInfo));
}
}
void JSNApi::SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data)
{
CROSS_THREAD_CHECK(vm);
vm->SetHostPromiseRejectionTracker(HostPromiseRejectionTracker);
vm->SetPromiseRejectCallback(reinterpret_cast<ecmascript::PromiseRejectCallback>(cb));
vm->SetPromiseRejectInfoData(data);
}
void JSNApi::SetTimerTaskCallback(EcmaVM *vm, TimerTaskCallback callback)
{
CROSS_THREAD_CHECK(vm);
vm->SetTimerTaskCallback(callback);
}
void JSNApi::SetCancelTimerCallback(EcmaVM *vm, CancelTimerCallback callback)
{
CROSS_THREAD_CHECK(vm);
vm->SetCancelTimerCallback(callback);
}
void JSNApi::NotifyEnvInitialized(EcmaVM *vm)
{
ecmascript::ModuleLogger::SetModuleLoggerTask(vm);
}
void JSNApi::SetReleaseSecureMemCallback(ReleaseSecureMemCallback releaseSecureMemFunc)
{
ecmascript::Runtime::GetInstance()->SetReleaseSecureMemCallback(releaseSecureMemFunc);
}
void JSNApi::PandaFileSerialize(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
if (const_cast<EcmaVM *>(vm)->GetJSOptions().DisableJSPandaFileAndModuleSnapshot()) {
return;
}
ecmascript::CString path(ecmascript::ohos::OhosConstants::PANDAFILE_AND_MODULE_SNAPSHOT_DIR);
ecmascript::ohos::JSPandaFileSnapshotInterfaces::Serialize(vm, path);
}
void JSNApi::ModuleSerialize(const EcmaVM *vm)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
JSRuntimeOptions &options = const_cast<EcmaVM *>(vm)->GetJSOptions();
if (options.DisableJSPandaFileAndModuleSnapshot()) {
return;
}
ecmascript::CString path(ecmascript::ohos::OhosConstants::PANDAFILE_AND_MODULE_SNAPSHOT_DIR);
ecmascript::ohos::ConstPoolSnapshotInterfaces::Serialize(vm, path);
if (options.DisableModuleSnapshot()) {
return;
}
ecmascript::ohos::ModuleSnapshotInterfaces::Serialize(vm, path);
}
void JSNApi::ModuleDeserialize(EcmaVM *vm, const uint32_t appVersion)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
if (vm->GetJSOptions().DisableJSPandaFileAndModuleSnapshot() || vm->GetJSOptions().DisableModuleSnapshot()) {
return;
}
vm->SetApplicationVersionCode(appVersion);
ecmascript::CString path(ecmascript::ohos::OhosConstants::PANDAFILE_AND_MODULE_SNAPSHOT_DIR);
ecmascript::ohos::ModuleSnapshotInterfaces::Deserialize(vm, path);
}
void JSNApi::SetHostResolveBufferTracker(EcmaVM *vm,
std::function<bool(std::string dirPath, uint8_t **buff, size_t *buffSize, std::string &errorMsg)> cb)
{
vm->SetResolveBufferCallback(cb);
}
void JSNApi::SetHostResolveBufferTrackerForHybridApp(EcmaVM *vm,
std::function<bool(std::string dirPath, uint8_t **buff, size_t *buffSize, std::string &errorMsg)> cb)
{
vm->SetResolveBufferCallbackForHybridApp(cb);
}
void JSNApi::SetSearchHapPathTracker(EcmaVM *vm,
std::function<bool(const std::string moduleName, std::string &hapPath)> cb)
{
vm->SetSearchHapPathCallBack(cb);
}
void JSNApi::SetMultiThreadCheck(bool multiThreadCheck)
{
EcmaVM::SetMultiThreadCheck(multiThreadCheck);
}
void JSNApi::SetErrorInfoEnhance(bool errorInfoEnhance)
{
EcmaVM::SetErrorInfoEnhance(errorInfoEnhance);
}
void JSNApi::SetIsMainProcess(bool isMainProcess)
{
ecmascript::Runtime::GetInstance()->SetIsMainProcess(isMainProcess);
}
void JSNApi::SetRequestAotCallback([[maybe_unused]] EcmaVM *vm, const std::function<int32_t
(const std::string &bundleName, const std::string &moduleName, int32_t triggerMode)> &cb)
{
ecmascript::pgo::PGOProfilerManager::GetInstance()->SetRequestAotCallback(cb);
}
void JSNApi::SetUnloadNativeModuleCallback(EcmaVM *vm, const std::function<bool(const std::string &moduleKey)> &cb)
{
vm->SetUnloadNativeModuleCallback(cb);
}
void JSNApi::SetNativePtrGetter(EcmaVM *vm, void* cb)
{
vm->SetNativePtrGetter(reinterpret_cast<ecmascript::NativePtrGetter>(cb));
}
void JSNApi::SetNativeReferenceDataGetter(EcmaVM *vm, void* cb)
{
vm->SetNativeReferenceDataGetter(reinterpret_cast<ecmascript::NativeReferenceDataCallbackGetter>(cb));
}
void JSNApi::SetHostEnqueueJob(const EcmaVM *vm, Local<JSValueRef> cb, QueueType queueType)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSFunction> fun = JSHandle<JSFunction>::Cast(JSNApiHelper::ToJSHandle(cb));
JSHandle<TaggedArray> array = vm->GetFactory()->EmptyArray();
JSHandle<MicroJobQueue> job = vm->GetMicroJobQueue();
MicroJobQueue::EnqueueJob(thread, job, queueType, fun, array);
}
bool JSNApi::ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope scope(thread);
if (!ecmascript::JSPandaFileExecutor::ExecuteFromBuffer(thread, data, size, ENTRY_POINTER, file.c_str(), false,
ecmascript::ExecuteTypes::NATIVE_MODULE)) {
if (thread->HasPendingException()) {
ecmascript::JsStackInfo::BuildCrashInfo(thread);
}
std::cerr << "Cannot execute panda file from memory" << std::endl;
return false;
}
return true;
}
JSNApi::PandaFileType JSNApi::GetFileType(const uint8_t *data, int32_t size)
{
panda_file::PandaFileType fileType = panda_file::GetFileType(data, size);
switch (fileType) {
case panda_file::PandaFileType::FILE_FORMAT_INVALID: {
return JSNApi::PandaFileType::FILE_FORMAT_INVALID;
}
case panda_file::PandaFileType::FILE_DYNAMIC: {
return JSNApi::PandaFileType::FILE_DYNAMIC;
}
case panda_file::PandaFileType::FILE_STATIC: {
return JSNApi::PandaFileType::FILE_STATIC;
}
default: {
UNREACHABLE();
}
}
}
Local<JSValueRef> JSNApi::NapiHasProperty(const EcmaVM *vm, uintptr_t nativeObj, uintptr_t key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> obj(nativeObj);
if (!(obj->IsECMAObject() || obj->IsCallable())) {
JSHandle<JSTaggedValue> holeHandle(thread, JSTaggedValue::Hole());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(holeHandle));
}
LOG_IF_SPECIAL(obj, ERROR);
JSMutableHandle<JSTaggedValue> keyValue(key);
JSTaggedValue res = ObjectFastOperator::TryFastHasProperty(thread, obj.GetTaggedValue(),
keyValue);
if (!res.IsHole()) {
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
auto ret = JSTaggedValue(JSTaggedValue::HasProperty(thread, obj, keyValue));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, ret)));
}
Local<JSValueRef> JSNApi::NapiHasOwnProperty(const EcmaVM *vm, uintptr_t nativeObj, uintptr_t key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> obj(nativeObj);
if (!(obj->IsECMAObject() || obj->IsCallable())) {
JSHandle<JSTaggedValue> holeHandle(thread, JSTaggedValue::Hole());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(holeHandle));
}
LOG_IF_SPECIAL(obj, ERROR);
JSMutableHandle<JSTaggedValue> keyValue(key);
JSTaggedValue res = ObjectFastOperator::TryFastHasProperty(thread, obj.GetTaggedValue(),
keyValue);
if (!res.IsHole()) {
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
auto ret = JSTaggedValue(JSTaggedValue::HasProperty(thread, obj, keyValue));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, ret)));
}
Local<JSValueRef> JSNApi::NapiGetProperty(const EcmaVM *vm, uintptr_t nativeObj, uintptr_t key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> obj(nativeObj);
if (!(obj->IsECMAObject() || obj->IsCallable())) {
JSHandle<JSTaggedValue> holeHandle(thread, JSTaggedValue::Hole());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(holeHandle));
}
LOG_IF_SPECIAL(obj, ERROR);
JSMutableHandle<JSTaggedValue> keyValue(key);
if (!obj->IsHeapObject()) {
OperationResult ret = JSTaggedValue::GetProperty(thread, obj, keyValue);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(ret.GetValue()));
}
JSTaggedValue res = ObjectFastOperator::TryFastGetPropertyByValue(thread, obj.GetTaggedValue(),
keyValue);
if (!res.IsHole()) {
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
JSTaggedValue ret = ObjectFastOperator::FastGetPropertyByValue(thread, obj.GetTaggedValue(),
keyValue.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, ret)));
}
Local<JSValueRef> JSNApi::NapiDeleteProperty(const EcmaVM *vm, uintptr_t nativeObj, uintptr_t key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> obj(nativeObj);
if (!(obj->IsECMAObject() || obj->IsCallable())) {
JSHandle<JSTaggedValue> holeHandle(thread, JSTaggedValue::Hole());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(holeHandle));
}
LOG_IF_SPECIAL(obj, ERROR);
JSMutableHandle<JSTaggedValue> keyValue(key);
if (keyValue->IsString() && !EcmaStringAccessor(keyValue.GetTaggedValue()).IsInternString()) {
[[maybe_unused]] ecmascript::EcmaHandleScope handleScope(thread);
auto string = thread->GetEcmaVM()->GetFactory()->InternString(keyValue);
EcmaStringAccessor(string).SetInternString();
keyValue.Update(JSTaggedValue(string));
}
auto ret = JSTaggedValue(JSTaggedValue::DeleteProperty(thread, obj, keyValue));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, ret)));
}
Local<JSValueRef> JSNApi::NapiGetNamedProperty(const EcmaVM *vm, uintptr_t nativeObj, const char* utf8Key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
EscapeLocalScope scope(vm);
JSHandle<JSTaggedValue> obj(nativeObj);
if (UNLIKELY(!(obj->IsECMAObject() || obj->IsCallable()))) {
JSHandle<JSTaggedValue> holeHandle(thread, JSTaggedValue::Hole());
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(holeHandle));
}
LOG_IF_SPECIAL(obj, ERROR);
ObjectFactory *factory = vm->GetFactory();
JSHandle<JSTaggedValue> keyValue(factory->NewFromUtf8(utf8Key));
JSTaggedValue res = ObjectFastOperator::TryGetPropertyByNameThroughCacheAtLocal(thread, obj.GetTaggedValue(),
keyValue.GetTaggedValue());
if (!res.IsHole()) {
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
if (!KeyIsNumber(utf8Key)) {
res = ObjectFastOperator::GetPropertyByName(thread, obj.GetTaggedValue(), keyValue.GetTaggedValue());
if (res.IsHole()) {
res = JSTaggedValue::GetProperty(thread, obj, keyValue).GetValue().GetTaggedValue();
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
res = ObjectFastOperator::FastGetPropertyByValue(thread, obj.GetTaggedValue(), keyValue.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
uintptr_t JSNApi::NapiCreateCallsiteInfo(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, 0);
ecmascript::ThreadManagedScope managedScope(thread);
[[maybe_unused]] LocalScope scope(vm);
JSHandle<ICInfo> array = vm->GetFactory()->NewICInfo(NapiICInfo::LENGTH);
return thread->NewGlobalHandle(array.GetTaggedValue().GetRawData());
}
void JSNApi::NapiDeleteCallsiteInfo(const EcmaVM *vm, uintptr_t info)
{
if (info == 0) {
return;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
thread->DisposeGlobalHandle(info);
}
Local<JSValueRef> JSNApi::NapiGetPropertyWithCallsiteInfo(const EcmaVM *vm, uintptr_t nativeObj, uintptr_t key,
uintptr_t info, bool* hit)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
if (hit != nullptr) {
*hit = false;
}
JSHandle<JSTaggedValue> obj(nativeObj);
if (UNLIKELY(!(obj->IsECMAObject() || obj->IsCallable()))) {
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Hole()));
}
JSHandle<NapiICInfo> icInfo = NapiICInfo::SafeCast(JSHandle<JSTaggedValue>(info));
if (UNLIKELY(icInfo.IsEmpty() || !icInfo->CanLoadIC(thread))) {
return NapiGetProperty(vm, nativeObj, key);
}
JSMutableHandle<JSTaggedValue> keyHandle(key);
JSTaggedValue fastRes = NapiICInfo::TryLoadKeyIC(thread, icInfo, obj.GetTaggedValue(), keyHandle.GetTaggedValue());
if (LIKELY(!fastRes.IsHole())) {
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
if (hit != nullptr) {
*hit = true;
}
ASSERT(vm->GetHandleScopeStorageNext() != nullptr);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, fastRes));
}
{
EscapeLocalScope scope(vm);
JSTaggedValue res = NapiICInfo::TryLoadICOrMiss(thread, icInfo, obj, keyHandle, hit);
if (LIKELY(!res.IsHole())) {
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, res)));
}
}
LOG_ECMA(DEBUG) << "NapiGetPropertyWithCallsiteInfo: IC doesn't work, go slow path";
return NapiGetProperty(vm, nativeObj, key);
}
bool JSNApi::NapiSetPropertyWithCallsiteInfo(const EcmaVM *vm, uintptr_t nativeObj, uintptr_t key, uintptr_t value,
uintptr_t info, bool* hit)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope managedScope(thread);
LocalScope scope(vm);
if (hit != nullptr) {
*hit = false;
}
JSHandle<JSTaggedValue> obj(nativeObj);
JSMutableHandle<JSTaggedValue> keyHandle(key);
JSHandle<JSTaggedValue> valueHandle(value);
JSHandle<NapiICInfo> icInfo = NapiICInfo::SafeCast(JSHandle<JSTaggedValue>(info));
if (UNLIKELY(icInfo.IsEmpty() || !icInfo->CanStoreIC(thread))) {
bool setSucceeded = JSNApiHelper::ToLocal<ObjectRef>(obj)->Set(vm,
JSNApiHelper::ToLocal<JSValueRef>(keyHandle),
JSNApiHelper::ToLocal<JSValueRef>(valueHandle));
RETURN_VALUE_IF_ABRUPT(thread, false);
return setSucceeded;
}
JSTaggedValue res = NapiICInfo::TryStoreICOrMiss(thread, icInfo, obj, keyHandle, valueHandle, hit);
if (LIKELY(!res.IsHole())) {
RETURN_VALUE_IF_ABRUPT(thread, false);
return !res.IsException();
}
LOG_ECMA(DEBUG) << "NapiSetPropertyWithCallsiteInfo: IC doesn't work, go slow path";
bool setSucceeded = JSNApiHelper::ToLocal<ObjectRef>(obj)->Set(vm,
JSNApiHelper::ToLocal<JSValueRef>(keyHandle),
JSNApiHelper::ToLocal<JSValueRef>(valueHandle));
RETURN_VALUE_IF_ABRUPT(thread, false);
return setSucceeded;
}
Local<JSValueRef> JSNApi::CreateLocal(const EcmaVM *vm, panda::JSValueRef src)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> handle(thread, JSNApiHelper::ToJSTaggedValue(&src));
return JSNApiHelper::ToLocal<JSValueRef>(handle);
}
Local<ObjectRef> JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, const std::string &key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
ecmascript::CString entry = file.c_str();
ecmascript::CString name = vm->GetAssetPath();
if (!vm->IsBundlePack()) {
ModulePathHelper::ParseAbcPathAndOhmUrl(vm, entry, name, entry);
std::shared_ptr<JSPandaFile> jsPandaFile =
JSPandaFileManager::GetInstance()->LoadJSPandaFile(
thread, name, entry.c_str(), false, ecmascript::ExecuteTypes::STATIC);
if (jsPandaFile == nullptr) {
JSHandle<JSTaggedValue> exportObj(thread, JSTaggedValue::Null());
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
if (!jsPandaFile->IsRecordWithBundleName()) {
PathHelper::AdaptOldIsaRecord(entry);
}
}
ecmascript::ModuleManager *moduleManager = thread->GetModuleManager();
JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->GetImportedModule(entry);
if (ecmaModule->GetIsNewBcVersion()) {
int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key.c_str());
JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
JSHandle<JSTaggedValue> exportObj(thread, result);
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
ObjectFactory *factory = vm->GetFactory();
JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
JSHandle<JSTaggedValue> exportObj(thread, result);
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
Local<ObjectRef> JSNApi::GetExportObjectFromBuffer(EcmaVM *vm, const std::string &file,
const std::string &key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
ecmascript::ModuleManager *moduleManager = thread->GetModuleManager();
JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->GetImportedModule(file.c_str());
if (ecmaModule->GetIsNewBcVersion()) {
int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key.c_str());
JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
JSHandle<JSTaggedValue> exportObj(thread, result);
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
ObjectFactory *factory = vm->GetFactory();
JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
JSHandle<JSTaggedValue> exportObj(thread, result);
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
Local<ObjectRef> JSNApi::GetExportObjectFromOhmUrl(EcmaVM *vm, const std::string &ohmUrl, const std::string &key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
ecmascript::CString recordName;
if (!ModulePathHelper::CheckAndGetRecordName(thread, ohmUrl.c_str(), recordName)) {
LOG_FULL(FATAL) << "ExecuteSecureWithOhmUrl: Invalid input OhmUrl: " << ohmUrl;
return JSValueRef::Undefined(vm);
}
ecmascript::ModuleManager *moduleManager = thread->GetModuleManager();
JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->GetImportedModule(recordName.c_str());
int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key.c_str());
JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
JSHandle<JSTaggedValue> exportObj(thread, result);
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
Local<ObjectRef> JSNApi::ExecuteNativeModule(EcmaVM *vm, const std::string &key)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ModuleManager *moduleManager = thread->GetModuleManager();
JSHandle<JSTaggedValue> exportObj = moduleManager->LoadNativeModule(thread, key.c_str());
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
Local<ObjectRef> JSNApi::GetModuleNameSpaceFromFile(EcmaVM *vm, const std::string &file)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
std::pair<std::string, std::string> moduleInfo = vm->GetCurrentModuleInfo(false);
if (thread->HasPendingException()) {
thread->HandleUncaughtException();
return JSValueRef::Undefined(vm);
}
ecmascript::CString moduleName = moduleInfo.first.c_str();
ecmascript::CString abcPath = moduleInfo.second.c_str();
JSHandle<JSTaggedValue> moduleNamespace =
ecmascript::NapiModuleLoader::LoadModuleNameSpace(vm, file.c_str(), moduleName, abcPath);
return JSNApiHelper::ToLocal<ObjectRef>(moduleNamespace);
}
template<ForHybridApp isHybrid>
Local<ObjectRef> JSNApi::GetModuleNameSpaceWithModuleInfo(EcmaVM *vm, const std::string &file,
const std::string &module_path)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ecmascript::CString requestPath = file.c_str();
ecmascript::CString modulePath = module_path.c_str();
JSHandle<JSTaggedValue> nameSp =
ecmascript::NapiModuleLoader::LoadModuleNameSpace<isHybrid>(vm, requestPath, modulePath);
return JSNApiHelper::ToLocal<ObjectRef>(nameSp);
}
template Local<ObjectRef> JSNApi::GetModuleNameSpaceWithModuleInfo<ForHybridApp::Normal>(EcmaVM *vm,
const std::string &file, const std::string &module_path);
template Local<ObjectRef> JSNApi::GetModuleNameSpaceWithModuleInfo<ForHybridApp::Hybrid>(EcmaVM *vm,
const std::string &file, const std::string &module_path);
Local<ObjectRef> JSNApi::GetModuleNameSpaceWithModuleInfoForNormalApp(EcmaVM *vm, const std::string &file,
const std::string &module_path)
{
return JSNApi::GetModuleNameSpaceWithModuleInfo<ForHybridApp::Normal>(vm, file, module_path);
}
Local<ObjectRef> JSNApi::GetModuleNameSpaceWithModuleInfoForHybridApp(EcmaVM *vm, const std::string &file,
const std::string &module_path)
{
if (module_path.empty()) {
return JSValueRef::Undefined(vm);
}
return JSNApi::GetModuleNameSpaceWithModuleInfo<ForHybridApp::Hybrid>(vm, file, module_path);
}
bool JSNApi::IsCrossBundleHsp(const EcmaVM *vm, const std::string &ohmurl)
{
return ModulePathHelper::IsCrossBundleHsp(vm, ohmurl.c_str());
}
Local<ObjectRef> JSNApi::GetModuleNameSpaceWithOhmurlForHybridApp(EcmaVM *vm, const std::string &ohmurl,
const std::string &fileName)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSTaggedValue> result =
ecmascript::NapiModuleLoader::LoadModuleNameSpaceWithOhmurl<ForHybridApp::Hybrid>(thread, ohmurl.c_str(),
fileName.c_str());
return JSNApiHelper::ToLocal<ObjectRef>(result);
}
uintptr_t JSNApi::GetSendableGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress)
{
if (localAddress == 0) {
return 0;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSTaggedValue> handle = JSHandle<JSTaggedValue>(localAddress);
if (!handle->IsSendable()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot create a sendable reference with a non-sendable variable.", 0);
}
return ecmascript::Runtime::GetInstance()->NewSendableGlobalHandle(handle.GetTaggedType());
}
void JSNApi::DisposeSendableGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr)
{
if (addr == 0) {
return;
}
CROSS_THREAD_CHECK(vm);
ecmascript::ThreadManagedScope scope(thread);
if (!reinterpret_cast<ecmascript::Node *>(addr)->IsUsing()) {
return;
}
ecmascript::Runtime::GetInstance()->DisposeSendableGlobalHandle(addr);
}
Local<PromiseRef> PromiseRef::Catch(const EcmaVM *vm, Local<FunctionRef> handler)
{
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(promise, ERROR);
JSHandle<JSTaggedValue> catchKey(thread, constants->GetPromiseCatchString());
JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(handler);
JSHandle<JSTaggedValue> undefined = constants->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 1);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(reject.GetTaggedValue().GetRawData());
#endif
info->SetCallArg(reject.GetTaggedValue());
JSTaggedValue result = JSFunction::Invoke(info, catchKey);
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
}
Local<PromiseRef> PromiseRef::Finally(const EcmaVM *vm, Local<FunctionRef> handler)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(promise, ERROR);
JSHandle<JSTaggedValue> finallyKey = constants->GetHandledPromiseFinallyString();
JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler);
JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(resolver.GetTaggedValue().GetRawData());
thread->CheckJSTaggedType(undefined.GetTaggedValue().GetRawData());
#endif
info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue());
JSTaggedValue result = JSFunction::Invoke(info, finallyKey);
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
}
Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> handler)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(promise, ERROR);
JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(handler);
JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(resolver.GetTaggedValue().GetRawData());
thread->CheckJSTaggedType(undefined.GetTaggedValue().GetRawData());
#endif
info->SetCallArg(resolver.GetTaggedValue(), undefined.GetTaggedValue());
JSTaggedValue result = JSFunction::Invoke(info, thenKey);
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
}
Local<PromiseRef> PromiseRef::Then(const EcmaVM *vm, Local<FunctionRef> onFulfilled, Local<FunctionRef> onRejected)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
const GlobalEnvConstants *constants = thread->GlobalConstants();
JSHandle<JSTaggedValue> promise = JSNApiHelper::ToJSHandle(this);
LOG_IF_SPECIAL(promise, ERROR);
JSHandle<JSTaggedValue> thenKey(thread, constants->GetPromiseThenString());
JSHandle<JSTaggedValue> resolver = JSNApiHelper::ToJSHandle(onFulfilled);
JSHandle<JSTaggedValue> reject = JSNApiHelper::ToJSHandle(onRejected);
JSHandle<JSTaggedValue> undefined(constants->GetHandledUndefined());
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, promise, undefined, 2);
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
#if ECMASCRIPT_ENABLE_STUB_ARGV_CHECK
thread->CheckJSTaggedType(resolver.GetTaggedValue().GetRawData());
thread->CheckJSTaggedType(reject.GetTaggedValue().GetRawData());
#endif
info->SetCallArg(resolver.GetTaggedValue(), reject.GetTaggedValue());
JSTaggedValue result = JSFunction::Invoke(info, thenKey);
#if ECMASCRIPT_ENABLE_STUB_RESULT_CHECK
thread->CheckJSTaggedType(result.GetRawData());
#endif
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
return JSNApiHelper::ToLocal<PromiseRef>(JSHandle<JSTaggedValue>(thread, result));
}
Local<JSValueRef> PromiseRef::GetPromiseState(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSPromise> promise(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(promise, ERROR);
ecmascript::PromiseState state = promise->GetPromiseState();
std::string promiseStateStr;
switch (state) {
case ecmascript::PromiseState::PENDING:
promiseStateStr = "Pending";
break;
case ecmascript::PromiseState::FULFILLED:
promiseStateStr = "Fulfilled";
break;
case ecmascript::PromiseState::REJECTED:
promiseStateStr = "Rejected";
break;
}
ObjectFactory *factory = vm->GetFactory();
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(factory->NewFromStdString(promiseStateStr)));
}
Local<JSValueRef> PromiseRef::GetPromiseResult(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSPromise> promise(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(promise, ERROR);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, promise->GetPromiseResult(thread)));
}
Local<JSValueRef> ProxyRef::GetHandler(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this));
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, jsProxy->GetHandler(thread)));
}
Local<JSValueRef> ProxyRef::GetTarget(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(thread);
JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this));
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, jsProxy->GetTarget(thread)));
}
bool ProxyRef::IsRevoked()
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
JSHandle<JSProxy> jsProxy(JSNApiHelper::ToJSHandle(this));
return jsProxy->GetIsRevoked();
}
int32_t SetRef::GetSize(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
return set->GetSize(thread);
}
int32_t SetRef::GetTotalElements(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
return static_cast<int>(set->GetSize(thread)) +
LinkedHashSet::Cast(set->GetLinkedSet(thread).GetTaggedObject())->NumberOfDeletedElements();
}
Local<JSValueRef> SetRef::GetValue(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(set, FATAL);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, set->GetValue(thread, entry)));
}
Local<SetRef> SetRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
JSHandle<JSSet> set =
JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
set->SetLinkedSet(thread, hashSet);
JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(set);
return JSNApiHelper::ToLocal<SetRef>(setTag);
}
void SetRef::Add(const EcmaVM *vm, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSSet> set(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(set, ERROR);
JSSet::Add(thread, set, JSNApiHelper::ToJSHandle(value));
}
int32_t WeakMapRef::GetSize(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
return weakMap->GetSize(thread);
}
int32_t WeakMapRef::GetTotalElements(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
return weakMap->GetSize(thread) +
WeakLinkedHashMap::Cast(weakMap->GetWeakLinkedMap(thread).GetTaggedObject())->NumberOfDeletedElements();
}
Local<JSValueRef> WeakMapRef::GetKey(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(weakMap, FATAL);
JSTaggedValue key = weakMap->GetKey(thread, entry);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, key.GetWeakRawValue()));
}
Local<JSValueRef> WeakMapRef::GetValue(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(weakMap, FATAL);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, weakMap->GetValue(thread, entry)));
}
Local<WeakMapRef> WeakMapRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor = env->GetBuiltinsWeakMapFunction();
JSHandle<JSWeakMap> weakMap =
JSHandle<JSWeakMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
JSHandle<WeakLinkedHashMap> hashMap = WeakLinkedHashMap::Create(thread);
weakMap->SetWeakLinkedMap(thread, hashMap);
JSHandle<JSTaggedValue> weakMapTag = JSHandle<JSTaggedValue>::Cast(weakMap);
return JSNApiHelper::ToLocal<WeakMapRef>(weakMapTag);
}
void WeakMapRef::Set(const EcmaVM *vm, const Local<JSValueRef> &key, const Local<JSValueRef> &value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(weakMap, FATAL);
JSWeakMap::Set(thread, weakMap, JSNApiHelper::ToJSHandle(key), JSNApiHelper::ToJSHandle(value));
}
bool WeakMapRef::Has(const EcmaVM *vm, Local<JSValueRef> key)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, false);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakMap> weakMap(JSNApiHelper::ToJSHandle(this));
return weakMap->Has(thread, JSNApiHelper::ToJSTaggedValue(*key));
}
int32_t WeakSetRef::GetSize(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
return weakSet->GetSize(thread);
}
int32_t WeakSetRef::GetTotalElements(const EcmaVM *vm)
{
DCHECK_SPECIAL_VALUE_WITH_RETURN(this, 0);
JSThread *thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
return weakSet->GetSize(thread) +
LinkedHashSet::Cast(weakSet->GetLinkedSet(thread).GetTaggedObject())->NumberOfDeletedElements();
}
Local<JSValueRef> WeakSetRef::GetValue(const EcmaVM *vm, int entry)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(weakSet, FATAL);
JSTaggedValue value = weakSet->GetValue(thread, entry);
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, value.GetWeakRawValue()));
}
Local<WeakSetRef> WeakSetRef::New(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> constructor = env->GetBuiltinsWeakSetFunction();
JSHandle<JSWeakSet> weakSet =
JSHandle<JSWeakSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
JSHandle<LinkedHashSet> hashWeakSet = LinkedHashSet::Create(thread);
weakSet->SetLinkedSet(thread, hashWeakSet);
JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(weakSet);
return JSNApiHelper::ToLocal<WeakSetRef>(setTag);
}
void WeakSetRef::Add(const EcmaVM *vm, Local<JSValueRef> value)
{
CROSS_THREAD_AND_EXCEPTION_CHECK(vm);
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<JSWeakSet> weakSet(JSNApiHelper::ToJSHandle(this));
LOG_IF_SPECIAL(weakSet, ERROR);
JSWeakSet::Add(thread, weakSet, JSNApiHelper::ToJSHandle(value));
}
TryCatch::~TryCatch() {}
bool TryCatch::HasCaught() const
{
return ecmaVm_->GetJSThread()->HasPendingException();
}
void TryCatch::Rethrow()
{
rethrow_ = true;
}
Local<ObjectRef> TryCatch::GetAndClearException()
{
ecmascript::ThreadManagedScope managedScope(ecmaVm_->GetJSThread());
ecmaVm_->GetJSThread()->SetExtraErrorMessage(JSTaggedValue::Hole());
return JSNApiHelper::ToLocal<ObjectRef>(ecmaVm_->GetAndClearEcmaUncaughtException());
}
Local<ObjectRef> TryCatch::GetException()
{
ecmascript::ThreadManagedScope managedScope(ecmaVm_->GetJSThread());
return JSNApiHelper::ToLocal<ObjectRef>(ecmaVm_->GetEcmaUncaughtException());
}
void TryCatch::ClearException()
{
ecmaVm_->GetJSThread()->ClearExceptionAndExtraErrorMessage();
}
void* TryCatch::GetEnv()
{
return ecmaVm_->GetJSThread()->GetEnv();
}
bool ExternalStringCache::RegisterStringCacheTable(const EcmaVM *vm, uint32_t size)
{
auto instance = ecmascript::Runtime::GetInstance();
ASSERT(instance != nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return instance->CreateStringCacheTable(size);
}
bool ExternalStringCache::SetCachedString(const EcmaVM *vm, const char *name, uint32_t propertyIndex)
{
auto instance = ecmascript::Runtime::GetInstance();
ASSERT(instance != nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
[[maybe_unused]] LocalScope scope(vm);
ObjectFactory *factory = vm->GetFactory();
JSHandle<EcmaString> str = factory->NewFromUtf8(name);
return instance->SetCachedString(str, propertyIndex);
}
Local<StringRef> ExternalStringCache::GetCachedString(const EcmaVM *vm, uint32_t propertyIndex)
{
auto instance = ecmascript::Runtime::GetInstance();
ASSERT(instance != nullptr);
auto thread = vm->GetJSThread();
ecmascript::ThreadManagedScope managedScope(thread);
JSHandle<EcmaString> str = instance->GetCachedString(thread, propertyIndex);
return JSNApiHelper::ToLocal<StringRef>(JSHandle<JSTaggedValue>(str));
}
bool ExternalStringCache::HasCachedString([[maybe_unused]] const EcmaVM *vm, uint32_t propertyIndex)
{
auto instance = ecmascript::Runtime::GetInstance();
ASSERT(instance != nullptr);
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
return instance->HasCachedString(propertyIndex);
}
}