Add sendable napi

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9O3XT?from=project-issue
Signed-off-by: liu-zelin <liuzelin8@huawei.com>
Change-Id: I6f361f4e3dd454d14ac9ef22a924118c7a41844b
This commit is contained in:
liu-zelin 2024-05-10 12:01:04 +08:00
parent c5738ee27e
commit 76cbb82b9d
9 changed files with 94 additions and 26 deletions

View File

@ -334,16 +334,13 @@ 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)
void JSObject::SetSProperties(JSThread *thread, JSHandle<JSObject> obj, 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())) {
if (LIKELY(!obj->GetJSHClass()->IsDictionaryMode())) {
for (uint32_t i = 0; i < length; ++i) {
propValue.Update(descs[i].GetValue());
// note(lzl): IsSAccessor?

View File

@ -749,10 +749,7 @@ 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);
static void SetSProperties(JSThread *thread, JSHandle<JSObject> obj, const std::vector<PropertyDescriptor> &descs);
protected:
static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj);

View File

@ -28,6 +28,7 @@ JSNapiSendable::JSNapiSendable(JSThread *thread, FunctionRef::SendableProperties
{
InitStaticDescription(thread, staticDescs_, name);
InitNonStaticDescription(thread, nonStaticDescs_);
InitInstanceDescription(thread, instanceDescs_);
InitWithPropertiesInfo(thread, infos.staticPropertiesInfo, staticDescs_);
InitWithPropertiesInfo(thread, infos.nonStaticPropertiesInfo, nonStaticDescs_);
InitWithPropertiesInfo(thread, infos.instancePropertiesInfo, instanceDescs_);
@ -71,6 +72,18 @@ void JSNapiSendable::InitNonStaticDescription(JSThread *thread, std::vector<Prop
descs.push_back(constructorDesc);
}
void JSNapiSendable::InitInstanceDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs)
{
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
JSHandle<JSTaggedValue> napiWrapperKey = globalConst->GetHandledNapiWrapperString();
PropertyDescriptor napiWrapperDesc(thread, true, false, false);
napiWrapperDesc.SetKey(napiWrapperKey);
napiWrapperDesc.SetSharedFieldType(SharedFieldType::SENDABLE);
napiWrapperDesc.SetValue(globalConst->GetHandledNull());
descs.push_back(napiWrapperDesc);
}
void JSNapiSendable::InitWithPropertiesInfo(JSThread *thread,
FunctionRef::SendablePropertiesInfo &info,
std::vector<PropertyDescriptor> &descs)

View File

@ -37,6 +37,9 @@ public:
{
return instanceDescs_;
}
static void InitWithPropertiesInfo(JSThread *thread,
FunctionRef::SendablePropertiesInfo &info,
std::vector<PropertyDescriptor> &descs);
private:
std::vector<PropertyDescriptor> staticDescs_;
@ -45,9 +48,7 @@ private:
static void InitStaticDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs, Local<StringRef> &name);
static void InitNonStaticDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs);
static void InitWithPropertiesInfo(JSThread *thread,
FunctionRef::SendablePropertiesInfo &info,
std::vector<PropertyDescriptor> &descs);
static void InitInstanceDescription(JSThread *thread, std::vector<PropertyDescriptor> &descs);
static SharedFieldType GetSharedFieldType(JSThread *thread,
FunctionRef::SendableType type,
Local<JSValueRef> value);

View File

