mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Fix stringify bug for supporting proxy object
Add processing logic to handle proxy objects and avoid code logic from entering serialize proxy. Issue: https://gitee.com/openharmony/ark_js_runtime/issues/I4ZLYT Signed-off-by: xujie <xujie101@huawei.com> Change-Id: If8c7c59bb9e0d6c156b13c5badf3c3f489c2b146
This commit is contained in:
parent
6075ee8512
commit
38f7a9f0c7
@ -374,7 +374,9 @@ JSTaggedValue JsonStringifier::SerializeJSONProperty(const JSHandle<JSTaggedValu
|
||||
return JSTaggedValue::Undefined();
|
||||
default: {
|
||||
if (!tagValue.IsCallable()) {
|
||||
if (UNLIKELY(tagValue.IsJSProxy())) {
|
||||
JSHClass *jsHclass = tagValue.GetTaggedObject()->GetClass();
|
||||
if (UNLIKELY(jsHclass->IsJSProxy() &&
|
||||
JSProxy::Cast(tagValue.GetTaggedObject())->IsArray(thread_))) {
|
||||
SerializeJSProxy(valHandle, replacer);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
} else {
|
||||
@ -451,15 +453,38 @@ bool JsonStringifier::SerializeJSONObject(const JSHandle<JSTaggedValue> &value,
|
||||
|
||||
JSHandle<JSObject> obj(value);
|
||||
if (!replacer->IsArray(thread_)) {
|
||||
uint32_t numOfKeys = obj->GetNumberOfKeys();
|
||||
uint32_t numOfElements = obj->GetNumberOfElements();
|
||||
if (numOfElements > 0) {
|
||||
hasContent = JsonStringifier::SerializeElements(obj, replacer, hasContent);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
|
||||
}
|
||||
if (numOfKeys > 0) {
|
||||
hasContent = JsonStringifier::SerializeKeys(obj, replacer, hasContent);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
|
||||
if (UNLIKELY(value->IsJSProxy())) { // serialize proxy object
|
||||
JSHandle<JSProxy> proxy(value);
|
||||
JSHandle<TaggedArray> propertyArray = JSObject::EnumerableOwnNames(thread_, obj);
|
||||
uint32_t arrLength = propertyArray->GetLength();
|
||||
for (uint32_t i = 0; i < arrLength; i++) {
|
||||
handleKey_.Update(propertyArray->Get(i));
|
||||
JSHandle<JSTaggedValue> proxyValue = JSProxy::GetProperty(thread_, proxy, handleKey_).GetValue();
|
||||
JSTaggedValue serializeValue = GetSerializeValue(value, handleKey_, proxyValue, replacer);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
|
||||
if (UNLIKELY(serializeValue.IsUndefined() || serializeValue.IsSymbol() ||
|
||||
(serializeValue.IsECMAObject() && serializeValue.IsCallable()))) {
|
||||
continue;
|
||||
}
|
||||
handleValue_.Update(serializeValue);
|
||||
SerializeObjectKey(handleKey_, hasContent);
|
||||
JSTaggedValue res = SerializeJSONProperty(handleValue_, replacer);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
|
||||
if (!res.IsUndefined()) {
|
||||
hasContent = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t numOfKeys = obj->GetNumberOfKeys();
|
||||
uint32_t numOfElements = obj->GetNumberOfElements();
|
||||
if (numOfElements > 0) {
|
||||
hasContent = JsonStringifier::SerializeElements(obj, replacer, hasContent);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
|
||||
}
|
||||
if (numOfKeys > 0) {
|
||||
hasContent = JsonStringifier::SerializeKeys(obj, replacer, hasContent);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t propLen = propList_.size();
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "ecmascript/base/builtins_base.h"
|
||||
#include "ecmascript/builtins/builtins_errors.h"
|
||||
#include "ecmascript/builtins/builtins_json.h"
|
||||
#include "ecmascript/builtins/builtins_proxy.h"
|
||||
#include "ecmascript/ecma_runtime_call_info.h"
|
||||
#include "ecmascript/ecma_string-inl.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
@ -461,4 +462,52 @@ HWTEST_F_L0(BuiltinsJsonTest, Stringify3)
|
||||
JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo.get());
|
||||
ASSERT_TRUE(EcmaString::StringsAreEqual(*test, EcmaString::Cast(result.GetTaggedObject())));
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> CreateJSObject(JSThread *thread)
|
||||
{
|
||||
EcmaVM *ecmaVM = thread->GetEcmaVM();
|
||||
JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> objFun = globalEnv->GetObjectFunction();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
||||
JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString("x"));
|
||||
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
||||
JSObject::SetProperty(thread, obj, key, value);
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> CreateProxy(JSThread *thread)
|
||||
{
|
||||
JSHandle<JSTaggedValue> target = CreateJSObject(thread);
|
||||
JSHandle<JSTaggedValue> handler = CreateJSObject(thread);
|
||||
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Null(), 8);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue());
|
||||
ecmaRuntimeCallInfo->SetCallArg(1, handler.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsProxy::ProxyConstructor(ecmaRuntimeCallInfo.get());
|
||||
return JSHandle<JSTaggedValue>(thread, result);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(BuiltinsJsonTest, Stringify4) // Test for proxy object
|
||||
{
|
||||
auto ecmaVM = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = ecmaVM->GetFactory();
|
||||
|
||||
JSHandle<JSTaggedValue> proxy = CreateProxy(thread);
|
||||
JSHandle<EcmaString> test = factory->NewFromStdString("{\"x\":1}");
|
||||
|
||||
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
|
||||
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
ecmaRuntimeCallInfo->SetCallArg(0, proxy.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
|
||||
JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo.get());
|
||||
ASSERT_TRUE(EcmaString::StringsAreEqual(*test, EcmaString::Cast(result.GetTaggedObject())));
|
||||
}
|
||||
} // namespace panda::test
|
||||
|
@ -1312,7 +1312,8 @@ JSHandle<TaggedArray> JSObject::EnumerableOwnNames(JSThread *thread, const JSHan
|
||||
JSTaggedValue key(keys->Get(i));
|
||||
if (key.IsString()) {
|
||||
PropertyDescriptor desc(thread);
|
||||
bool status = GetOwnProperty(thread, obj, JSHandle<JSTaggedValue>(thread, key), desc);
|
||||
bool status = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>(obj),
|
||||
JSHandle<JSTaggedValue>(thread, key), desc);
|
||||
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
|
||||
|
||||
if (status && desc.IsEnumerable()) {
|
||||
|
Loading…
Reference in New Issue
Block a user