mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
!7013 Can not modify properties inherit from sendable parent in napi
Merge pull request !7013 from diartyz/bugfix
This commit is contained in:
commit
619ee92cf1
@ -1401,6 +1401,7 @@ PropertyLookupResult JSHClass::LookupPropertyInBuiltinHClass(const JSThread *thr
|
||||
|
||||
JSHandle<JSHClass> JSHClass::CreateSHClass(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
const JSHClass *parentHClass,
|
||||
bool isFunction)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
@ -1409,18 +1410,22 @@ JSHandle<JSHClass> JSHClass::CreateSHClass(JSThread *thread,
|
||||
uint32_t length = descs.size();
|
||||
uint32_t maxInline = isFunction ? JSSharedFunction::MAX_INLINE : JSSharedObject::MAX_INLINE;
|
||||
|
||||
if (parentHClass) {
|
||||
if (parentHClass->IsDictionaryMode()) {
|
||||
auto dict = reinterpret_cast<NameDictionary *>(parentHClass->GetLayout().GetTaggedObject());
|
||||
length += dict->EntriesCount();
|
||||
} else {
|
||||
length += parentHClass->NumberOfProps();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
CreateSInlinedLayout(thread, descs, hclass, parentHClass);
|
||||
} else {
|
||||
auto layout = CreateSDictLayout(thread, descs);
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(0);
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
CreateSDictLayout(thread, descs, hclass, parentHClass);
|
||||
}
|
||||
|
||||
return hclass;
|
||||
@ -1428,7 +1433,7 @@ JSHandle<JSHClass> JSHClass::CreateSHClass(JSThread *thread,
|
||||
|
||||
JSHandle<JSHClass> JSHClass::CreateSConstructorHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs)
|
||||
{
|
||||
auto hclass = CreateSHClass(thread, descs, true);
|
||||
auto hclass = CreateSHClass(thread, descs, nullptr, true);
|
||||
hclass->SetClassConstructor(true);
|
||||
hclass->SetConstructor(true);
|
||||
return hclass;
|
||||
@ -1442,15 +1447,22 @@ JSHandle<JSHClass> JSHClass::CreateSPrototypeHClass(JSThread *thread, const std:
|
||||
return hclass;
|
||||
}
|
||||
|
||||
JSHandle<LayoutInfo> JSHClass::CreateSInlinedLayout(JSThread *thread, const std::vector<PropertyDescriptor> &descs)
|
||||
void JSHClass::CreateSInlinedLayout(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
const JSHandle<JSHClass> &hclass,
|
||||
const JSHClass *parentHClass)
|
||||
{
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
|
||||
uint32_t parentLength{0};
|
||||
if (parentHClass) {
|
||||
parentLength = parentHClass->NumberOfProps();
|
||||
}
|
||||
auto length = descs.size();
|
||||
auto layout = factory->CreateSLayoutInfo(length);
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
auto layout = factory->CreateSLayoutInfo(length + parentLength);
|
||||
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
key.Update(descs[i].GetKey());
|
||||
PropertyAttributes attr =
|
||||
@ -1465,16 +1477,50 @@ JSHandle<LayoutInfo> JSHClass::CreateSInlinedLayout(JSThread *thread, const std:
|
||||
layout->AddKey(thread, i, key.GetTaggedValue(), attr);
|
||||
}
|
||||
|
||||
return layout;
|
||||
auto index = length;
|
||||
if (parentHClass) {
|
||||
JSHandle<LayoutInfo> old(thread, parentHClass->GetLayout());
|
||||
for (uint32_t i = 0; i < parentLength; i++) {
|
||||
key.Update(descs[i].GetKey());
|
||||
auto entry = layout->FindElementWithCache(thread, *hclass, key.GetTaggedValue(), index);
|
||||
if (entry != -1) {
|
||||
continue;
|
||||
}
|
||||
auto attr = PropertyAttributes(old->GetAttr(i));
|
||||
attr.SetOffset(index);
|
||||
layout->AddKey(thread, index, old->GetKey(i), attr);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
hclass->SetLayout(thread, layout);
|
||||
hclass->SetNumberOfProps(index);
|
||||
auto inlinedPropsLength = hclass->GetInlinedProperties();
|
||||
if (inlinedPropsLength > index) {
|
||||
uint32_t duplicatedSize = (inlinedPropsLength - index) * JSTaggedValue::TaggedTypeSize();
|
||||
hclass->SetObjectSize(hclass->GetObjectSize() - duplicatedSize);
|
||||
}
|
||||
}
|
||||
|
||||
JSHandle<NameDictionary> JSHClass::CreateSDictLayout(JSThread *thread, const std::vector<PropertyDescriptor> &descs)
|
||||
void JSHClass::CreateSDictLayout(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
const JSHandle<JSHClass> &hclass,
|
||||
const JSHClass *parentHClass)
|
||||
{
|
||||
uint32_t parentLength{0};
|
||||
if (parentHClass) {
|
||||
if (parentHClass->IsDictionaryMode()) {
|
||||
parentLength =
|
||||
reinterpret_cast<NameDictionary *>(parentHClass->GetLayout().GetTaggedObject())->EntriesCount();
|
||||
} else {
|
||||
parentLength = parentHClass->NumberOfProps();
|
||||
}
|
||||
}
|
||||
auto length = descs.size();
|
||||
JSMutableHandle<NameDictionary> dict(
|
||||
thread, NameDictionary::CreateInSharedHeap(thread, NameDictionary::ComputeHashTableSize(length)));
|
||||
thread,
|
||||
NameDictionary::CreateInSharedHeap(thread, NameDictionary::ComputeHashTableSize(length + parentLength)));
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
|
||||
auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
|
||||
JSHandle<JSTaggedValue> value = globalConst->GetHandledUndefined();
|
||||
|
||||
@ -1488,7 +1534,30 @@ JSHandle<NameDictionary> JSHClass::CreateSDictLayout(JSThread *thread, const std
|
||||
dict.Update(newDict);
|
||||
}
|
||||
|
||||
return dict;
|
||||
if (parentHClass) {
|
||||
if (parentHClass->IsDictionaryMode()) {
|
||||
JSHandle<NameDictionary> old(thread, parentHClass->GetLayout());
|
||||
std::vector<int> indexOrder = old->GetEnumerationOrder();
|
||||
for (uint32_t i = 0; i < parentLength; i++) {
|
||||
key.Update(old->GetKey(indexOrder[i]));
|
||||
JSHandle<NameDictionary> newDict = NameDictionary::Put(
|
||||
thread, dict, key, value, PropertyAttributes(old->GetAttributes(indexOrder[i])));
|
||||
dict.Update(newDict);
|
||||
}
|
||||
} else {
|
||||
JSHandle<LayoutInfo> old(thread, parentHClass->GetLayout());
|
||||
for (uint32_t i = 0; i < parentLength; i++) {
|
||||
key.Update(old->GetKey(i));
|
||||
JSHandle<NameDictionary> newDict =
|
||||
NameDictionary::Put(thread, dict, key, value, PropertyAttributes(old->GetAttr(i)));
|
||||
dict.Update(newDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hclass->SetLayout(thread, dict);
|
||||
hclass->SetNumberOfProps(0);
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -1999,13 +1999,20 @@ public:
|
||||
|
||||
static JSHandle<JSHClass> CreateSHClass(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
const JSHClass *parentHClass = nullptr,
|
||||
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 void CreateSInlinedLayout(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
const JSHandle<JSHClass> &hclass,
|
||||
const JSHClass *parentHClass = nullptr);
|
||||
static void CreateSDictLayout(JSThread *thread,
|
||||
const std::vector<PropertyDescriptor> &descs,
|
||||
const JSHandle<JSHClass> &hclass,
|
||||
const JSHClass *parentHClass = nullptr);
|
||||
static inline void AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
|
||||
const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key,
|
||||
PropertyAttributes attr);
|
||||
|
@ -2926,6 +2926,7 @@ Local<FunctionRef> FunctionRef::NewSendableClassFunction(const EcmaVM *vm,
|
||||
EscapeLocalScope scope(vm);
|
||||
ObjectFactory *factory = vm->GetFactory();
|
||||
|
||||
bool hasParent = !parent->IsNull();
|
||||
JSNapiSendable sendable(thread, infos, name);
|
||||
JSHandle<JSHClass> prototypeHClass = JSHClass::CreateSPrototypeHClass(thread, sendable.GetNonStaticDescs());
|
||||
JSHandle<JSObject> prototype = factory->NewSharedOldSpaceJSObject(prototypeHClass);
|
||||
@ -2937,23 +2938,28 @@ Local<FunctionRef> FunctionRef::NewSendableClassFunction(const EcmaVM *vm,
|
||||
JSObject::SetSProperties(thread, prototype, sendable.GetNonStaticDescs());
|
||||
JSObject::SetSProperties(thread, JSHandle<JSObject>::Cast(constructor), sendable.GetStaticDescs());
|
||||
|
||||
if (!parent->IsNull()) {
|
||||
if (hasParent) {
|
||||
auto parentPrototype = parent->GetFunctionPrototype(vm);
|
||||
prototypeHClass->SetPrototype(thread, JSNApiHelper::ToJSHandle(parentPrototype));
|
||||
constructorHClass->SetPrototype(thread, JSNApiHelper::ToJSHandle(parent));
|
||||
}
|
||||
prototype->GetJSHClass()->SetExtensible(false);
|
||||
prototypeHClass->SetExtensible(false);
|
||||
constructor->SetHomeObject(thread, prototype);
|
||||
constructor->SetProtoOrHClass(thread, prototype);
|
||||
constructor->SetLexicalEnv(thread, constructor);
|
||||
constructor->SetCallNapi(callNapi);
|
||||
constructor->SetSFunctionExtraInfo(thread, nullptr, deleter, data, nativeBindingSize);
|
||||
|
||||
JSHandle<JSHClass> iHClass = JSHClass::CreateSHClass(thread, sendable.GetInstanceDescs());
|
||||
JSHClass *parentIHClass{nullptr};
|
||||
if (hasParent) {
|
||||
JSHandle<JSFunction> parentHandle(JSNApiHelper::ToJSHandle(parent));
|
||||
parentIHClass = reinterpret_cast<JSHClass *>(parentHandle->GetProtoOrHClass().GetTaggedObject());
|
||||
}
|
||||
JSHandle<JSHClass> iHClass = JSHClass::CreateSHClass(thread, sendable.GetInstanceDescs(), parentIHClass);
|
||||
iHClass->SetPrototype(thread, JSHandle<JSTaggedValue>(prototype));
|
||||
iHClass->SetExtensible(false);
|
||||
constructor->SetProtoOrHClass(thread, iHClass);
|
||||
constructor->GetJSHClass()->SetExtensible(false);
|
||||
constructorHClass->SetExtensible(false);
|
||||
|
||||
Local<FunctionRef> result = JSNApiHelper::ToLocal<FunctionRef>(JSHandle<JSTaggedValue>(constructor));
|
||||
return scope.Escape(result);
|
||||
|
@ -101,26 +101,62 @@ panda::JSValueRef FunctionCallback(JsiRuntimeCallInfo *info)
|
||||
return **thisRef;
|
||||
}
|
||||
|
||||
Local<FunctionRef> GetNewSendableClassFunction(
|
||||
EcmaVM *vm, const char *instanceKey, const char *staticKey, const char *nonStaticKey, Local<FunctionRef> parent)
|
||||
Local<FunctionRef> GetNewSendableClassFunction(EcmaVM *vm,
|
||||
Local<FunctionRef> parent,
|
||||
bool isDict = false,
|
||||
bool duplicated = false)
|
||||
{
|
||||
FunctionRef::SendablePropertiesInfos infos;
|
||||
|
||||
Local<StringRef> instanceStr = StringRef::NewFromUtf8(vm, instanceKey);
|
||||
if (isDict) {
|
||||
uint32_t maxInline = std::max(JSSharedFunction::MAX_INLINE, JSSharedObject::MAX_INLINE);
|
||||
for (uint32_t i = 0; i < maxInline; ++i) {
|
||||
Local<StringRef> tempStr = StringRef::NewFromUtf8(vm, std::to_string(i).c_str());
|
||||
infos.instancePropertiesInfo.keys.push_back(tempStr);
|
||||
infos.instancePropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.instancePropertiesInfo.attributes.push_back(PropertyAttribute(tempStr, true, true, true));
|
||||
infos.staticPropertiesInfo.keys.push_back(tempStr);
|
||||
infos.staticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.staticPropertiesInfo.attributes.push_back(PropertyAttribute(tempStr, true, true, true));
|
||||
infos.nonStaticPropertiesInfo.keys.push_back(tempStr);
|
||||
infos.nonStaticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.nonStaticPropertiesInfo.attributes.push_back(PropertyAttribute(tempStr, true, true, true));
|
||||
}
|
||||
}
|
||||
|
||||
std::string instanceKey = "instance";
|
||||
std::string staticKey = "static";
|
||||
std::string nonStaticKey = "nonStatic";
|
||||
|
||||
if (!parent->IsNull()) {
|
||||
instanceKey = "parentInstance";
|
||||
staticKey = "parentStatic";
|
||||
nonStaticKey = "parentNonStatic";
|
||||
}
|
||||
|
||||
Local<StringRef> instanceStr = StringRef::NewFromUtf8(vm, instanceKey.c_str());
|
||||
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);
|
||||
Local<StringRef> staticStr = StringRef::NewFromUtf8(vm, staticKey.c_str());
|
||||
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);
|
||||
Local<StringRef> nonStaticStr = StringRef::NewFromUtf8(vm, nonStaticKey.c_str());
|
||||
infos.nonStaticPropertiesInfo.keys.push_back(nonStaticStr);
|
||||
infos.nonStaticPropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.nonStaticPropertiesInfo.attributes.push_back(PropertyAttribute(nonStaticStr, true, true, true));
|
||||
|
||||
if (duplicated) {
|
||||
Local<StringRef> duplicatedKey = StringRef::NewFromUtf8(vm, "instance");
|
||||
Local<NumberRef> duplicatedValue = NumberRef::New(vm, 0);
|
||||
infos.instancePropertiesInfo.keys.push_back(duplicatedKey);
|
||||
infos.instancePropertiesInfo.types.push_back(FunctionRef::SendableType::NONE);
|
||||
infos.instancePropertiesInfo.attributes.push_back(PropertyAttribute(duplicatedValue, true, true, true));
|
||||
}
|
||||
|
||||
Local<FunctionRef> constructor = FunctionRef::NewSendableClassFunction(
|
||||
vm, FunctionCallback, nullptr, nullptr, StringRef::NewFromUtf8(vm, "name"), infos, parent);
|
||||
|
||||
@ -130,8 +166,7 @@ Local<FunctionRef> GetNewSendableClassFunction(
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunction)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> constructor =
|
||||
GetNewSendableClassFunction(vm_, "instance", "static", "nonStatic", FunctionRef::Null(vm_));
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_));
|
||||
|
||||
ASSERT_EQ("name", constructor->GetName(vm_)->ToString());
|
||||
ASSERT_TRUE(constructor->IsFunction());
|
||||
@ -154,8 +189,41 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunction)
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionProperties)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> constructor =
|
||||
GetNewSendableClassFunction(vm_, "instance", "static", "nonStatic", FunctionRef::Null(vm_));
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_));
|
||||
Local<ObjectRef> prototype = constructor->GetFunctionPrototype(vm_);
|
||||
|
||||
ASSERT_EQ("static", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("nonStatic", prototype->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("undefined", constructor->Get(vm_, invalidKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("undefined", prototype->Get(vm_, invalidKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set static property on constructor
|
||||
constructor->Set(vm_, staticKey, StringRef::NewFromUtf8(vm_, "static0"));
|
||||
ASSERT_EQ("static0", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set non static property on prototype
|
||||
prototype->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic0"));
|
||||
ASSERT_EQ("nonStatic0", prototype->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set invalid property on constructor
|
||||
ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
|
||||
constructor->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
|
||||
ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
|
||||
JSNApi::GetAndClearUncaughtException(vm_);
|
||||
ASSERT_EQ("undefined", constructor->Get(vm_, invalidKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set invalid property on prototype
|
||||
ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
|
||||
prototype->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
|
||||
ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
|
||||
JSNApi::GetAndClearUncaughtException(vm_);
|
||||
ASSERT_EQ("undefined", prototype->Get(vm_, invalidKey)->ToString(vm_)->ToString());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictProperties)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), true);
|
||||
Local<ObjectRef> prototype = constructor->GetFunctionPrototype(vm_);
|
||||
|
||||
ASSERT_EQ("static", constructor->Get(vm_, staticKey)->ToString(vm_)->ToString());
|
||||
@ -189,8 +257,50 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionProperties)
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInstance)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> constructor =
|
||||
GetNewSendableClassFunction(vm_, "instance", "static", "nonStatic", FunctionRef::Null(vm_));
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_));
|
||||
Local<JSValueRef> argv[1] = {NumberRef::New(vm_, 0)};
|
||||
Local<ObjectRef> obj = constructor->Constructor(vm_, argv, 0);
|
||||
Local<ObjectRef> obj0 = constructor->Constructor(vm_, argv, 0);
|
||||
|
||||
ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(constructor)));
|
||||
ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(constructor)));
|
||||
|
||||
// set instance property
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, instanceKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("undefined", obj0->Get(vm_, instanceKey)->ToString(vm_)->ToString());
|
||||
obj->Set(vm_, instanceKey, StringRef::NewFromUtf8(vm_, "instance"));
|
||||
ASSERT_EQ("instance", obj->Get(vm_, instanceKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("undefined", obj0->Get(vm_, instanceKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set non static property on prototype and get from instance
|
||||
ASSERT_EQ("nonStatic", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("nonStatic", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
Local<ObjectRef> prototype = obj->GetPrototype(vm_);
|
||||
prototype->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic0"));
|
||||
ASSERT_EQ("nonStatic0", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("nonStatic0", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set non static property on instance
|
||||
ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
|
||||
obj->Set(vm_, nonStaticKey, StringRef::NewFromUtf8(vm_, "nonStatic1"));
|
||||
ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
|
||||
JSNApi::GetAndClearUncaughtException(vm_);
|
||||
ASSERT_EQ("nonStatic0", obj->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("nonStatic0", obj0->Get(vm_, nonStaticKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set invalid property on instance
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, invalidKey)->ToString(vm_)->ToString());
|
||||
ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
|
||||
obj->Set(vm_, invalidKey, StringRef::NewFromUtf8(vm_, "invalid"));
|
||||
ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
|
||||
JSNApi::GetAndClearUncaughtException(vm_);
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, invalidKey)->ToString(vm_)->ToString());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInstance)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), true);
|
||||
Local<JSValueRef> argv[1] = {NumberRef::New(vm_, 0)};
|
||||
Local<ObjectRef> obj = constructor->Constructor(vm_, argv, 0);
|
||||
Local<ObjectRef> obj0 = constructor->Constructor(vm_, argv, 0);
|
||||
@ -233,9 +343,8 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInstance)
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInherit)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> parent =
|
||||
GetNewSendableClassFunction(vm_, "parentInstance", "parentStatic", "parentNonStatic", FunctionRef::Null(vm_));
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, "instance", "static", "nonStatic", parent);
|
||||
Local<FunctionRef> parent = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_));
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, parent);
|
||||
Local<JSValueRef> argv[1] = {NumberRef::New(vm_, 0)};
|
||||
Local<ObjectRef> obj = constructor->Constructor(vm_, argv, 0);
|
||||
Local<ObjectRef> obj0 = constructor->Constructor(vm_, argv, 0);
|
||||
@ -246,11 +355,8 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInherit)
|
||||
// set parent instance property on instance
|
||||
Local<StringRef> parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance");
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString());
|
||||
ASSERT_FALSE(vm_->GetJSThread()->HasPendingException());
|
||||
obj->Set(vm_, parentInstanceKey, StringRef::NewFromUtf8(vm_, "parentInstance"));
|
||||
ASSERT_TRUE(vm_->GetJSThread()->HasPendingException());
|
||||
JSNApi::GetAndClearUncaughtException(vm_);
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString());
|
||||
ASSERT_EQ("parentInstance", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString());
|
||||
|
||||
// get parent static property from constructor
|
||||
Local<StringRef> parentStaticKey = StringRef::NewFromUtf8(vm_, "parentStatic");
|
||||
@ -261,6 +367,56 @@ HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInherit)
|
||||
ASSERT_EQ("parentNonStatic", obj->Get(vm_, parentNonStaticKey)->ToString(vm_)->ToString());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionDictInherit)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> parent = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_), true);
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, parent);
|
||||
Local<JSValueRef> argv[1] = {NumberRef::New(vm_, 0)};
|
||||
Local<ObjectRef> obj = constructor->Constructor(vm_, argv, 0);
|
||||
Local<ObjectRef> obj0 = constructor->Constructor(vm_, argv, 0);
|
||||
|
||||
ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent)));
|
||||
ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj0), JSNApiHelper::ToJSHandle(parent)));
|
||||
|
||||
// set parent instance property on instance
|
||||
Local<StringRef> parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance");
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString());
|
||||
obj->Set(vm_, parentInstanceKey, StringRef::NewFromUtf8(vm_, "parentInstance"));
|
||||
ASSERT_EQ("parentInstance", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString());
|
||||
|
||||
// get parent static property from constructor
|
||||
Local<StringRef> parentStaticKey = StringRef::NewFromUtf8(vm_, "parentStatic");
|
||||
ASSERT_EQ("parentStatic", constructor->Get(vm_, parentStaticKey)->ToString(vm_)->ToString());
|
||||
|
||||
// get parent non static property form instance
|
||||
Local<StringRef> parentNonStaticKey = StringRef::NewFromUtf8(vm_, "parentNonStatic");
|
||||
ASSERT_EQ("parentNonStatic", obj->Get(vm_, parentNonStaticKey)->ToString(vm_)->ToString());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSNApiTests, NewSendableClassFunctionInheritWithDuplicatedKey)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
Local<FunctionRef> parent = GetNewSendableClassFunction(vm_, FunctionRef::Null(vm_));
|
||||
Local<FunctionRef> constructor = GetNewSendableClassFunction(vm_, parent, false, true);
|
||||
Local<JSValueRef> argv[1] = {NumberRef::New(vm_, 0)};
|
||||
Local<ObjectRef> obj = constructor->Constructor(vm_, argv, 0);
|
||||
|
||||
ASSERT_TRUE(JSFunction::InstanceOf(thread_, JSNApiHelper::ToJSHandle(obj), JSNApiHelper::ToJSHandle(parent)));
|
||||
|
||||
// set parent instance property on instance
|
||||
Local<StringRef> parentInstanceKey = StringRef::NewFromUtf8(vm_, "parentInstance");
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString());
|
||||
obj->Set(vm_, parentInstanceKey, StringRef::NewFromUtf8(vm_, "parentInstance"));
|
||||
ASSERT_EQ("parentInstance", obj->Get(vm_, parentInstanceKey)->ToString(vm_)->ToString());
|
||||
|
||||
// set duplicated instance property on instance
|
||||
Local<StringRef> duplicatedInstanceKey = StringRef::NewFromUtf8(vm_, "instance");
|
||||
ASSERT_EQ("undefined", obj->Get(vm_, duplicatedInstanceKey)->ToString(vm_)->ToString());
|
||||
obj->Set(vm_, duplicatedInstanceKey, NumberRef::New(vm_, 1));
|
||||
ASSERT_EQ("1", obj->Get(vm_, duplicatedInstanceKey)->ToString(vm_)->ToString());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSNApiTests, NewSendable)
|
||||
{
|
||||
LocalScope scope(vm_);
|
||||
|
Loading…
Reference in New Issue
Block a user