@ -491,6 +491,7 @@ public:
bool IsTreeSet();
bool IsVector();
bool IsSharedObject();
bool IsSharedFunction();
bool IsJSShared();
bool IsSharedArray();
bool IsSharedTypedArray();
@ -642,14 +643,25 @@ public:
class ECMA_PUBLIC_API ObjectRef : public JSValueRef {
public:
enum class SendableType {
NONE,
OBJECT,
};
struct SendablePropertiesInfo {
std::vector<Local<JSValueRef>> keys;
std::vector<SendableType> types;
std::vector<PropertyAttribute> attributes;
};
static constexpr int MAX_PROPERTIES_ON_STACK = 32;
static inline ObjectRef *Cast(JSValueRef *value)
{
return static_cast<ObjectRef *>(value);
}
static Local<ObjectRef> New(const EcmaVM *vm);
static Local<ObjectRef> NewS(const EcmaVM *vm);
static Local<ObjectRef> NewWithProperties(const EcmaVM *vm, size_t propertyCount, const Local<JSValueRef> *keys,
const PropertyAttribute *attributes);
static Local<ObjectRef> NewSWithProperties(const EcmaVM *vm, SendablePropertiesInfo &info);
static Local<ObjectRef> NewWithNamedProperties(const EcmaVM *vm, size_t propertyCount, const char **keys,
const Local<JSValueRef> *values);
static Local<ObjectRef> CreateAccessorData(const EcmaVM *vm, Local<FunctionRef> getter, Local<FunctionRef> setter);
@ -703,15 +715,6 @@ using FunctionCallback = Local<JSValueRef>(*)(JsiRuntimeCallInfo*);
using InternalFunctionCallback = JSValueRef(*)(JsiRuntimeCallInfo*);
class ECMA_PUBLIC_API FunctionRef : public ObjectRef {
public:
enum class SendableType {
NONE,
OBJECT,
};
struct SendablePropertiesInfo {
std::vector<Local<JSValueRef>> keys;
std::vector<SendableType> types;
std::vector<PropertyAttribute> attributes;
};
struct SendablePropertiesInfos {
SendablePropertiesInfo instancePropertiesInfo;
SendablePropertiesInfo staticPropertiesInfo;

View File

@ -820,6 +820,11 @@ bool JSValueRef::IsSharedObject()
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedObject();
}
bool JSValueRef::IsSharedFunction()
{
return JSNApiHelper::ToJSTaggedValue(this).IsJSSharedFunction();
}
bool JSValueRef::IsJSShared()
{
return JSNApiHelper::ToJSTaggedValue(this).IsJSShared();
@ -1720,6 +1725,17 @@ Local<ObjectRef> ObjectRef::New(const EcmaVM *vm)
return JSNApiHelper::ToLocal<ObjectRef>(object);
}
Local<ObjectRef> ObjectRef::NewS(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
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)
@ -1754,6 +1770,19 @@ Local<ObjectRef> ObjectRef::NewWithProperties(const EcmaVM *vm, size_t propertyC
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(vm->GetJSThread());
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)
{
@ -2519,9 +2548,8 @@ Local<FunctionRef> FunctionRef::NewSendableClassFunction(const EcmaVM *vm,
reinterpret_cast<void *>(nativeFunc), constructorHClass, ecmascript::FunctionKind::CLASS_CONSTRUCTOR);
sendable.SetSConstructor(constructor);
JSObject::SetSProperties(thread, prototype, prototypeHClass, sendable.GetNonStaticDescs());
JSObject::SetSProperties(thread, JSHandle<JSObject>::Cast(constructor), constructorHClass,
sendable.GetStaticDescs());
JSObject::SetSProperties(thread, prototype, sendable.GetNonStaticDescs());
JSObject::SetSProperties(thread, JSHandle<JSObject>::Cast(constructor), sendable.GetStaticDescs());
if (!parent->IsNull()) {
auto parentPrototype = parent->GetFunctionPrototype(vm);

View File

@ -347,4 +347,19 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionGetterSetter)
ASSERT_EQ("getterSetter0", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString());
}
HWTEST_F_L0(JSNApiTests, NewObjectWithProperties)
{
LocalScope scope(vm_);
FunctionRef::SendablePropertiesInfo info;
Local<StringRef> str = StringRef::NewFromUtf8(vm_, "str");
info.keys.push_back(str);
info.types.push_back(FunctionRef::SendableType::NONE);
info.attributes.push_back(PropertyAttribute(str, true, true, true));
Local<ObjectRef> object = ObjectRef::NewSWithProperties(vm_, info);
Local<JSValueRef> value = object->Get(vm_, str);
EXPECT_TRUE(str->IsStrictEquals(vm_, value));
}
} // namespace panda::test

View File

@ -704,6 +704,8 @@ public:
TaggedObject *NewSharedOldSpaceObject(const JSHandle<JSHClass> &hclass);
JSHandle<JSTaggedValue> CreateSObjectWithProperties(std::vector<PropertyDescriptor> &descs);
JSHandle<JSHClass> PUBLIC_API NewSEcmaHClass(uint32_t size, JSType type, uint32_t inlinedProps);
JSHandle<JSHClass> PUBLIC_API NewSEcmaHClass(JSHClass *hclass, uint32_t size, JSType type,

View File

@ -291,6 +291,18 @@ JSHandle<JSObject> ObjectFactory::NewSharedOldSpaceJSObject(const JSHandle<JSHCl
return obj;
}
JSHandle<JSTaggedValue> ObjectFactory::CreateSObjectWithProperties(std::vector<PropertyDescriptor> &descs)
{
JSHandle<JSHClass> hclass = JSHClass::CreateSHClass(thread_, descs);
JSHandle<JSObject> object = NewSharedOldSpaceJSObject(hclass);
JSObject::SetSProperties(thread_, object, descs);
JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
JSHandle<JSTaggedValue> objFuncProto = env->GetSObjectFunctionPrototype();
hclass->SetPrototype(thread_, objFuncProto);
hclass->SetExtensible(false);
return JSHandle<JSTaggedValue>(object);
}
JSHandle<TaggedArray> ObjectFactory::SharedEmptyArray() const
{
return JSHandle<TaggedArray>(thread_->GlobalConstants()->GetHandledEmptyArray());