mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
Fix napi_define_sendable_class
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9AUU2?from=project-issue Signed-off-by: liu-zelin <liuzelin8@huawei.com> Change-Id: Id3bdb9f5dd975dc0243f8a12f82c94f86043fe46
This commit is contained in:
parent
becdd90295
commit
89c0b1061f
1
BUILD.gn
1
BUILD.gn
@ -745,6 +745,7 @@ ecma_source = [
|
||||
"ecmascript/js_iterator.cpp",
|
||||
"ecmascript/js_map.cpp",
|
||||
"ecmascript/js_map_iterator.cpp",
|
||||
"ecmascript/jsnapi_sendable.cpp",
|
||||
"ecmascript/method.cpp",
|
||||
"ecmascript/js_object.cpp",
|
||||
"ecmascript/js_primitive_ref.cpp",
|
||||
|
@ -491,6 +491,22 @@ void EcmaVM::ProcessNativeDelete(const WeakRootVisitor &visitor)
|
||||
}
|
||||
}
|
||||
|
||||
void EcmaVM::ProcessSharedNativeDelete(const WeakRootVisitor &visitor)
|
||||
{
|
||||
auto sharedIter = sharedNativePointerList_.begin();
|
||||
while (sharedIter != sharedNativePointerList_.end()) {
|
||||
JSNativePointer *object = *sharedIter;
|
||||
auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
|
||||
if (fwd == nullptr) {
|
||||
sharedNativePointerCallbacks_.emplace_back(
|
||||
std::make_pair(object->GetDeleter(), std::make_pair(object->GetExternalPointer(), object->GetData())));
|
||||
sharedIter = sharedNativePointerList_.erase(sharedIter);
|
||||
} else {
|
||||
++sharedIter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EcmaVM::ProcessReferences(const WeakRootVisitor &visitor)
|
||||
{
|
||||
if (thread_->GetCurrentEcmaContext()->GetRegExpParserCache() != nullptr) {
|
||||
@ -549,6 +565,12 @@ void EcmaVM::PushToNativePointerList(JSNativePointer *pointer, Concurrent isConc
|
||||
}
|
||||
}
|
||||
|
||||
void EcmaVM::PushToSharedNativePointerList(JSNativePointer *pointer)
|
||||
{
|
||||
ASSERT(JSTaggedValue(pointer).IsInSharedHeap());
|
||||
sharedNativePointerList_.emplace_back(pointer);
|
||||
}
|
||||
|
||||
void EcmaVM::RemoveFromNativePointerList(JSNativePointer *pointer)
|
||||
{
|
||||
auto iter = std::find(nativePointerList_.begin(), nativePointerList_.end(), pointer);
|
||||
|
@ -246,6 +246,9 @@ public:
|
||||
void ProcessNativeDelete(const WeakRootVisitor &visitor);
|
||||
void ProcessReferences(const WeakRootVisitor &visitor);
|
||||
|
||||
void PushToSharedNativePointerList(JSNativePointer *pointer);
|
||||
void ProcessSharedNativeDelete(const WeakRootVisitor &visitor);
|
||||
|
||||
SnapshotEnv *GetSnapshotEnv() const
|
||||
{
|
||||
return snapshotEnv_;
|
||||
@ -335,7 +338,7 @@ public:
|
||||
{
|
||||
return resolveBufferCallback_;
|
||||
}
|
||||
|
||||
|
||||
void SetSearchHapPathCallBack(SearchHapPathCallBack cb)
|
||||
{
|
||||
SearchHapPathCallBack_ = cb;
|
||||
@ -623,6 +626,11 @@ public:
|
||||
}
|
||||
|
||||
static void InitializeIcuData(const JSRuntimeOptions &options);
|
||||
|
||||
std::vector<std::pair<DeleteEntryPoint, std::pair<void *, void *>>> &GetSharedNativePointerCallbacks()
|
||||
{
|
||||
return sharedNativePointerCallbacks_;
|
||||
}
|
||||
protected:
|
||||
|
||||
void PrintJSErrorInfo(const JSHandle<JSTaggedValue> &exceptionInfo) const;
|
||||
@ -653,6 +661,8 @@ private:
|
||||
CList<JSNativePointer *> nativePointerList_;
|
||||
CList<JSNativePointer *> concurrentNativePointerList_;
|
||||
std::vector<std::pair<DeleteEntryPoint, std::pair<void *, void *>>> nativePointerCallbacks_ {};
|
||||
CList<JSNativePointer *> sharedNativePointerList_;
|
||||
std::vector<std::pair<DeleteEntryPoint, std::pair<void *, void *>>> sharedNativePointerCallbacks_ {};
|
||||
// VM execution states.
|
||||
JSThread *thread_ {nullptr};
|
||||
|
||||
|
@ -1326,4 +1326,97 @@ PropertyLookupResult JSHClass::LookupPropertyInBuiltinHClass(const JSThread *thr
|
||||
result.SetIsFound(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> JSHClass::CreateSHClass(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
bool isFunction)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
|
||||
uint32_t length = descs.size();
|
||||
uint32_t maxInline = isFunction ? JSSharedFunction::MAX_INLINE : JSSharedObject::MAX_INLINE;
|
||||
|
||||
JSHandle<JSHClass> hclass =
|
||||
isFunction ? factory->NewSEcmaHClass(JSSharedFunction::SIZE, JSType::JS_SHARED_FUNCTION, length)
|
||||
: factory->NewSEcmaHClass(JSSharedObject::SIZE, JSType::JS_SHARED_OBJECT, length);
|
||||
if (LIKELY(length <= maxInline)) {
|
||||
auto layout = CreateSInlinedLayout(thread, descs);
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(length);
|
||||
} else {
|
||||
auto layout = CreateSDictLayout(thread, descs);
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(0);
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
}
|
||||
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> JSHClass::CreateSConstructorHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs)
|
||||
{
|
||||
auto hclass = CreateSHClass(thread, descs, true);
|
||||
hclass->SetClassConstructor(true);
|
||||
hclass->SetConstructor(true);
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> JSHClass::CreateSPrototypeHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs)
|
||||
{
|
||||
auto hclass = CreateSHClass(thread, descs);
|
||||
hclass->SetClassPrototype(true);
|
||||
hclass->SetIsPrototype(true);
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<LayoutInfo> JSHClass::CreateSInlinedLayout(JSThread *thread, const std::vector<PropertyDescriptor> &descs)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
|
||||
auto length = descs.size();
|
||||
auto layout = factory->CreateSLayoutInfo(length);
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
key.Update(descs[i].GetKey());
|
||||
PropertyAttributes attr =
|
||||
PropertyAttributes::Default(descs[i].IsWritable(), descs[i].IsEnumerable(), descs[i].IsConfigurable());
|
||||
if (UNLIKELY(descs[i].GetValue()->IsAccessor())) {
|
||||
attr.SetIsAccessor(true);
|
||||
}
|
||||
attr.SetIsInlinedProps(true);
|
||||
attr.SetRepresentation(Representation::TAGGED);
|
||||
attr.SetSharedFieldType(descs[i].GetSharedFieldType());
|
||||
attr.SetOffset(i);
|
||||
layout->AddKey(thread, i, key.GetTaggedValue(), attr);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
JSHandle<NameDictionary> JSHClass::CreateSDictLayout(JSThread *thread, const std::vector<PropertyDescriptor> &descs)
|
||||
{
|
||||
auto length = descs.size();
|
||||
JSMutableHandle<NameDictionary> dict(
|
||||
thread, NameDictionary::CreateInSharedHeap(thread, NameDictionary::ComputeHashTableSize(length)));
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
|
||||
auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
|
||||
JSHandle<JSTaggedValue> value = globalConst->GetHandledUndefined();
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
key.Update(descs[i].GetKey());
|
||||
PropertyAttributes attr =
|
||||
PropertyAttributes::Default(descs[i].IsWritable(), descs[i].IsEnumerable(), descs[i].IsConfigurable());
|
||||
attr.SetSharedFieldType(descs[i].GetSharedFieldType());
|
||||
attr.SetBoxType(PropertyBoxType::UNDEFINED);
|
||||
JSHandle<NameDictionary> newDict = NameDictionary::Put(thread, dict, key, value, attr);
|
||||
dict.Update(newDict);
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -64,6 +64,8 @@ class ProtoChangeDetails;
|
||||
class PropertyLookupResult;
|
||||
class SharedHeap;
|
||||
class JSSharedArray;
|
||||
class LayoutInfo;
|
||||
class NameDictionary;
|
||||
namespace pgo {
|
||||
class HClassLayoutDesc;
|
||||
class PGOHClassTreeDesc;
|
||||
@ -1919,7 +1921,15 @@ public:
|
||||
DECL_VISIT_OBJECT(PROTOTYPE_OFFSET, BIT_FIELD_OFFSET);
|
||||
inline JSHClass *FindProtoTransitions(const JSTaggedValue &key, const JSTaggedValue &proto);
|
||||
|
||||
static JSHandle<JSHClass> CreateSHClass(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
bool isFunction = false);
|
||||
static JSHandle<JSHClass> CreateSConstructorHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
|
||||
static JSHandle<JSHClass> CreateSPrototypeHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
|
||||
|
||||
private:
|
||||
static JSHandle<LayoutInfo> CreateSInlinedLayout(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
|
||||
static JSHandle<NameDictionary> CreateSDictLayout(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
|
||||
static inline void AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
|
||||
const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key,
|
||||
PropertyAttributes attr);
|
||||
|
@ -333,6 +333,41 @@ void JSObject::OptimizeAsFastProperties(const JSThread *thread, JSHandle<JSObjec
|
||||
obj->SetProperties(thread, array);
|
||||
}
|
||||
|
||||
void JSObject::SetSProperties(JSThread *thread,
|
||||
JSHandle<JSObject> obj,
|
||||
JSHandle<JSHClass> hclass,
|
||||
const std::vector<PropertyDescriptor> &descs)
|
||||
{
|
||||
uint32_t length = descs.size();
|
||||
JSMutableHandle<JSTaggedValue> propKey(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> propValue(thread, JSTaggedValue::Undefined());
|
||||
|
||||
if (LIKELY(!hclass->IsDictionaryMode())) {
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
propValue.Update(descs[i].GetValue());
|
||||
// note(lzl): IsSAccessor?
|
||||
if (!propValue->IsSharedType() && !propValue->IsAccessor()) {
|
||||
THROW_TYPE_ERROR(thread, "The properties of sendable class must be sendable too.");
|
||||
}
|
||||
obj->SetPropertyInlinedProps(thread, i, propValue.GetTaggedValue());
|
||||
}
|
||||
} else {
|
||||
JSMutableHandle<ecmascript::NameDictionary> dict(
|
||||
thread, ecmascript::NameDictionary::CreateInSharedHeap(
|
||||
thread, ecmascript::NameDictionary::ComputeHashTableSize(length)));
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
propKey.Update(descs[i].GetKey());
|
||||
propValue.Update(descs[i].GetValue());
|
||||
PropertyAttributes attr =
|
||||
PropertyAttributes::Default(descs[i].IsWritable(), descs[i].IsEnumerable(), descs[i].IsConfigurable());
|
||||
JSHandle<ecmascript::NameDictionary> newDict =
|
||||
ecmascript::NameDictionary::PutIfAbsent(thread, dict, propKey, propValue, attr);
|
||||
dict.Update(newDict);
|
||||
}
|
||||
obj->SetProperties(thread, dict);
|
||||
}
|
||||
}
|
||||
|
||||
bool JSObject::IsArrayLengthWritable(JSThread *thread, const JSHandle<JSObject> &receiver)
|
||||
{
|
||||
auto *hclass = receiver->GetJSHClass();
|
||||
@ -2809,10 +2844,15 @@ void ECMAObject::SetNativePointerField(const JSThread *thread, int32_t index, vo
|
||||
if (static_cast<int32_t>(array->GetExtraLength()) > index) {
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
JSHandle<JSTaggedValue> current = JSHandle<JSTaggedValue>(thread, array->Get(thread, index));
|
||||
JSHandle<JSTaggedValue> obj(thread, this);
|
||||
if (!current->IsHole() && nativePointer == nullptr) {
|
||||
// Try to remove native pointer if exists.
|
||||
vm->RemoveFromNativePointerList(*JSHandle<JSNativePointer>(current));
|
||||
array->Set(thread, index, JSTaggedValue::Hole());
|
||||
} else if (obj->IsJSShared()) {
|
||||
JSHandle<JSNativePointer> pointer =
|
||||
vm->GetFactory()->NewSJSNativePointer(nativePointer, callBack, data, false, nativeBindingsize);
|
||||
array->Set(thread, index, pointer.GetTaggedValue());
|
||||
} else {
|
||||
JSHandle<JSNativePointer> pointer = vm->GetFactory()->NewJSNativePointer(
|
||||
nativePointer, callBack, data, false, nativeBindingsize, isConcurrent);
|
||||
@ -2848,7 +2888,8 @@ void ECMAObject::SetNativePointerFieldCount(const JSThread *thread, int32_t coun
|
||||
// Native Pointer field count is fixed.
|
||||
if (array->GetExtraLength() == 0) {
|
||||
JSHandle<TaggedArray> newArray =
|
||||
thread->GetEcmaVM()->GetFactory()->NewTaggedArray(count + RESOLVED_MAX_SIZE);
|
||||
value->IsJSShared() ? thread->GetEcmaVM()->GetFactory()->NewSTaggedArray(count + RESOLVED_MAX_SIZE)
|
||||
: thread->GetEcmaVM()->GetFactory()->NewTaggedArray(count + RESOLVED_MAX_SIZE);
|
||||
newArray->SetExtraLength(count);
|
||||
newArray->Set(thread, count + HASH_INDEX, array->Get(HASH_INDEX));
|
||||
newArray->Set(thread, count + FUNCTION_EXTRA_INDEX, array->Get(FUNCTION_EXTRA_INDEX));
|
||||
@ -2856,7 +2897,8 @@ void ECMAObject::SetNativePointerFieldCount(const JSThread *thread, int32_t coun
|
||||
}
|
||||
} else if (value->IsJSNativePointer()) {
|
||||
JSHandle<TaggedArray> newArray =
|
||||
thread->GetEcmaVM()->GetFactory()->NewTaggedArray(count + RESOLVED_MAX_SIZE);
|
||||
value->IsJSShared() ? thread->GetEcmaVM()->GetFactory()->NewSTaggedArray(count + RESOLVED_MAX_SIZE)
|
||||
: thread->GetEcmaVM()->GetFactory()->NewTaggedArray(count + RESOLVED_MAX_SIZE);
|
||||
newArray->SetExtraLength(count);
|
||||
newArray->Set(thread, count + HASH_INDEX, JSTaggedValue(0));
|
||||
newArray->Set(thread, count + FUNCTION_EXTRA_INDEX, value);
|
||||
@ -2866,7 +2908,9 @@ void ECMAObject::SetNativePointerFieldCount(const JSThread *thread, int32_t coun
|
||||
UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
JSHandle<TaggedArray> newArray = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(count + 1);
|
||||
JSHandle<TaggedArray> newArray = value->IsJSShared()
|
||||
? thread->GetEcmaVM()->GetFactory()->NewSTaggedArray(count + 1)
|
||||
: thread->GetEcmaVM()->GetFactory()->NewTaggedArray(count + 1);
|
||||
newArray->SetExtraLength(count);
|
||||
newArray->Set(thread, count + HASH_INDEX, value);
|
||||
Barriers::SetObject<true>(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
|
||||
|
@ -743,6 +743,11 @@ public:
|
||||
static void TryOptimizeAsFastElements(const JSThread *thread, JSHandle<JSObject> obj);
|
||||
static void OptimizeAsFastProperties(const JSThread *thread, JSHandle<JSObject> obj);
|
||||
|
||||
static void SetSProperties(JSThread *thread,
|
||||
JSHandle<JSObject> obj,
|
||||
JSHandle<JSHClass> hclass,
|
||||
const std::vector<PropertyDescriptor> &descs);
|
||||
|
||||
protected:
|
||||
static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj);
|
||||
|
||||
|
@ -215,6 +215,19 @@ void JSThread::InvokeWeakNodeFreeGlobalCallBack()
|
||||
}
|
||||
}
|
||||
|
||||
void JSThread::InvokeSharedNativePointerCallbacks()
|
||||
{
|
||||
auto callbacks = vm_->GetSharedNativePointerCallbacks();
|
||||
while (!callbacks.empty()) {
|
||||
auto callbackPair = callbacks.back();
|
||||
callbacks.pop_back();
|
||||
ASSERT(callbackPair.first != nullptr && callbackPair.second.first != nullptr &&
|
||||
callbackPair.second.second != nullptr);
|
||||
auto callback = callbackPair.first;
|
||||
(*callback)(callbackPair.second.first, callbackPair.second.second);
|
||||
}
|
||||
}
|
||||
|
||||
void JSThread::InvokeWeakNodeNativeFinalizeCallback()
|
||||
{
|
||||
// the second callback may lead to another GC, if this, return directly;
|
||||
@ -1043,6 +1056,9 @@ void JSThread::TransferToRunning()
|
||||
if (!weakNodeFreeGlobalCallbacks_.empty()) {
|
||||
InvokeWeakNodeFreeGlobalCallBack();
|
||||
}
|
||||
if (!vm_->GetSharedNativePointerCallbacks().empty()) {
|
||||
InvokeSharedNativePointerCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
void JSThread::StoreState(ThreadState newState, bool lockMutatorLock)
|
||||
|
@ -794,6 +794,7 @@ public:
|
||||
}
|
||||
|
||||
void InvokeWeakNodeFreeGlobalCallBack();
|
||||
void InvokeSharedNativePointerCallbacks();
|
||||
void InvokeWeakNodeNativeFinalizeCallback();
|
||||
bool IsStartGlobalLeakCheck() const;
|
||||
bool EnableGlobalObjectLeakCheck() const;
|
||||
|
122
ecmascript/jsnapi_sendable.cpp
Normal file
122
ecmascript/jsnapi_sendable.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 "ecmascript/jsnapi_sendable.h"
|
||||
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/napi/jsnapi_helper.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tagged_dictionary.h"
|
||||
#include "js_function.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
JSNapiSendable::JSNapiSendable(JSThread *thread, FunctionRef::SendablePropertiesInfos &infos, Local<StringRef> &name)
|
||||
{
|
||||
InitSPropertiesInfos(thread, infos, name);
|
||||
Init(thread, infos.staticPropertiesInfo, staticDescs_);
|
||||
Init(thread, infos.nonStaticPropertiesInfo, nonStaticDescs_);
|
||||
Init(thread, infos.instancePropertiesInfo, instanceDescs_);
|
||||
}
|
||||
|
||||
void JSNapiSendable::InitSPropertiesInfos(JSThread *thread,
|
||||
FunctionRef::SendablePropertiesInfos &infos,
|
||||
Local<StringRef> &name)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
JSHandle<JSTaggedValue> napiWrapperKey = globalConst->GetHandledNapiWrapperString();
|
||||
|
||||
infos.instancePropertiesInfo.keys.insert(infos.instancePropertiesInfo.keys.begin(),
|
||||
JSNApiHelper::ToLocal<StringRef>(napiWrapperKey));
|
||||
infos.instancePropertiesInfo.types.insert(infos.instancePropertiesInfo.types.begin(),
|
||||
FunctionRef::SendableType::OBJECT);
|
||||
infos.instancePropertiesInfo.attributes.insert(infos.instancePropertiesInfo.attributes.begin(),
|
||||
PropertyAttribute(JSValueRef::Null(vm), true, false, true));
|
||||
|
||||
JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
|
||||
infos.staticPropertiesInfo.keys.insert(infos.staticPropertiesInfo.keys.begin(),
|
||||
JSNApiHelper::ToLocal<StringRef>(nameKey));
|
||||
infos.staticPropertiesInfo.types.insert(infos.staticPropertiesInfo.types.begin(), FunctionRef::SendableType::NONE);
|
||||
infos.staticPropertiesInfo.attributes.insert(infos.staticPropertiesInfo.attributes.begin(),
|
||||
PropertyAttribute(name, false, false, false));
|
||||
|
||||
JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
|
||||
infos.nonStaticPropertiesInfo.keys.insert(infos.nonStaticPropertiesInfo.keys.begin(),
|
||||
JSNApiHelper::ToLocal<StringRef>(constructorKey));
|
||||
infos.nonStaticPropertiesInfo.types.insert(infos.nonStaticPropertiesInfo.types.begin(),
|
||||
FunctionRef::SendableType::OBJECT);
|
||||
infos.nonStaticPropertiesInfo.attributes.insert(infos.nonStaticPropertiesInfo.attributes.begin(),
|
||||
PropertyAttribute(JSValueRef::Null(vm), false, false, false));
|
||||
}
|
||||
|
||||
void JSNapiSendable::Init(JSThread *thread,
|
||||
FunctionRef::SendablePropertiesInfo &info,
|
||||
std::vector<PropertyDescriptor> &descs)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
auto length = info.keys.size();
|
||||
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
PropertyDescriptor desc(thread, info.attributes[i].IsWritable(), info.attributes[i].IsEnumerable(),
|
||||
info.attributes[i].IsConfigurable());
|
||||
desc.SetKey(JSNApiHelper::ToJSHandle(info.keys[i]));
|
||||
auto type = GetSharedFieldType(thread, info.types[i], info.attributes[i].GetValue(vm));
|
||||
desc.SetSharedFieldType(type);
|
||||
desc.SetValue(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm)));
|
||||
descs.push_back(desc);
|
||||
}
|
||||
}
|
||||
|
||||
SharedFieldType JSNapiSendable::GetSharedFieldType(JSThread *thread,
|
||||
FunctionRef::SendableType type,
|
||||
Local<JSValueRef> value)
|
||||
{
|
||||
switch (type) {
|
||||
case FunctionRef::SendableType::OBJECT:
|
||||
return SharedFieldType::SENDABLE;
|
||||
case FunctionRef::SendableType::NONE: {
|
||||
auto valueHandle = JSNApiHelper::ToJSHandle(value);
|
||||
if (valueHandle->IsUndefined()) {
|
||||
return SharedFieldType::NONE;
|
||||
}
|
||||
if (valueHandle->IsNull()) {
|
||||
// fixme: SharedFieldType::NULL ?
|
||||
return SharedFieldType::SENDABLE;
|
||||
}
|
||||
if (valueHandle->IsNumber()) {
|
||||
return SharedFieldType::NUMBER;
|
||||
}
|
||||
if (valueHandle->IsString()) {
|
||||
return SharedFieldType::STRING;
|
||||
}
|
||||
if (valueHandle->IsBoolean()) {
|
||||
return SharedFieldType::BOOLEAN;
|
||||
}
|
||||
if (valueHandle->IsJSShared()) {
|
||||
return SharedFieldType::SENDABLE;
|
||||
}
|
||||
if (valueHandle->IsBigInt()) {
|
||||
return SharedFieldType::BIG_INT;
|
||||
}
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
|
||||
}
|
||||
default:
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Unknown SharedFieldType", SharedFieldType::NONE);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript
|
58
ecmascript/jsnapi_sendable.h
Normal file
58
ecmascript/jsnapi_sendable.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_JS_NAPI_SENDABLE_H
|
||||
#define ECMASCRIPT_JS_NAPI_SENDABLE_H
|
||||
|
||||
#include "ecmascript/layout_info.h"
|
||||
#include "ecmascript/property_attributes.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
class JSNapiSendable {
|
||||
public:
|
||||
JSNapiSendable(JSThread *thread, FunctionRef::SendablePropertiesInfos &infos, Local<StringRef> &name);
|
||||
const std::vector<PropertyDescriptor> GetStaticDescs() const
|
||||
{
|
||||
return staticDescs_;
|
||||
}
|
||||
const std::vector<PropertyDescriptor> GetNonStaticDescs() const
|
||||
{
|
||||
return nonStaticDescs_;
|
||||
}
|
||||
const std::vector<PropertyDescriptor> GetInstanceDescs() const
|
||||
{
|
||||
return instanceDescs_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<PropertyDescriptor> staticDescs_;
|
||||
std::vector<PropertyDescriptor> nonStaticDescs_;
|
||||
std::vector<PropertyDescriptor> instanceDescs_;
|
||||
|
||||
static void InitSPropertiesInfos(JSThread *thread,
|
||||
FunctionRef::SendablePropertiesInfos &infos,
|
||||
Local<StringRef> &name);
|
||||
static void Init(JSThread *thread,
|
||||
FunctionRef::SendablePropertiesInfo &info,
|
||||
std::vector<PropertyDescriptor> &descs);
|
||||
static SharedFieldType GetSharedFieldType(JSThread *thread,
|
||||
FunctionRef::SendableType type,
|
||||
Local<JSValueRef> value);
|
||||
};
|
||||
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif
|
@ -86,6 +86,7 @@ void SharedGC::Sweep()
|
||||
ASSERT(!thread->IsInRunningState());
|
||||
thread->GetCurrentEcmaContext()->ProcessNativeDeleteInSharedGC(gcUpdateWeak);
|
||||
thread->IterateWeakEcmaGlobalStorage(gcUpdateWeak, true);
|
||||
thread->GetEcmaVM()->ProcessSharedNativeDelete(gcUpdateWeak);
|
||||
});
|
||||
|
||||
sHeap_->GetSweeper()->Sweep();
|
||||
|
@ -627,6 +627,11 @@ public:
|
||||
static Local<NativePointerRef> NewConcurrent(const EcmaVM *vm, void *nativePointer,
|
||||
NativePointerCallback callBack,
|
||||
void *data, size_t nativeBindingsize = 0);
|
||||
static Local<NativePointerRef> NewSendable(const EcmaVM *vm,
|
||||
void *nativePointer,
|
||||
NativePointerCallback callBack,
|
||||
void *data,
|
||||
size_t nativeBindingsize = 0);
|
||||
void *Value();
|
||||
};
|
||||
|
||||
@ -691,10 +696,14 @@ using FunctionCallback = Local<JSValueRef>(*)(JsiRuntimeCallInfo*);
|
||||
using InternalFunctionCallback = JSValueRef(*)(JsiRuntimeCallInfo*);
|
||||
class ECMA_PUBLIC_API FunctionRef : public ObjectRef {
|
||||
public:
|
||||
enum class SendableType {
|
||||
NONE,
|
||||
OBJECT,
|
||||
};
|
||||
struct SendablePropertiesInfo {
|
||||
Local<panda::ArrayRef> keys;
|
||||
Local<panda::ArrayRef> values;
|
||||
PropertyAttribute *attributes;
|
||||
std::vector<Local<JSValueRef>> keys;
|
||||
std::vector<SendableType> types;
|
||||
std::vector<PropertyAttribute> attributes;
|
||||
};
|
||||
struct SendablePropertiesInfos {
|
||||
SendablePropertiesInfo instancePropertiesInfo;
|
||||
@ -724,7 +733,7 @@ public:
|
||||
Deleter deleter,
|
||||
void *data,
|
||||
Local<StringRef> name,
|
||||
SendablePropertiesInfos infos,
|
||||
SendablePropertiesInfos &infos,
|
||||
Local<FunctionRef> parent,
|
||||
bool callNapi = false,
|
||||
size_t nativeBindingsize = 0);
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "ecmascript/js_tagged_number.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/js_typed_array.h"
|
||||
#include "ecmascript/jsnapi_sendable.h"
|
||||
#include "ecmascript/jspandafile/debug_info_extractor.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_executor.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
@ -132,6 +133,7 @@ using ecmascript::JSHClass;
|
||||
using ecmascript::JSIterator;
|
||||
using ecmascript::JSMap;
|
||||
using ecmascript::JSMapIterator;
|
||||
using ecmascript::JSNapiSendable;
|
||||
using ecmascript::JSNativePointer;
|
||||
using ecmascript::JSObject;
|
||||
using ecmascript::JSPandaFile;
|
||||
@ -2051,8 +2053,19 @@ Local<NativePointerRef> NativePointerRef::NewConcurrent(
|
||||
{
|
||||
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(nativePointer, callBack, data,
|
||||
false, nativeBindingsize, Concurrent::YES);
|
||||
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(vm->GetJSThread());
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
JSHandle<JSNativePointer> obj =
|
||||
factory->NewSJSNativePointer(nativePointer, callBack, data, false, nativeBindingsize);
|
||||
return JSNApiHelper::ToLocal<NativePointerRef>(JSHandle<JSTaggedValue>(obj));
|
||||
}
|
||||
|
||||
@ -2317,165 +2330,12 @@ Local<FunctionRef> FunctionRef::NewClassFunction(EcmaVM *vm, InternalFunctionCal
|
||||
return scope.Escape(result);
|
||||
}
|
||||
|
||||
ecmascript::SharedFieldType GetSharedFieldType(Local<JSValueRef> value)
|
||||
{
|
||||
auto valueHandle = JSNApiHelper::ToJSHandle(value);
|
||||
if (valueHandle->IsUndefined()) {
|
||||
return ecmascript::SharedFieldType::NONE;
|
||||
}
|
||||
if (valueHandle->IsNumber()) {
|
||||
return ecmascript::SharedFieldType::NUMBER;
|
||||
}
|
||||
if (valueHandle->IsString()) {
|
||||
return ecmascript::SharedFieldType::STRING;
|
||||
}
|
||||
if (valueHandle->IsBoolean()) {
|
||||
return ecmascript::SharedFieldType::BOOLEAN;
|
||||
}
|
||||
if (valueHandle->IsObject()) {
|
||||
return ecmascript::SharedFieldType::SENDABLE;
|
||||
}
|
||||
if (valueHandle->IsBigInt()) {
|
||||
return ecmascript::SharedFieldType::BIG_INT;
|
||||
}
|
||||
LOG_ECMA(ERROR) << "SharedFieldType";
|
||||
return ecmascript::SharedFieldType::NONE;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> CreateInlinedSendableHClass(JSThread *thread,
|
||||
FunctionRef::SendablePropertiesInfo info,
|
||||
bool isProtoClass)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
JSHandle<JSHClass> hclass;
|
||||
uint32_t length = info.keys->Length(vm);
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSHandle<ecmascript::LayoutInfo> layout = factory->CreateSLayoutInfo(length);
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
key.Update(JSNApiHelper::ToJSHandle(info.keys->Get(vm, i)));
|
||||
ASSERT(key->IsString());
|
||||
ecmascript::SharedFieldType type = GetSharedFieldType(info.values->Get(vm, i));
|
||||
ecmascript::PropertyAttributes attr = ecmascript::PropertyAttributes::Default(
|
||||
info.attributes[i].IsWritable(), info.attributes[i].IsEnumerable(), info.attributes[i].IsConfigurable());
|
||||
if (UNLIKELY(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm))->IsAccessor())) {
|
||||
attr.SetIsAccessor(true);
|
||||
}
|
||||
attr.SetIsInlinedProps(true);
|
||||
attr.SetRepresentation(ecmascript::Representation::TAGGED);
|
||||
attr.SetSharedFieldType(type);
|
||||
attr.SetOffset(i);
|
||||
layout->AddKey(thread, i, key.GetTaggedValue(), attr);
|
||||
}
|
||||
hclass = isProtoClass ? factory->NewSEcmaHClass(ecmascript::JSSharedObject::SIZE,
|
||||
ecmascript::JSType::JS_SHARED_OBJECT, length)
|
||||
: factory->NewSEcmaHClass(ecmascript::JSSharedFunction::SIZE,
|
||||
ecmascript::JSType::JS_SHARED_FUNCTION, length);
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(length);
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> CreateDictSendableHClass(JSThread *thread,
|
||||
FunctionRef::SendablePropertiesInfo info,
|
||||
bool isProtoClass)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
JSHandle<JSHClass> hclass;
|
||||
uint32_t length = info.keys->Length(vm);
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<ecmascript::NameDictionary> dict(thread,
|
||||
ecmascript::NameDictionary::CreateInSharedHeap(thread,
|
||||
ecmascript::NameDictionary::ComputeHashTableSize(length)));
|
||||
auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
|
||||
JSHandle<JSTaggedValue> value = globalConst->GetHandledUndefined();
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
key.Update(JSNApiHelper::ToJSHandle(info.keys->Get(vm, i)));
|
||||
ASSERT(key->IsString());
|
||||
ecmascript::SharedFieldType type = GetSharedFieldType(info.values->Get(vm, i));
|
||||
ecmascript::PropertyAttributes attr = ecmascript::PropertyAttributes::Default(
|
||||
info.attributes[i].IsWritable(), info.attributes[i].IsEnumerable(), info.attributes[i].IsConfigurable());
|
||||
attr.SetSharedFieldType(type);
|
||||
attr.SetBoxType(ecmascript::PropertyBoxType::UNDEFINED);
|
||||
JSHandle<ecmascript::NameDictionary> newDict = ecmascript::NameDictionary::Put(thread, dict, key, value, attr);
|
||||
dict.Update(newDict);
|
||||
}
|
||||
hclass =
|
||||
isProtoClass
|
||||
? factory->NewSEcmaHClass(ecmascript::JSSharedObject::SIZE, ecmascript::JSType::JS_SHARED_OBJECT, 0)
|
||||
: factory->NewSEcmaHClass(ecmascript::JSSharedFunction::SIZE, ecmascript::JSType::JS_SHARED_FUNCTION, 0);
|
||||
hclass->SetLayout(thread, dict);
|
||||
hclass->SetNumberOfProps(0);
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> CreateSendableHClass(JSThread *thread, FunctionRef::SendablePropertiesInfo info, bool isProtoClass)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
uint32_t length = info.keys->Length(vm);
|
||||
uint32_t maxInline =
|
||||
isProtoClass ? ecmascript::JSSharedObject::MAX_INLINE : ecmascript::JSSharedFunction::MAX_INLINE;
|
||||
JSHandle<JSHClass> hclass;
|
||||
|
||||
if (LIKELY(length <= maxInline)) {
|
||||
hclass = CreateInlinedSendableHClass(thread, info, isProtoClass);
|
||||
} else {
|
||||
hclass = CreateDictSendableHClass(thread, info, isProtoClass);
|
||||
}
|
||||
if (isProtoClass) {
|
||||
hclass->SetClassPrototype(true);
|
||||
hclass->SetIsPrototype(true);
|
||||
} else {
|
||||
hclass->SetClassConstructor(true);
|
||||
hclass->SetConstructor(true);
|
||||
}
|
||||
|
||||
return hclass;
|
||||
}
|
||||
|
||||
void SetInlinedAndDictProps(JSThread *thread,
|
||||
FunctionRef::SendablePropertiesInfo info,
|
||||
JSHandle<JSHClass> hclass,
|
||||
JSHandle<JSObject> obj)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
JSMutableHandle<JSTaggedValue> propKey(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> propValue(thread, JSTaggedValue::Undefined());
|
||||
|
||||
uint32_t length = info.keys->Length(vm);
|
||||
if (LIKELY(!hclass->IsDictionaryMode())) {
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
propValue.Update(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm)));
|
||||
obj->SetPropertyInlinedProps(thread, i, propValue.GetTaggedValue());
|
||||
}
|
||||
} else {
|
||||
JSMutableHandle<ecmascript::NameDictionary> dict(thread,
|
||||
ecmascript::NameDictionary::CreateInSharedHeap(thread,
|
||||
ecmascript::NameDictionary::ComputeHashTableSize(length)));
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
ecmascript::PropertyAttributes attr = ecmascript::PropertyAttributes::Default(
|
||||
info.attributes[i].IsWritable(), info.attributes[i].IsEnumerable(),
|
||||
info.attributes[i].IsConfigurable());
|
||||
propKey.Update(JSNApiHelper::ToJSHandle(info.keys->Get(vm, i)));
|
||||
propValue.Update(JSNApiHelper::ToJSHandle(info.attributes[i].GetValue(vm)));
|
||||
JSHandle<ecmascript::NameDictionary> newDict =
|
||||
ecmascript::NameDictionary::PutIfAbsent(thread, dict, propKey, propValue, attr);
|
||||
dict.Update(newDict);
|
||||
}
|
||||
obj->SetProperties(thread, dict);
|
||||
}
|
||||
}
|
||||
|
||||
Local<FunctionRef> FunctionRef::NewSendableClassFunction(const EcmaVM *vm,
|
||||
InternalFunctionCallback nativeFunc,
|
||||
Deleter deleter,
|
||||
void *data,
|
||||
Local<StringRef> name,
|
||||
SendablePropertiesInfos propertiesInfos,
|
||||
SendablePropertiesInfos &infos,
|
||||
Local<FunctionRef> parent,
|
||||
bool callNapi,
|
||||
size_t nativeBindingSize)
|
||||
@ -2484,27 +2344,19 @@ Local<FunctionRef> FunctionRef::NewSendableClassFunction(const EcmaVM *vm,
|
||||
ecmascript::ThreadManagedScope managedScope(thread);
|
||||
EscapeLocalScope scope(vm);
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
|
||||
auto [instancePropertiesInfo, staticPropertiesInfo, nonStaticPropertiesInfo] = propertiesInfos;
|
||||
JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
|
||||
staticPropertiesInfo.keys->Set(vm, 0, JSNApiHelper::ToLocal<StringRef>(nameKey));
|
||||
staticPropertiesInfo.values->Set(vm, 0, name);
|
||||
JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
|
||||
nonStaticPropertiesInfo.keys->Set(vm, 0, JSNApiHelper::ToLocal<StringRef>(constructorKey));
|
||||
nonStaticPropertiesInfo.values->Set(vm, 0, JSValueRef::Null(vm));
|
||||
|
||||
JSHandle<JSHClass> prototypeHClass = CreateSendableHClass(thread, nonStaticPropertiesInfo, true);
|
||||
JSNapiSendable sendable(thread, infos, name);
|
||||
JSHandle<JSHClass> prototypeHClass = JSHClass::CreateSPrototypeHClass(thread, sendable.GetNonStaticDescs());
|
||||
JSHandle<JSObject> prototype = factory->NewSharedOldSpaceJSObject(prototypeHClass);
|
||||
JSHandle<JSHClass> constructorHClass = CreateSendableHClass(thread, staticPropertiesInfo, false);
|
||||
JSHandle<JSHClass> constructorHClass = JSHClass::CreateSConstructorHClass(thread, sendable.GetStaticDescs());
|
||||
JSHandle<JSFunction> constructor = factory->NewSFunctionByHClass(
|
||||
reinterpret_cast<void *>(nativeFunc), constructorHClass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
|
||||
|
||||
staticPropertiesInfo.attributes[0] = PropertyAttribute(name, false, false, false);
|
||||
nonStaticPropertiesInfo.attributes[0] = PropertyAttribute(
|
||||
infos.nonStaticPropertiesInfo.attributes.front() = PropertyAttribute(
|
||||
JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>::Cast(constructor)), false, false, false);
|
||||
SetInlinedAndDictProps(thread, nonStaticPropertiesInfo, prototypeHClass, prototype);
|
||||
SetInlinedAndDictProps(thread, staticPropertiesInfo, constructorHClass, JSHandle<JSObject>::Cast(constructor));
|
||||
JSObject::SetSProperties(thread, prototype, prototypeHClass, sendable.GetNonStaticDescs());
|
||||
JSObject::SetSProperties(thread, JSHandle<JSObject>::Cast(constructor), constructorHClass,
|
||||
sendable.GetStaticDescs());
|
||||
|
||||
if (!parent->IsNull()) {
|
||||
auto parentPrototype = parent->GetFunctionPrototype(vm);
|
||||
@ -2518,7 +2370,7 @@ Local<FunctionRef> FunctionRef::NewSendableClassFunction(const EcmaVM *vm,
|
||||
constructor->SetCallNapi(callNapi);
|
||||
constructor->SetSFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingSize);
|
||||
|
||||
JSHandle<JSHClass> iHClass = CreateSendableHClass(thread, instancePropertiesInfo, true);
|
||||
JSHandle<JSHClass> iHClass = JSHClass::CreateSHClass(thread, sendable.GetInstanceDescs());
|
||||
iHClass->SetPrototype(thread, JSHandle<JSTaggedValue>(prototype));
|
||||
iHClass->SetExtensible(false);
|
||||
constructor->SetProtoOrHClass(thread, iHClass);
|
||||
|
@ -17,9 +17,6 @@
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// index 0 is name/constructor, index 1 is property to test.
|
||||
static constexpr int INITIAL_PROPERTY_LENGTH = 2;
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
|
||||
namespace panda::test {
|
||||
@ -107,40 +104,26 @@ panda::JSValueRef FunctionCallback(JsiRuntimeCallInfo *info)
|
||||
Local<FunctionRef> GetNewSendableClassFunction(
|
||||
EcmaVM *vm, const char *instanceKey, const char *staticKey, const char *nonStaticKey, Local<FunctionRef> parent)
|
||||
{
|
||||
Local<panda::ArrayRef> instanceKeys = panda::ArrayRef::New(vm, 1);
|
||||
Local<panda::ArrayRef> instanceValues = panda::ArrayRef::New(vm, 1);
|
||||
PropertyAttribute *instanceAttributes = new PropertyAttribute[1];
|
||||
// index 0 is name
|
||||
Local<panda::ArrayRef> staticKeys = panda::ArrayRef::New(vm, INITIAL_PROPERTY_LENGTH);
|
||||
Local<panda::ArrayRef> staticValues = panda::ArrayRef::New(vm, INITIAL_PROPERTY_LENGTH);
|
||||
PropertyAttribute *staticAttributes = new PropertyAttribute[INITIAL_PROPERTY_LENGTH];
|
||||
// index 0 is constructor
|
||||
Local<panda::ArrayRef> nonStaticKeys = panda::ArrayRef::New(vm, INITIAL_PROPERTY_LENGTH);
|
||||
Local<panda::ArrayRef> nonStaticValues = panda::ArrayRef::New(vm, INITIAL_PROPERTY_LENGTH);
|
||||
PropertyAttribute *nonStaticAttributes = new PropertyAttribute[INITIAL_PROPERTY_LENGTH];
|
||||
FunctionRef::SendablePropertiesInfos infos;
|
||||
|
||||
Local<StringRef> instanceStr = StringRef::NewFromUtf8(vm, instanceKey);
|
||||
instanceKeys->Set(vm, 0, instanceStr);
|
||||
instanceValues->Set(vm, 0, instanceStr);
|
||||
instanceAttributes[0] = PropertyAttribute(instanceStr, true, true, true);
|
||||
infos.instancePropertiesInfo.keys.push_back(instanceStr);
|
||||
infos.instancePropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.instancePropertiesInfo.attributes.push_back(PropertyAttribute(instanceStr, true, true, true));
|
||||
|
||||
Local<StringRef> staticStr = StringRef::NewFromUtf8(vm, staticKey);
|
||||
staticKeys->Set(vm, 1, staticStr);
|
||||
staticValues->Set(vm, 1, staticStr);
|
||||
staticAttributes[1] = PropertyAttribute(staticStr, true, true, true);
|
||||
infos.staticPropertiesInfo.keys.push_back(staticStr);
|
||||
infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(staticStr, true, true, true));
|
||||
|
||||
Local<StringRef> nonStaticStr = StringRef::NewFromUtf8(vm, nonStaticKey);
|
||||
nonStaticKeys->Set(vm, 1, nonStaticStr);
|
||||
nonStaticValues->Set(vm, 1, nonStaticStr);
|
||||
nonStaticAttributes[1] = PropertyAttribute(nonStaticStr, true, true, true);
|
||||
infos.nonStaticPropertiesInfo.keys.push_back(nonStaticStr);
|
||||
infos.nonStaticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.nonStaticPropertiesInfo.attributes.push_back(PropertyAttribute(nonStaticStr, true, true, true));
|
||||
|
||||
Local<StringRef> nameStr = StringRef::NewFromUtf8(vm, "name");
|
||||
Local<FunctionRef> constructor =
|
||||
FunctionRef::NewSendableClassFunction(vm, FunctionCallback, nullptr, nullptr, nameStr,
|
||||
{{instanceKeys, instanceValues, instanceAttributes},
|
||||
{staticKeys, staticValues, staticAttributes},
|
||||
{nonStaticKeys, nonStaticValues, nonStaticAttributes}},
|
||||
parent);
|
||||
FunctionRef::NewSendableClassFunction(vm, FunctionCallback, nullptr, nullptr, nameStr, infos, parent);
|
||||
|
||||
return constructor;
|
||||
}
|
||||
@ -291,17 +274,7 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionFunction)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
|
||||
Local<panda::ArrayRef> instanceKeys = panda::ArrayRef::New(vm_, 0);
|
||||
Local<panda::ArrayRef> instanceValues = panda::ArrayRef::New(vm_, 0);
|
||||
PropertyAttribute *instanceAttributes = new PropertyAttribute[0];
|
||||
// index 0 is name
|
||||
Local<panda::ArrayRef> staticKeys = panda::ArrayRef::New(vm_, INITIAL_PROPERTY_LENGTH);
|
||||
Local<panda::ArrayRef> staticValues = panda::ArrayRef::New(vm_, INITIAL_PROPERTY_LENGTH);
|
||||
PropertyAttribute *staticAttributes = new PropertyAttribute[INITIAL_PROPERTY_LENGTH];
|
||||
// index 0 is constructor
|
||||
Local<panda::ArrayRef> nonStaticKeys = panda::ArrayRef::New(vm_, 1);
|
||||
Local<panda::ArrayRef> nonStaticValues = panda::ArrayRef::New(vm_, 1);
|
||||
PropertyAttribute *nonStaticAttributes = new PropertyAttribute[1];
|
||||
FunctionRef::SendablePropertiesInfos infos;
|
||||
|
||||
Local<FunctionRef> func = FunctionRef::NewSendable(
|
||||
vm_,
|
||||
@ -311,16 +284,12 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionFunction)
|
||||
return **StringRef::NewFromUtf8(vm, "funcResult");
|
||||
},
|
||||
nullptr);
|
||||
staticKeys->Set(vm_, 1, staticKey);
|
||||
staticValues->Set(vm_, 1, func);
|
||||
staticAttributes[1] = PropertyAttribute(func, true, true, true);
|
||||
infos.staticPropertiesInfo.keys.push_back(staticKey);
|
||||
infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::OBJECT);
|
||||
infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(func, true, true, true));
|
||||
|
||||
Local<FunctionRef> constructor = FunctionRef::NewSendableClassFunction(
|
||||
vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"),
|
||||
{{instanceKeys, instanceValues, instanceAttributes},
|
||||
{staticKeys, staticValues, staticAttributes},
|
||||
{nonStaticKeys, nonStaticValues, nonStaticAttributes}},
|
||||
FunctionRef::Null(vm_));
|
||||
vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, FunctionRef::Null(vm_));
|
||||
|
||||
Local<FunctionRef> staticValue = constructor->Get(vm_, staticKey);
|
||||
ASSERT_TRUE(staticValue->IsFunction());
|
||||
@ -332,22 +301,12 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionGetterSetter)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
|
||||
Local<panda::ArrayRef> instanceKeys = panda::ArrayRef::New(vm_, 0);
|
||||
Local<panda::ArrayRef> instanceValues = panda::ArrayRef::New(vm_, 0);
|
||||
PropertyAttribute *instanceAttributes = new PropertyAttribute[0];
|
||||
// index 0 is name
|
||||
Local<panda::ArrayRef> staticKeys = panda::ArrayRef::New(vm_, 3);
|
||||
Local<panda::ArrayRef> staticValues = panda::ArrayRef::New(vm_, 3);
|
||||
PropertyAttribute *staticAttributes = new PropertyAttribute[3];
|
||||
// index 0 is constructor
|
||||
Local<panda::ArrayRef> nonStaticKeys = panda::ArrayRef::New(vm_, 1);
|
||||
Local<panda::ArrayRef> nonStaticValues = panda::ArrayRef::New(vm_, 1);
|
||||
PropertyAttribute *nonStaticAttributes = new PropertyAttribute[1];
|
||||
FunctionRef::SendablePropertiesInfos infos;
|
||||
|
||||
Local<StringRef> getterSetter = StringRef::NewFromUtf8(vm_, "getterSetter");
|
||||
staticKeys->Set(vm_, 1, getterSetter);
|
||||
staticValues->Set(vm_, 1, getterSetter);
|
||||
staticAttributes[1] = PropertyAttribute(getterSetter, true, true, true);
|
||||
infos.staticPropertiesInfo.keys.push_back(getterSetter);
|
||||
infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(getterSetter, true, true, true));
|
||||
Local<FunctionRef> staticGetter = FunctionRef::NewSendable(
|
||||
vm_,
|
||||
[](JsiRuntimeCallInfo *info) -> JSValueRef {
|
||||
@ -368,19 +327,17 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionGetterSetter)
|
||||
},
|
||||
nullptr);
|
||||
Local<JSValueRef> staticValue = panda::ObjectRef::CreateSendableAccessorData(vm_, staticGetter, staticSetter);
|
||||
staticKeys->Set(vm_, 2, staticKey);
|
||||
staticValues->Set(vm_, 2, staticValue);
|
||||
staticAttributes[2] = PropertyAttribute(staticValue, true, true, true);
|
||||
infos.staticPropertiesInfo.keys.push_back(staticKey);
|
||||
infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::OBJECT);
|
||||
infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(staticValue, true, true, true));
|
||||
|
||||
Local<FunctionRef> constructor = FunctionRef::NewSendableClassFunction(
|
||||
vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"),
|
||||
{{instanceKeys, instanceValues, instanceAttributes},
|
||||
{staticKeys, staticValues, staticAttributes},
|
||||
{nonStaticKeys, nonStaticValues, nonStaticAttributes}},
|
||||
FunctionRef::Null(vm_));
|
||||
vm_, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm_, "name"), infos, FunctionRef::Null(vm_));
|
||||
|
||||
ASSERT_EQ("getterSetter", constructor->Get(vm_, getterSetter)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("getterSetter", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString());
|
||||
constructor->Set(vm_, staticKey, StringRef::NewFromUtf8(vm_, "getterSetter0"));
|
||||
ASSERT_EQ("getterSetter0", constructor->Get(vm_, getterSetter)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("getterSetter0", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString());
|
||||
}
|
||||
|
||||
|
@ -766,7 +766,9 @@ public:
|
||||
|
||||
JSHandle<TaggedArray> NewSOldSpaceTaggedArray(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole());
|
||||
|
||||
JSHandle<TaggedArray> NewSTaggedArray(uint32_t length, JSTaggedValue initVal, MemSpaceType spaceType);
|
||||
JSHandle<TaggedArray> NewSTaggedArray(uint32_t length,
|
||||
JSTaggedValue initVal = JSTaggedValue::Hole(),
|
||||
MemSpaceType spaceType = SHARED_OLD_SPACE);
|
||||
|
||||
JSHandle<AccessorData> NewSAccessorData();
|
||||
|
||||
@ -816,6 +818,7 @@ public:
|
||||
JSHandle<JSSymbol> NewSWellKnownSymbolWithChar(std::string_view description);
|
||||
JSHandle<JSSymbol> NewSPublicSymbolWithChar(std::string_view description);
|
||||
JSHandle<JSSymbol> NewSPublicSymbol(const JSHandle<JSTaggedValue> &name);
|
||||
|
||||
private:
|
||||
friend class GlobalEnv;
|
||||
friend class GlobalEnvConstants;
|
||||
|
@ -362,7 +362,7 @@ JSHandle<JSNativePointer> ObjectFactory::NewSJSNativePointer(void *externalPoint
|
||||
obj->SetNativeFlag(flag);
|
||||
|
||||
if (callBack != nullptr) {
|
||||
vm_->PushToNativePointerList(static_cast<JSNativePointer *>(header));
|
||||
vm_->PushToSharedNativePointerList(static_cast<JSNativePointer *>(header));
|
||||
// In some cases, the size of JS/TS object is too small and the native binding size is too large.
|
||||
// Check and try trigger concurrent mark here.
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user