Stringify support TypedArray

Support Stringify a TypedArray object

issue:https://gitee.com/openharmony/ark_js_runtime/issues/I53K0R

Signed-off-by: scw <suchongwei@huawei.com>
This commit is contained in:
scw 2022-04-19 19:36:06 +08:00
parent 355b2b8e80
commit e339c93829
4 changed files with 45 additions and 10 deletions

View File

@ -294,7 +294,7 @@ JSTaggedValue JsonStringifier::GetSerializeValue(const JSHandle<JSTaggedValue> &
thread_, FastRuntimeStub::FastGetPropertyByValue(thread_, tagValue, toJson.GetTaggedValue()));
// b. ReturnIfAbrupt(toJSON).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
tagValue = value.GetTaggedValue();
// c. If IsCallable(toJSON) is true
if (UNLIKELY(toJsonFun->IsCallable())) {
// Let value be Call(toJSON, value, «key»).
@ -455,14 +455,13 @@ bool JsonStringifier::SerializeJSONObject(const JSHandle<JSTaggedValue> &value,
JSHandle<JSObject> obj(value);
if (!replacer->IsArray(thread_)) {
if (UNLIKELY(value->IsJSProxy())) { // serialize proxy object
JSHandle<JSProxy> proxy(value);
if (UNLIKELY(value->IsJSProxy() || value->IsTypedArray())) { // serialize proxy and typedArray
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);
JSHandle<JSTaggedValue> valueHandle = JSTaggedValue::GetProperty(thread_, value, handleKey_).GetValue();
JSTaggedValue serializeValue = GetSerializeValue(value, handleKey_, valueHandle, replacer);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, false);
if (UNLIKELY(serializeValue.IsUndefined() || serializeValue.IsSymbol() ||
(serializeValue.IsECMAObject() && serializeValue.IsCallable()))) {

View File

@ -21,6 +21,7 @@
#include "ecmascript/builtins/builtins_errors.h"
#include "ecmascript/builtins/builtins_json.h"
#include "ecmascript/builtins/builtins_proxy.h"
#include "ecmascript/builtins/builtins_typedarray.h"
#include "ecmascript/ecma_runtime_call_info.h"
#include "ecmascript/ecma_string-inl.h"
#include "ecmascript/ecma_vm.h"
@ -510,4 +511,38 @@ HWTEST_F_L0(BuiltinsJsonTest, Stringify4) // Test for proxy object
JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo.get());
ASSERT_TRUE(EcmaString::StringsAreEqual(*test, EcmaString::Cast(result.GetTaggedObject())));
}
HWTEST_F_L0(BuiltinsJsonTest, Stringify5) // Test for proxy object
{
auto ecmaVM = thread->GetEcmaVM();
ObjectFactory *factory = ecmaVM->GetFactory();
[[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
array->Set(thread, 0, JSTaggedValue(2));
array->Set(thread, 1, JSTaggedValue(3));
array->Set(thread, 2, JSTaggedValue(4));
JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
JSHandle<JSFunction> int8Func(env->GetInt8ArrayFunction());
JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo1->SetNewTarget(JSTaggedValue(*int8Func));
ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
ecmaRuntimeCallInfo1->SetCallArg(0, jsArray.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get());
JSHandle<JSTaggedValue> int8Array(thread, BuiltinsTypedArray::Int8ArrayConstructor(ecmaRuntimeCallInfo1.get()));
JSHandle<EcmaString> test = factory->NewFromStdString("{\"0\":2,\"1\":3,\"2\":4}");
auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
ecmaRuntimeCallInfo->SetCallArg(0, int8Array.GetTaggedValue());
prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get());
JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo.get());
ASSERT_TRUE(result.IsString());
ASSERT_TRUE(EcmaString::StringsAreEqual(*test, EcmaString::Cast(result.GetTaggedObject())));
}
} // namespace panda::test

View File

@ -33,7 +33,7 @@ bool JSArray::LengthSetter(JSThread *thread, const JSHandle<JSObject> &self, con
{
uint32_t newLen = 0;
if (!JSTaggedValue::ToArrayLength(thread, value, &newLen) && mayThrow) {
THROW_RANGE_ERROR_AND_RETURN(thread, "array length must less than 2^32 - 1", false);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
}
if (!IsArrayLengthWritable(thread, self)) {

View File

@ -1306,16 +1306,17 @@ JSHandle<TaggedArray> JSObject::EnumerableOwnNames(JSThread *thread, const JSHan
uint32_t length = keys->GetLength();
JSHandle<TaggedArray> names = factory->NewTaggedArray(length);
JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
for (uint32_t i = 0; i < length; i++) {
JSTaggedValue key(keys->Get(i));
if (key.IsString()) {
keyHandle.Update(keys->Get(i));
if (keyHandle->IsString()) {
PropertyDescriptor desc(thread);
bool status = JSTaggedValue::GetOwnProperty(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, key), desc);
keyHandle, desc);
RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
if (status && desc.IsEnumerable()) {
names->Set(thread, copyLength, key);
names->Set(thread, copyLength, keyHandle);
copyLength++;
}
}