mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
Add Container Plainarray
Description To ensure the high performance of container classes, Plainarray is provided in ark. Related issue #I4XXYA:Add Container Plainarray Signed-off-by: zhangjixing <zhangjixing4@huawei.com>
This commit is contained in:
parent
ac88a6ad3f
commit
eafc261ff6
19
BUILD.gn
19
BUILD.gn
@ -339,6 +339,7 @@ ecma_source = [
|
||||
"ecmascript/builtins/builtins_weak_set.cpp",
|
||||
"ecmascript/containers/containers_arraylist.cpp",
|
||||
"ecmascript/containers/containers_deque.cpp",
|
||||
"ecmascript/containers/containers_plainarray.cpp",
|
||||
"ecmascript/containers/containers_private.cpp",
|
||||
"ecmascript/containers/containers_queue.cpp",
|
||||
"ecmascript/containers/containers_stack.cpp",
|
||||
@ -371,12 +372,6 @@ ecma_source = [
|
||||
"ecmascript/jobs/micro_job_queue.cpp",
|
||||
"ecmascript/jspandafile/js_pandafile.cpp",
|
||||
"ecmascript/jspandafile/js_pandafile_manager.cpp",
|
||||
"ecmascript/js_api_deque.cpp",
|
||||
"ecmascript/js_api_deque_iterator.cpp",
|
||||
"ecmascript/js_api_queue.cpp",
|
||||
"ecmascript/js_api_queue_iterator.cpp",
|
||||
"ecmascript/js_api_stack.cpp",
|
||||
"ecmascript/js_api_stack_iterator.cpp",
|
||||
"ecmascript/jspandafile/class_info_extractor.cpp",
|
||||
"ecmascript/jspandafile/debug_info_extractor.cpp",
|
||||
"ecmascript/jspandafile/ecma_class_linker_extension.cpp",
|
||||
@ -386,6 +381,16 @@ ecma_source = [
|
||||
"ecmascript/jspandafile/panda_file_translator.cpp",
|
||||
"ecmascript/jspandafile/js_pandafile_executor.cpp",
|
||||
"ecmascript/jspandafile/scope_info_extractor.cpp",
|
||||
"ecmascript/js_api_arraylist.cpp",
|
||||
"ecmascript/js_api_arraylist_iterator.cpp",
|
||||
"ecmascript/js_api_deque.cpp",
|
||||
"ecmascript/js_api_deque_iterator.cpp",
|
||||
"ecmascript/js_api_plain_array.cpp",
|
||||
"ecmascript/js_api_plain_array_iterator.cpp",
|
||||
"ecmascript/js_api_queue.cpp",
|
||||
"ecmascript/js_api_queue_iterator.cpp",
|
||||
"ecmascript/js_api_stack.cpp",
|
||||
"ecmascript/js_api_stack_iterator.cpp",
|
||||
"ecmascript/js_api_tree_map.cpp",
|
||||
"ecmascript/js_api_tree_map_iterator.cpp",
|
||||
"ecmascript/js_api_tree_set.cpp",
|
||||
@ -394,8 +399,6 @@ ecma_source = [
|
||||
"ecmascript/js_array.cpp",
|
||||
"ecmascript/js_array_iterator.cpp",
|
||||
"ecmascript/js_arraybuffer.cpp",
|
||||
"ecmascript/js_api_arraylist.cpp",
|
||||
"ecmascript/js_api_arraylist_iterator.cpp",
|
||||
"ecmascript/js_async_function.cpp",
|
||||
"ecmascript/js_bigint.cpp",
|
||||
"ecmascript/js_dataview.cpp",
|
||||
|
355
ecmascript/containers/containers_plainarray.cpp
Normal file
355
ecmascript/containers/containers_plainarray.cpp
Normal file
@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 "containers_plainarray.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_iterator.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
|
||||
namespace panda::ecmascript::containers {
|
||||
JSTaggedValue ContainersPlainArray::PlainArrayConstructor(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, Constructor);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
|
||||
if (newTarget->IsUndefined()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "new target can't be undefined", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
|
||||
JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
JSHandle<JSAPIPlainArray> plainArray = JSHandle<JSAPIPlainArray>::Cast(obj);
|
||||
JSHandle<TaggedArray> keys =
|
||||
JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
|
||||
JSHandle<TaggedArray> values =
|
||||
JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
|
||||
plainArray->SetKeys(thread, keys);
|
||||
plainArray->SetValues(thread, values);
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::Add(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, Add);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
|
||||
if (!key->IsNumber()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception());
|
||||
}
|
||||
JSAPIPlainArray::Add(thread, JSHandle<JSAPIPlainArray>::Cast(self), key, value);
|
||||
return JSTaggedValue::True();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::Clear(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, Clear);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
array->Clear(thread);
|
||||
return JSTaggedValue::True();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::Clone(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, Clone);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSAPIPlainArray> newPlainArray =
|
||||
JSAPIPlainArray::Clone(thread, JSHandle<JSAPIPlainArray>::Cast(self));
|
||||
return newPlainArray.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::Has(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, Has);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
|
||||
if (!value->IsNumber()) {
|
||||
return JSTaggedValue::False();
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
int32_t key = value->GetNumber();
|
||||
bool result = array->Has(key);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::Get(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, Get);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
|
||||
if (!key->IsNumber()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the key is not integer", JSTaggedValue::Exception());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
JSTaggedValue value = array->Get(key.GetTaggedValue());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::GetIteratorObj(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, GetIteratorObj);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> iter =
|
||||
JSAPIPlainArray::GetIteratorObj(thread, JSHandle<JSAPIPlainArray>::Cast(self), IterationKind::KEY_AND_VALUE);
|
||||
return iter.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::ForEach(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, ForEach);
|
||||
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
|
||||
JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
|
||||
if (!callbackFnHandle->IsCallable()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
|
||||
return JSAPIPlainArray::ForEach(thread, thisHandle, callbackFnHandle, thisArgHandle);
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::ToString(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, ToString);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSTaggedValue value = JSAPIPlainArray::ToString(thread, JSHandle<JSAPIPlainArray>::Cast(self));
|
||||
return value;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::GetIndexOfKey(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, GetIndexOfKey);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
|
||||
if (!value->IsNumber()) {
|
||||
return JSTaggedValue(-1);
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
int32_t key = value->GetNumber();
|
||||
JSTaggedValue result = array->GetIndexOfKey(key);
|
||||
return result;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::GetIndexOfValue(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, GetIndexOfValue);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
|
||||
JSTaggedValue jsValue = array->GetIndexOfValue(value.GetTaggedValue());
|
||||
return jsValue;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::IsEmpty(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, IsEmpty);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
bool ret = array->IsEmpty();
|
||||
return JSTaggedValue(ret);
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::GetKeyAt(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, GetKeyAt);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
|
||||
if (!value->IsNumber()) {
|
||||
return JSTaggedValue(-1);
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
int32_t index = value->GetNumber();
|
||||
JSTaggedValue result = array->GetKeyAt(index);
|
||||
return result;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::Remove(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, Remove);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
|
||||
if (!key->IsNumber()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the key is not integer", JSTaggedValue::Undefined());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
JSTaggedValue value = array->Remove(thread, key.GetTaggedValue());
|
||||
return value;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::RemoveAt(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, RemoveAt);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
|
||||
if (!index->IsNumber()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Undefined());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
JSTaggedValue value = array->RemoveAt(thread, index.GetTaggedValue());
|
||||
return value;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::RemoveRangeFrom(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, RemoveRangeFrom);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> valueIndex(GetCallArg(argv, 0));
|
||||
JSHandle<JSTaggedValue> valueSize(GetCallArg(argv, 1));
|
||||
if (!valueIndex->IsNumber() || !valueSize->IsNumber()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the index or the value is not integer", JSTaggedValue::Undefined());
|
||||
}
|
||||
int32_t index = valueIndex->GetNumber();
|
||||
int32_t size = valueSize->GetNumber();
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
JSTaggedValue value = array->RemoveRangeFrom(thread, index, size);
|
||||
return value;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::SetValueAt(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, SetValueAt);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
|
||||
if (!index->IsNumber()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
array->SetValueAt(thread, index.GetTaggedValue(), value.GetTaggedValue());
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::GetValueAt(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, GetValueAt);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSTaggedValue> idx(GetCallArg(argv, 0));
|
||||
if (!idx->IsNumber()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Undefined());
|
||||
}
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
|
||||
int32_t index = idx->GetNumber();
|
||||
JSTaggedValue value = array->GetValueAt(index);
|
||||
return value;
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersPlainArray::GetSize(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv != nullptr);
|
||||
JSThread *thread = argv->GetThread();
|
||||
BUILTINS_API_TRACE(thread, PlainArray, GetSize);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
if (!self->IsJSAPIPlainArray()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception());
|
||||
}
|
||||
uint32_t length = JSHandle<JSAPIPlainArray>::Cast(self)->GetSize();
|
||||
return JSTaggedValue(length);
|
||||
}
|
||||
} // namespace panda::ecmascript::containers
|
46
ecmascript/containers/containers_plainarray.h
Normal file
46
ecmascript/containers/containers_plainarray.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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_CONTAINERS_CONTAINERS_PLAIN_ARRAY_H
|
||||
#define ECMASCRIPT_CONTAINERS_CONTAINERS_PLAIN_ARRAY_H
|
||||
|
||||
#include "ecmascript/base/builtins_base.h"
|
||||
#include "ecmascript/ecma_runtime_call_info.h"
|
||||
|
||||
namespace panda::ecmascript::containers {
|
||||
class ContainersPlainArray : public base::BuiltinsBase {
|
||||
public:
|
||||
static JSTaggedValue PlainArrayConstructor(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue Add(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue Clear(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue Clone(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue Has(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue Get(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue GetIteratorObj(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue ForEach(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue GetIndexOfKey(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue GetIndexOfValue(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue IsEmpty(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue GetKeyAt(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue Remove(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue RemoveAt(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue RemoveRangeFrom(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue SetValueAt(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue GetValueAt(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue GetSize(EcmaRuntimeCallInfo *argv);
|
||||
};
|
||||
} // namespace panda::ecmascript::containers
|
||||
#endif // ECMASCRIPT_CONTAINERS_CONTAINERS_PLAIN_ARRAY_H
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "containers_arraylist.h"
|
||||
#include "containers_deque.h"
|
||||
#include "containers_plainarray.h"
|
||||
#include "containers_queue.h"
|
||||
#include "containers_stack.h"
|
||||
#include "containers_treemap.h"
|
||||
@ -26,6 +27,8 @@
|
||||
#include "ecmascript/interpreter/fast_runtime_stub-inl.h"
|
||||
#include "ecmascript/js_api_deque.h"
|
||||
#include "ecmascript/js_api_deque_iterator.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_api_queue.h"
|
||||
#include "ecmascript/js_api_queue_iterator.h"
|
||||
#include "ecmascript/js_api_stack.h"
|
||||
@ -41,7 +44,7 @@
|
||||
namespace panda::ecmascript::containers {
|
||||
JSTaggedValue ContainersPrivate::Load(EcmaRuntimeCallInfo *msg)
|
||||
{
|
||||
ASSERT(msg);
|
||||
ASSERT(msg != nullptr);
|
||||
JSThread *thread = msg->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> argv = GetCallArg(msg, 0);
|
||||
@ -78,6 +81,10 @@ JSTaggedValue ContainersPrivate::Load(EcmaRuntimeCallInfo *msg)
|
||||
res = InitializeContainer(thread, thisValue, InitializeDeque, "DequeConstructor");
|
||||
break;
|
||||
}
|
||||
case ContainerTag::PlainArray: {
|
||||
res = InitializeContainer(thread, thisValue, InitializePlainArray, "PlainArrayConstructor");
|
||||
break;
|
||||
}
|
||||
case ContainerTag::Vector:
|
||||
case ContainerTag::List:
|
||||
case ContainerTag::LinkedList:
|
||||
@ -85,7 +92,6 @@ JSTaggedValue ContainersPrivate::Load(EcmaRuntimeCallInfo *msg)
|
||||
case ContainerTag::HashSet:
|
||||
case ContainerTag::LightWeightMap:
|
||||
case ContainerTag::LightWeightSet:
|
||||
case ContainerTag::PlainArray:
|
||||
case ContainerTag::END:
|
||||
break;
|
||||
default:
|
||||
@ -198,7 +204,6 @@ void ContainersPrivate::SetFunctionAtSymbol(JSThread *thread, const JSHandle<Glo
|
||||
JSHandle<JSTaggedValue> nameString(factory->NewFromASCII(name));
|
||||
JSHandle<JSFunctionBase> baseFunction(function);
|
||||
JSFunction::SetFunctionName(thread, baseFunction, nameString, thread->GlobalConstants()->GetHandledUndefined());
|
||||
|
||||
PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(function), false, false, false);
|
||||
JSObject::DefineOwnProperty(thread, obj, symbol, descriptor);
|
||||
}
|
||||
@ -433,6 +438,79 @@ void ContainersPrivate::InitializeTreeSetIterator(JSThread *thread)
|
||||
globalConst->SetConstant(ConstantIndex::TREESET_ITERATOR_PROTOTYPE_INDEX, setIteratorPrototype.GetTaggedValue());
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> ContainersPrivate::InitializePlainArray(JSThread *thread)
|
||||
{
|
||||
auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// PlainArray.prototype
|
||||
JSHandle<JSObject> plainArrayFuncPrototype = factory->NewEmptyJSObject();
|
||||
JSHandle<JSTaggedValue> plainArrayFuncPrototypeValue(plainArrayFuncPrototype);
|
||||
// PlainArray.prototype_or_dynclass
|
||||
JSHandle<JSHClass> plainArrayInstanceDynclass =
|
||||
factory->NewEcmaDynClass(JSAPIPlainArray::SIZE, JSType::JS_API_PLAIN_ARRAY, plainArrayFuncPrototypeValue);
|
||||
JSHandle<JSTaggedValue> plainArrayFunction(
|
||||
NewContainerConstructor(thread, plainArrayFuncPrototype, ContainersPlainArray::PlainArrayConstructor,
|
||||
"PlainArray", FuncLength::ZERO));
|
||||
JSHandle<JSFunction>(plainArrayFunction)->SetFunctionPrototype(thread,
|
||||
plainArrayInstanceDynclass.GetTaggedValue());
|
||||
// "constructor" property on the prototype
|
||||
JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(plainArrayFuncPrototype), constructorKey,
|
||||
plainArrayFunction);
|
||||
// PlainArray.prototype.add()
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "add", ContainersPlainArray::Add, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "clear", ContainersPlainArray::Clear, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "clone", ContainersPlainArray::Clone, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "has", ContainersPlainArray::Has, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "get", ContainersPlainArray::Get, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "forEach", ContainersPlainArray::ForEach, FuncLength::ONE);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "toString", ContainersPlainArray::ToString,
|
||||
FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "getIndexOfKey", ContainersPlainArray::GetIndexOfKey,
|
||||
FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "getIndexOfValue", ContainersPlainArray::GetIndexOfValue,
|
||||
FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "isEmpty", ContainersPlainArray::IsEmpty, FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "getKeyAt",
|
||||
ContainersPlainArray::GetKeyAt, FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "remove", ContainersPlainArray::Remove, FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "removeAt", ContainersPlainArray::RemoveAt,
|
||||
FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "removeRangeFrom", ContainersPlainArray::RemoveRangeFrom,
|
||||
FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "setValueAt", ContainersPlainArray::SetValueAt,
|
||||
FuncLength::ZERO);
|
||||
SetFrozenFunction(thread, plainArrayFuncPrototype, "getValueAt", ContainersPlainArray::GetValueAt,
|
||||
FuncLength::ZERO);
|
||||
|
||||
JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersPlainArray::GetSize, "length",
|
||||
FuncLength::ZERO);
|
||||
JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
|
||||
SetGetter(thread, plainArrayFuncPrototype, lengthKey, lengthGetter);
|
||||
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
SetFunctionAtSymbol(thread, env, plainArrayFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
|
||||
ContainersPlainArray::GetIteratorObj, FuncLength::ONE);
|
||||
InitializePlainArrayIterator(thread);
|
||||
globalConst->SetConstant(ConstantIndex::PLAIN_ARRAY_FUNCTION_INDEX, plainArrayFunction.GetTaggedValue());
|
||||
return plainArrayFunction;
|
||||
}
|
||||
|
||||
void ContainersPrivate::InitializePlainArrayIterator(JSThread *thread)
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
|
||||
JSHandle<JSHClass> iteratorDynclass = JSHandle<JSHClass>(thread, globalConst->
|
||||
GetHandledJSAPIIteratorFuncDynClass().
|
||||
GetObject<JSHClass>());
|
||||
JSHandle<JSObject> plainarrayIteratorPrototype(factory->NewJSObject(iteratorDynclass));
|
||||
SetFrozenFunction(thread, plainarrayIteratorPrototype, "next", JSAPIPlainArrayIterator::Next, FuncLength::ONE);
|
||||
SetStringTagSymbol(thread, env, plainarrayIteratorPrototype, "PlainArray Iterator");
|
||||
globalConst->SetConstant(ConstantIndex::PLAIN_ARRAY_ITERATOR_PROTOTYPE_INDEX,
|
||||
plainarrayIteratorPrototype.GetTaggedValue());
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> ContainersPrivate::InitializeStack(JSThread *thread)
|
||||
{
|
||||
auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
|
||||
|
@ -74,6 +74,8 @@ private:
|
||||
static void InitializeTreeMapIterator(JSThread *thread);
|
||||
static JSHandle<JSTaggedValue> InitializeTreeSet(JSThread *thread);
|
||||
static void InitializeTreeSetIterator(JSThread *thread);
|
||||
static JSHandle<JSTaggedValue> InitializePlainArray(JSThread *thread);
|
||||
static void InitializePlainArrayIterator(JSThread *thread);
|
||||
static JSHandle<JSTaggedValue> InitializeQueue(JSThread *thread);
|
||||
static void InitializeQueueIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
|
||||
GlobalEnvConstants *globalConst);
|
||||
|
@ -59,6 +59,32 @@ host_unittest_action("ContainersTreeSetTest") {
|
||||
}
|
||||
}
|
||||
|
||||
host_unittest_action("ContainersPlainArrayTest") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
sources = [
|
||||
# test file
|
||||
"containers_plainarray_test.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
"//ark/js_runtime:ecma_test_config",
|
||||
"//ark/js_runtime:ark_jsruntime_public_config", # should add before
|
||||
# arkruntime_public_config
|
||||
"//ark/js_runtime:ark_jsruntime_common_config",
|
||||
"$ark_root/runtime:arkruntime_public_config",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"$ark_root/libpandabase:libarkbase",
|
||||
"//ark/js_runtime:libark_jsruntime_test",
|
||||
sdk_libc_secshared_dep,
|
||||
]
|
||||
|
||||
if (!is_standard_system) {
|
||||
deps += [ "$ark_root/runtime:libarkruntime" ]
|
||||
}
|
||||
}
|
||||
host_unittest_action("ContainersStackTest") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
@ -119,6 +145,7 @@ group("unittest") {
|
||||
# deps file
|
||||
deps = [
|
||||
":ContainersDequeTest",
|
||||
":ContainersPlainArrayTest",
|
||||
":ContainersStackTest",
|
||||
":ContainersTreeMapTest",
|
||||
":ContainersTreeSetTest",
|
||||
@ -131,6 +158,7 @@ group("host_unittest") {
|
||||
# deps file
|
||||
deps = [
|
||||
":ContainersDequeTestAction",
|
||||
":ContainersPlainArrayTestAction",
|
||||
":ContainersStackTestAction",
|
||||
":ContainersTreeMapTestAction",
|
||||
":ContainersTreeSetTestAction",
|
||||
|
376
ecmascript/containers/tests/containers_plainarray_test.cpp
Normal file
376
ecmascript/containers/tests/containers_plainarray_test.cpp
Normal file
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/js_api_plain_array.h"
|
||||
#include "ecmascript/containers/containers_private.h"
|
||||
#include "ecmascript/containers/containers_plainarray.h"
|
||||
#include "ecmascript/ecma_runtime_call_info.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::ecmascript::containers;
|
||||
|
||||
namespace panda::test {
|
||||
class ContainersPlainArrayTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
||||
}
|
||||
|
||||
PandaVM *instance {nullptr};
|
||||
EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
|
||||
class TestClass : public base::BuiltinsBase {
|
||||
public:
|
||||
static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
JSThread *thread = argv->GetThread();
|
||||
JSHandle<JSTaggedValue> key = GetCallArg(argv, 0); // 0 means the value
|
||||
JSHandle<JSTaggedValue> value = GetCallArg(argv, 1); // 1 means the value
|
||||
JSHandle<JSAPIPlainArray> plainArray(GetCallArg(argv, 2)); // 2 means the value
|
||||
if (key->IsNumber()) {
|
||||
JSHandle<JSTaggedValue> newValue(thread, JSTaggedValue(value->GetInt() * 2)); // 2 means the value
|
||||
JSAPIPlainArray::Add(thread, plainArray, key, newValue);
|
||||
}
|
||||
|
||||
return JSTaggedValue::True();
|
||||
}
|
||||
};
|
||||
protected:
|
||||
JSTaggedValue InitializePlainArrayConstructor()
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
|
||||
JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
|
||||
JSHandle<JSTaggedValue> value =
|
||||
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
|
||||
|
||||
auto objCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
|
||||
objCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
objCallInfo->SetThis(value.GetTaggedValue());
|
||||
objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::PlainArray)));
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get());
|
||||
JSTaggedValue result = ContainersPrivate::Load(objCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
JSHandle<JSAPIPlainArray> CreateJSAPIPlainArray()
|
||||
{
|
||||
JSHandle<JSFunction> newTarget(thread, InitializePlainArrayConstructor());
|
||||
auto objCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); // 4 means the value
|
||||
objCallInfo->SetFunction(newTarget.GetTaggedValue());
|
||||
objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
|
||||
objCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::PlainArrayConstructor(objCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
JSHandle<JSAPIPlainArray> plain(thread, result);
|
||||
return plain;
|
||||
}
|
||||
};
|
||||
|
||||
HWTEST_F_L0(ContainersPlainArrayTest, PlainArrayConstructor)
|
||||
{
|
||||
InitializePlainArrayConstructor();
|
||||
JSHandle<JSFunction> newTarget(thread, InitializePlainArrayConstructor());
|
||||
auto objCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); // 4 means the value
|
||||
objCallInfo->SetFunction(newTarget.GetTaggedValue());
|
||||
objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
|
||||
objCallInfo->SetThis(JSTaggedValue::Undefined());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::PlainArrayConstructor(objCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
|
||||
ASSERT_TRUE(result.IsJSAPIPlainArray());
|
||||
JSHandle<JSAPIPlainArray> arrayHandle(thread, result);
|
||||
JSTaggedValue resultProto = JSObject::GetPrototype(JSHandle<JSObject>::Cast(arrayHandle));
|
||||
JSTaggedValue funcProto = newTarget->GetFunctionPrototype();
|
||||
ASSERT_EQ(resultProto, funcProto);
|
||||
int size = arrayHandle->GetSize();
|
||||
ASSERT_EQ(size, 0);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(ContainersPlainArrayTest, AddAndHas)
|
||||
{
|
||||
constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
|
||||
|
||||
JSHandle<JSAPIPlainArray> tArray1 = CreateJSAPIPlainArray();
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(tArray1.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(i));
|
||||
callInfo->SetCallArg(1, JSTaggedValue(i + 1));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Add(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(result.IsTrue());
|
||||
EXPECT_EQ(tArray1->GetSize(), static_cast<int>(i + 1));
|
||||
}
|
||||
EXPECT_EQ(tArray1->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
// test has
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(tArray1.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(i));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Has(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(result.IsTrue());
|
||||
}
|
||||
EXPECT_EQ(tArray1->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
// test add string
|
||||
JSHandle<JSAPIPlainArray> tArray = CreateJSAPIPlainArray();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
||||
std::string myValue("myvalue");
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
std::string ivalue = myValue + std::to_string(i);
|
||||
key.Update(JSTaggedValue(i));
|
||||
value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
|
||||
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(tArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, key.GetTaggedValue());
|
||||
callInfo->SetCallArg(1, value.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Add(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(result.IsTrue());
|
||||
}
|
||||
EXPECT_EQ(tArray->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
// test get
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
std::string ivalue = myValue + std::to_string(i);
|
||||
key.Update(JSTaggedValue(i));
|
||||
value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
|
||||
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(tArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, key.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Get(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result), value));
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F_L0(ContainersPlainArrayTest, Iterator)
|
||||
{
|
||||
constexpr uint32_t NODE_NUMBERS = 8;
|
||||
JSHandle<JSAPIPlainArray> array = CreateJSAPIPlainArray();
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(array.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(i));
|
||||
callInfo->SetCallArg(1, JSTaggedValue(i + 1));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Add(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(result.IsTrue());
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(i + 1));
|
||||
}
|
||||
// test iterator
|
||||
{
|
||||
auto callInf = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
|
||||
callInf->SetFunction(JSTaggedValue::Undefined());
|
||||
callInf->SetThis(array.GetTaggedValue());
|
||||
[[maybe_unused]] auto pre = TestHelper::SetupFrame(thread, callInf.get());
|
||||
JSHandle<JSTaggedValue> iter(thread, ContainersPlainArray::GetIteratorObj(callInf.get()));
|
||||
TestHelper::TearDownFrame(thread, pre);
|
||||
EXPECT_TRUE(iter->IsJSAPIPlainArrayIterator());
|
||||
|
||||
JSHandle<JSTaggedValue> first(thread, JSTaggedValue(0));
|
||||
JSHandle<JSTaggedValue> second(thread, JSTaggedValue(1));
|
||||
JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> entries(thread, JSTaggedValue::Undefined());
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(iter.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
result.Update(JSAPIPlainArrayIterator::Next(callInfo.get()));
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
entries.Update(JSIterator::IteratorValue(thread, result).GetTaggedValue());
|
||||
EXPECT_EQ(static_cast<int>(i), JSObject::GetProperty(thread, entries, first).GetValue()->GetInt());
|
||||
EXPECT_EQ(static_cast<int>(i + 1), JSObject::GetProperty(thread, entries, second).GetValue()->GetInt());
|
||||
}
|
||||
}
|
||||
// test add string
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
||||
std::string myValue("myvalue");
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
std::string iValue = myValue + std::to_string(i);
|
||||
value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(array.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(100 + i));
|
||||
callInfo->SetCallArg(1, value.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Add(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(result.IsTrue());
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS + i + 1));
|
||||
}
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS * 2));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(ContainersPlainArrayTest, GetIndexOfKeyAndGetIndexOfValue)
|
||||
{
|
||||
constexpr uint32_t NODE_NUMBERS = 8;
|
||||
JSHandle<JSAPIPlainArray> pArray = CreateJSAPIPlainArray();
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 4 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(pArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(i));
|
||||
callInfo->SetCallArg(1, JSTaggedValue(i + 1));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Add(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(result.IsTrue());
|
||||
EXPECT_EQ(pArray->GetSize(), static_cast<int>(i + 1));
|
||||
}
|
||||
// test GetIndexOfKey
|
||||
{
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(pArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(2));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::GetIndexOfKey(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_EQ(result, JSTaggedValue(2));
|
||||
}
|
||||
// test GetIndexOfValue
|
||||
{
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(pArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(4));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::GetIndexOfValue(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_EQ(result, JSTaggedValue(3));
|
||||
}
|
||||
// test add string
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
||||
std::string myValue("myvalue");
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
std::string iValue = myValue + std::to_string(i);
|
||||
value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(pArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(100 + i));
|
||||
callInfo->SetCallArg(1, value.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::Add(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_TRUE(result.IsTrue());
|
||||
EXPECT_EQ(pArray->GetSize(), static_cast<int>(NODE_NUMBERS + i + 1));
|
||||
}
|
||||
EXPECT_EQ(pArray->GetSize(), static_cast<int>(NODE_NUMBERS * 2));
|
||||
// test GetIndexOfKey
|
||||
{
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(pArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, JSTaggedValue(102));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::GetIndexOfKey(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_EQ(result, JSTaggedValue(10));
|
||||
}
|
||||
// test GetIndexOfValue
|
||||
{
|
||||
std::string tValue("myvalue3");
|
||||
value.Update(factory->NewFromStdString(tValue).GetTaggedValue());
|
||||
auto callInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
|
||||
callInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
callInfo->SetThis(pArray.GetTaggedValue());
|
||||
callInfo->SetCallArg(0, value.GetTaggedValue());
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get());
|
||||
JSTaggedValue result = ContainersPlainArray::GetIndexOfValue(callInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
EXPECT_EQ(result, JSTaggedValue(11));
|
||||
}
|
||||
}
|
||||
}
|
@ -364,6 +364,10 @@ CString *HeapSnapShot::GenerateNodeName(TaggedObject *entry)
|
||||
return GetString("ResolvedBinding");
|
||||
case JSType::JS_MODULE_NAMESPACE:
|
||||
return GetString("ModuleNamespace");
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
return GetString("PlainArray");
|
||||
case JSType::JS_API_PLAIN_ARRAY_ITERATOR:
|
||||
return GetString("PlainArrayIterator");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -28,14 +28,18 @@
|
||||
#include "ecmascript/interpreter/frame_handler.h"
|
||||
#include "ecmascript/jobs/micro_job_queue.h"
|
||||
#include "ecmascript/jobs/pending_job.h"
|
||||
#include "ecmascript/jspandafile/class_info_extractor.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/js_api_arraylist.h"
|
||||
#include "ecmascript/js_api_arraylist_iterator.h"
|
||||
#include "ecmascript/js_api_deque.h"
|
||||
#include "ecmascript/js_api_deque_iterator.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_api_queue.h"
|
||||
#include "ecmascript/js_api_queue_iterator.h"
|
||||
#include "ecmascript/js_api_stack.h"
|
||||
#include "ecmascript/js_api_stack_iterator.h"
|
||||
#include "ecmascript/jspandafile/class_info_extractor.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/js_api_tree_map.h"
|
||||
#include "ecmascript/js_api_tree_map_iterator.h"
|
||||
#include "ecmascript/js_api_tree_set.h"
|
||||
@ -43,8 +47,6 @@
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_api_arraylist.h"
|
||||
#include "ecmascript/js_api_arraylist_iterator.h"
|
||||
#include "ecmascript/js_async_function.h"
|
||||
#include "ecmascript/js_bigint.h"
|
||||
#include "ecmascript/js_collator.h"
|
||||
@ -307,6 +309,10 @@ CString JSHClass::DumpJSType(JSType type)
|
||||
return "Queue";
|
||||
case JSType::JS_API_QUEUE_ITERATOR:
|
||||
return "QueueIterator";
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
return "PlainArray";
|
||||
case JSType::JS_API_PLAIN_ARRAY_ITERATOR:
|
||||
return "PlainArrayIterator";
|
||||
case JSType::JS_API_DEQUE:
|
||||
return "Deque";
|
||||
case JSType::JS_API_DEQUE_ITERATOR:
|
||||
@ -732,6 +738,12 @@ static void DumpObject(TaggedObject *obj, std::ostream &os)
|
||||
case JSType::JS_MODULE_NAMESPACE:
|
||||
ModuleNamespace::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
JSAPIPlainArray::Cast(obj)->Dump(os);
|
||||
break;
|
||||
case JSType::JS_API_PLAIN_ARRAY_ITERATOR:
|
||||
JSAPIPlainArrayIterator::Cast(obj)->Dump(os);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
@ -1332,6 +1344,44 @@ void TaggedTreeSet::Dump(std::ostream &os) const
|
||||
}
|
||||
}
|
||||
|
||||
void JSAPIPlainArray::Dump(std::ostream &os) const
|
||||
{
|
||||
TaggedArray *keys = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
uint32_t len = GetLength();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
os << " - keys: ";
|
||||
keys->Get(i).DumpTaggedValue(os);
|
||||
os << "\n";
|
||||
os << " - values: ";
|
||||
values->Get(i).DumpTaggedValue(os);
|
||||
os << "\n";
|
||||
}
|
||||
os << " - length: " << std::dec << len << "\n";
|
||||
JSObject::Dump(os);
|
||||
}
|
||||
|
||||
void JSAPIPlainArray::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &vec) const
|
||||
{
|
||||
JSObject::DumpForSnapshot(vec);
|
||||
}
|
||||
|
||||
void JSAPIPlainArrayIterator::Dump(std::ostream &os) const
|
||||
{
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(GetIteratedPlainArray().GetTaggedObject());
|
||||
os << " - length: " << std::dec << array->GetSize() << "\n";
|
||||
os << " - nextIndex: " << std::dec << GetNextIndex() << "\n";
|
||||
JSObject::Dump(os);
|
||||
}
|
||||
|
||||
void JSAPIPlainArrayIterator::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &vec) const
|
||||
{
|
||||
JSAPIPlainArray *array = JSAPIPlainArray::Cast(GetIteratedPlainArray().GetTaggedObject());
|
||||
array->DumpForSnapshot(vec);
|
||||
vec.push_back(std::make_pair(CString("NextIndex"), JSTaggedValue(GetNextIndex())));
|
||||
JSObject::DumpForSnapshot(vec);
|
||||
}
|
||||
|
||||
void JSForInIterator::Dump(std::ostream &os) const
|
||||
{
|
||||
os << " - Object : ";
|
||||
@ -2905,6 +2955,12 @@ static void DumpObject(TaggedObject *obj,
|
||||
case JSType::JS_MODULE_NAMESPACE:
|
||||
ModuleNamespace::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
JSAPIPlainArray::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
case JSType::JS_API_PLAIN_ARRAY_ITERATOR:
|
||||
JSAPIPlainArrayIterator::Cast(obj)->DumpForSnapshot(vec);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3515,6 +3571,8 @@ void GlobalEnv::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &
|
||||
vec.push_back(std::make_pair(CString("TreeMapIteratorPrototype"), globalConst->GetTreeMapIteratorPrototype()));
|
||||
vec.push_back(std::make_pair(CString("TreeSetIteratorPrototype"), globalConst->GetTreeSetIteratorPrototype()));
|
||||
vec.push_back(std::make_pair(CString("QueueIteratorPrototype"), globalConst->GetQueueIteratorPrototype()));
|
||||
vec.push_back(
|
||||
std::make_pair(CString("PlainArrayIteratorPrototype"), globalConst->GetPlainArrayIteratorPrototype()));
|
||||
vec.push_back(std::make_pair(CString("DequeIteratorPrototype"), globalConst->GetDequeIteratorPrototype()));
|
||||
vec.push_back(std::make_pair(CString("StackIteratorPrototype"), globalConst->GetStackIteratorPrototype()));
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "ecmascript/jobs/pending_job.h"
|
||||
#include "ecmascript/js_api_arraylist_iterator.h"
|
||||
#include "ecmascript/js_api_deque_iterator.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_api_queue_iterator.h"
|
||||
#include "ecmascript/js_api_stack_iterator.h"
|
||||
#include "ecmascript/js_api_tree_map_iterator.h"
|
||||
@ -184,6 +185,9 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl
|
||||
factory->NewEcmaDynClass(dynClassClass, JSAPIArrayListIterator::SIZE, JSType::JS_API_ARRAYLIST_ITERATOR));
|
||||
SetConstant(ConstantIndex::JS_API_DEQUE_ITERATOR_CLASS_INDEX,
|
||||
factory->NewEcmaDynClass(dynClassClass, JSAPIDequeIterator::SIZE, JSType::JS_API_DEQUE_ITERATOR));
|
||||
SetConstant(
|
||||
ConstantIndex::JS_API_PLAIN_ARRAY_ITERATOR_CLASS_INDEX,
|
||||
factory->NewEcmaDynClass(dynClassClass, JSAPIPlainArrayIterator::SIZE, JSType::JS_API_PLAIN_ARRAY_ITERATOR));
|
||||
SetConstant(ConstantIndex::JS_API_QUEUE_ITERATOR_CLASS_INDEX,
|
||||
factory->NewEcmaDynClass(dynClassClass, JSAPIQueueIterator::SIZE, JSType::JS_API_QUEUE_ITERATOR));
|
||||
SetConstant(ConstantIndex::JS_API_STACK_ITERATOR_CLASS_INDEX,
|
||||
|
@ -84,6 +84,7 @@ class JSThread;
|
||||
V(JSTaggedValue, JSArrayIteratorClass, JS_ARRAY_ITERATOR_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, JSAPIArrayListIteratorClass, JS_API_ARRAYLIST_ITERATOR_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, JSAPIDequeIteratorClass, JS_API_DEQUE_ITERATOR_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, JSAPIPlainArrayIteratorClass, JS_API_PLAIN_ARRAY_ITERATOR_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, JSAPIQueueIteratorClass, JS_API_QUEUE_ITERATOR_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, JSAPIStackIteratorClass, JS_API_STACK_ITERATOR_CLASS_INDEX, ecma_roots_class) \
|
||||
V(JSTaggedValue, JSAPITreeMapIteratorClass, JS_API_TREE_MAP_ITERATOR_CLASS_INDEX, ecma_roots_class) \
|
||||
@ -116,6 +117,8 @@ class JSThread;
|
||||
V(JSTaggedValue, TreeMapIteratorPrototype, TREEMAP_ITERATOR_PROTOTYPE_INDEX, TreeMapIterator) \
|
||||
V(JSTaggedValue, TreeSetIteratorPrototype, TREESET_ITERATOR_PROTOTYPE_INDEX, TreeSetIterator) \
|
||||
V(JSTaggedValue, QueueIteratorPrototype, QUEUE_ITERATOR_PROTOTYPE_INDEX, QueueIterator) \
|
||||
V(JSTaggedValue, PlainArrayIteratorPrototype, PLAIN_ARRAY_ITERATOR_PROTOTYPE_INDEX, PlainArrayIterator) \
|
||||
V(JSTaggedValue, PlainArrayFunction, PLAIN_ARRAY_FUNCTION_INDEX, PlainArrayFunction) \
|
||||
V(JSTaggedValue, DequeIteratorPrototype, DEQUE_ITERATOR_PROTOTYPE_INDEX, DequeIterator) \
|
||||
V(JSTaggedValue, StackIteratorPrototype, STACK_ITERATOR_PROTOTYPE_INDEX, StackIterator) \
|
||||
/* SymbolTable*RegisterSymbols */ \
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ecmascript/interpreter/interpreter.h"
|
||||
#include "ecmascript/js_api_arraylist.h"
|
||||
#include "ecmascript/js_api_deque.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_api_queue.h"
|
||||
#include "ecmascript/js_api_stack.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
@ -1366,6 +1367,9 @@ JSTaggedValue FastRuntimeStub::GetContainerProperty(JSThread *thread, JSTaggedVa
|
||||
case JSType::JS_API_QUEUE:
|
||||
res = JSAPIQueue::Cast(receiver.GetTaggedObject())->Get(thread, index);
|
||||
break;
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
res = JSAPIPlainArray::Cast(receiver.GetTaggedObject())->Get(JSTaggedValue(index));
|
||||
break;
|
||||
case JSType::JS_API_DEQUE:
|
||||
res = JSAPIDeque::Cast(receiver.GetTaggedObject())->Get(index);
|
||||
break;
|
||||
@ -1389,6 +1393,9 @@ JSTaggedValue FastRuntimeStub::SetContainerProperty(JSThread *thread, JSTaggedVa
|
||||
case JSType::JS_API_QUEUE:
|
||||
res = JSAPIQueue::Cast(receiver.GetTaggedObject())->Set(thread, index, value);
|
||||
break;
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
res = JSAPIPlainArray::Set(thread, JSHandle<JSAPIPlainArray> (thread, receiver), index, value);
|
||||
break;
|
||||
case JSType::JS_API_DEQUE:
|
||||
res = JSAPIDeque::Cast(receiver.GetTaggedObject())->Set(thread, index, value);
|
||||
break;
|
||||
|
394
ecmascript/js_api_plain_array.cpp
Normal file
394
ecmascript/js_api_plain_array.cpp
Normal file
@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 "js_api_plain_array.h"
|
||||
#include "js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/interpreter/interpreter.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void JSAPIPlainArray::Add(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value)
|
||||
{
|
||||
JSHandle<TaggedArray> keyArray(thread, obj->GetKeys());
|
||||
JSHandle<TaggedArray> valueArray(thread, obj->GetValues());
|
||||
int32_t size = obj->GetLength();
|
||||
int32_t index = obj->BinarySearch(*keyArray, 0, size, key.GetTaggedValue().GetNumber());
|
||||
if (index >= 0) {
|
||||
keyArray->Set(thread, index, key);
|
||||
valueArray->Set(thread, index, value);
|
||||
return;
|
||||
}
|
||||
index ^= 0xFFFFFFFF;
|
||||
if (index < size) {
|
||||
obj->AdjustArray(thread, *keyArray, index, size, true);
|
||||
obj->AdjustArray(thread, *valueArray, index, size, true);
|
||||
}
|
||||
int32_t capacity = valueArray->GetLength();
|
||||
if (size + 1 >= capacity) {
|
||||
uint32_t newCapacity = capacity << 1U;
|
||||
keyArray =
|
||||
thread->GetEcmaVM()->GetFactory()->CopyArray(keyArray, capacity, newCapacity);
|
||||
valueArray =
|
||||
thread->GetEcmaVM()->GetFactory()->CopyArray(valueArray, capacity, newCapacity);
|
||||
obj->SetKeys(thread, keyArray);
|
||||
obj->SetValues(thread, valueArray);
|
||||
}
|
||||
keyArray->Set(thread, index, key);
|
||||
valueArray->Set(thread, index, value);
|
||||
size++;
|
||||
obj->SetLength(size);
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> JSAPIPlainArray::CreateSlot(const JSThread *thread, const uint32_t capacity)
|
||||
{
|
||||
ASSERT_PRINT(capacity > 0, "size must be a non-negative integer");
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TaggedArray> taggedArray = factory->NewTaggedArray(capacity, JSTaggedValue::Hole());
|
||||
return taggedArray;
|
||||
}
|
||||
|
||||
bool JSAPIPlainArray::AdjustForward(JSThread *thread, int32_t index, int32_t forwardSize)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
TaggedArray *keys = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
AdjustArray(thread, keys, index + forwardSize, index, false);
|
||||
AdjustArray(thread, values, index + forwardSize, index, false);
|
||||
size = size - forwardSize;
|
||||
SetLength(size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void JSAPIPlainArray::AdjustArray(JSThread *thread, TaggedArray *srcArray, int32_t fromIndex,
|
||||
int32_t toIndex, bool direction)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
int32_t idx = size - 1;
|
||||
if (direction) {
|
||||
while (fromIndex < toIndex) {
|
||||
JSTaggedValue value = srcArray->Get(idx);
|
||||
srcArray->Set(thread, idx + 1, value);
|
||||
idx--;
|
||||
fromIndex++;
|
||||
}
|
||||
} else {
|
||||
int32_t moveSize = size - fromIndex;
|
||||
for (int32_t i = 0; i < moveSize; i++) {
|
||||
if ((fromIndex + i) < size) {
|
||||
JSTaggedValue value = srcArray->Get(fromIndex + i);
|
||||
srcArray->Set(thread, toIndex + i, value);
|
||||
} else {
|
||||
srcArray->Set(thread, toIndex + i, JSTaggedValue::Hole());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t JSAPIPlainArray::BinarySearch(TaggedArray *array, int32_t fromIndex, int32_t toIndex, int32_t key)
|
||||
{
|
||||
int32_t low = fromIndex;
|
||||
int32_t high = toIndex - 1;
|
||||
while (low <= high) {
|
||||
int32_t mid = (low + high) >> 1U;
|
||||
int32_t midVal = static_cast<int32_t>(array->Get(mid).GetNumber());
|
||||
if (midVal < key) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
if (midVal <= key) {
|
||||
return mid;
|
||||
}
|
||||
high = mid - 1;
|
||||
}
|
||||
}
|
||||
return -(low + 1);
|
||||
}
|
||||
|
||||
void JSAPIPlainArray::Clear(JSThread *thread)
|
||||
{
|
||||
TaggedArray *keys = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
int32_t size = GetLength();
|
||||
for (int32_t index = 0; index < size; index++) {
|
||||
keys->Set(thread, index, JSTaggedValue::Hole());
|
||||
values->Set(thread, index, JSTaggedValue::Hole());
|
||||
}
|
||||
SetLength(0);
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::RemoveRangeFrom(JSThread *thread, int32_t index, int32_t batchSize)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
if (index < 0 || index >= size) {
|
||||
return JSTaggedValue(-1);
|
||||
}
|
||||
if (batchSize < 1) {
|
||||
return JSTaggedValue(-1);
|
||||
}
|
||||
int32_t safeSize = (size - (index + batchSize)) < 0 ? size - index : batchSize;
|
||||
AdjustForward(thread, index, safeSize);
|
||||
return JSTaggedValue(safeSize);
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::Set(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
const uint32_t index, JSTaggedValue value)
|
||||
{
|
||||
JSHandle<JSTaggedValue> key(thread, JSTaggedValue(index));
|
||||
JSHandle<JSTaggedValue> valueHandle(thread, value);
|
||||
JSAPIPlainArray::Add(thread, obj, key, valueHandle);
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
bool JSAPIPlainArray::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
|
||||
{
|
||||
TaggedArray *keyArray = TaggedArray::Cast(obj->GetKeys().GetTaggedObject());
|
||||
int32_t size = obj->GetLength();
|
||||
int32_t index = obj->BinarySearch(keyArray, 0, size, key.GetTaggedValue().GetNumber());
|
||||
if (index < 0 || index > size) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false);
|
||||
}
|
||||
return JSObject::GetOwnProperty(thread, JSHandle<JSObject>::Cast(obj), key, desc);
|
||||
}
|
||||
|
||||
OperationResult JSAPIPlainArray::GetProperty(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
TaggedArray *keyArray = TaggedArray::Cast(obj->GetKeys().GetTaggedObject());
|
||||
int32_t size = obj->GetLength();
|
||||
int32_t index = obj->BinarySearch(keyArray, 0, size, key.GetTaggedValue().GetNumber());
|
||||
if (index < 0 || index > size) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds",
|
||||
OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
|
||||
}
|
||||
|
||||
return OperationResult(thread, obj->Get(JSTaggedValue(index)), PropertyMetaData(false));
|
||||
}
|
||||
|
||||
JSHandle<JSAPIPlainArray> JSAPIPlainArray::Clone(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj)
|
||||
{
|
||||
JSHandle<TaggedArray> keys(thread, obj->GetKeys());
|
||||
JSHandle<TaggedArray> values(thread, obj->GetValues());
|
||||
int32_t capacity = keys->GetLength();
|
||||
int32_t size = obj->GetLength();
|
||||
JSHandle<JSAPIPlainArray> newPlainArray = thread->GetEcmaVM()->GetFactory()->NewJSAPIPlainArray(capacity);
|
||||
newPlainArray->SetLength(size);
|
||||
TaggedArray *newKeys = TaggedArray::Cast(newPlainArray->GetKeys().GetTaggedObject());
|
||||
TaggedArray *newValues = TaggedArray::Cast(newPlainArray->GetValues().GetTaggedObject());
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
newKeys->Set(thread, i, keys->Get(i));
|
||||
newValues->Set(thread, i, values->Get(i));
|
||||
}
|
||||
return newPlainArray;
|
||||
}
|
||||
|
||||
bool JSAPIPlainArray::Has(const int32_t key)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
TaggedArray *keyArray = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
int32_t index = BinarySearch(keyArray, 0, size, key);
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::Get(const JSTaggedValue key)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
TaggedArray *keyArray = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
int32_t index = BinarySearch(keyArray, 0, size, key.GetNumber());
|
||||
if (index < 0) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
return values->Get(index);
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> JSAPIPlainArray::GetIteratorObj(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
IterationKind kind)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> iter =
|
||||
JSHandle<JSTaggedValue>::Cast(factory->NewJSAPIPlainArrayIterator(obj, kind));
|
||||
return iter;
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::ForEach(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
|
||||
const JSHandle<JSTaggedValue> &callbackFn,
|
||||
const JSHandle<JSTaggedValue> &thisArg)
|
||||
{
|
||||
JSAPIPlainArray *plainarray = JSAPIPlainArray::Cast(thisHandle->GetTaggedObject());
|
||||
int32_t length = plainarray->GetLength();
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
JSHandle<TaggedArray> keyArray(thread, plainarray->GetKeys());
|
||||
JSHandle<TaggedArray> valueArray(thread, plainarray->GetValues());
|
||||
for (int32_t k = 0; k < length; k++) {
|
||||
JSTaggedValue kValue = valueArray->Get(k);
|
||||
JSTaggedValue key = keyArray->Get(k);
|
||||
EcmaRuntimeCallInfo info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, 3); // 3: three args
|
||||
info.SetCallArg(kValue, key, thisHandle.GetTaggedValue());
|
||||
JSTaggedValue funcResult = JSFunction::Call(&info);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
|
||||
}
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::ToString(JSThread *thread, const JSHandle<JSAPIPlainArray> &plainarray)
|
||||
{
|
||||
EcmaVM *ecmaVM = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = ecmaVM->GetFactory();
|
||||
std::u16string sepStr = std::wstring_convert < std::codecvt_utf8_utf16<char16_t>, char16_t > {}.from_bytes(",");
|
||||
int32_t length = plainarray->GetLength();
|
||||
JSHandle<TaggedArray> keyArray(thread, plainarray->GetKeys());
|
||||
JSHandle<TaggedArray> elements(thread, plainarray->GetValues());
|
||||
std::u16string concatStr;
|
||||
std::u16string concatStrNew;
|
||||
|
||||
JSHandle<EcmaString> stringSeparate = factory->NewFromASCII(":");
|
||||
JSMutableHandle<JSTaggedValue> keys(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<EcmaString> ret(thread, nullptr);
|
||||
JSMutableHandle<EcmaString> stringKey(thread, nullptr);
|
||||
JSMutableHandle<EcmaString> stringValue(thread, nullptr);
|
||||
JSMutableHandle<EcmaString> concatValue(thread, nullptr);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
for (int32_t k = 0; k < length; k++) {
|
||||
std::u16string nextStr;
|
||||
keys.Update(JSTaggedValue(keyArray->Get(k)));
|
||||
element.Update(JSTaggedValue(elements->Get(k)));
|
||||
if (!element->IsUndefined() && !element->IsNull()) {
|
||||
stringKey.Update(JSTaggedValue::ToString(thread, keys).GetTaggedValue());
|
||||
ret.Update(JSTaggedValue(EcmaString::Concat(stringKey, stringSeparate, ecmaVM)));
|
||||
|
||||
stringValue.Update(JSTaggedValue::ToString(thread, element).GetTaggedValue());
|
||||
concatValue.Update(JSTaggedValue(EcmaString::Concat(ret, stringValue, ecmaVM)));
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
uint32_t nextLen = concatValue->GetLength();
|
||||
if (concatValue->IsUtf16()) {
|
||||
nextStr = base::StringHelper::Utf16ToU16String(concatValue->GetDataUtf16(), nextLen);
|
||||
} else {
|
||||
nextStr = base::StringHelper::Utf8ToU16String(concatValue->GetDataUtf8(), nextLen);
|
||||
}
|
||||
}
|
||||
if (k > 0) {
|
||||
concatStrNew = base::StringHelper::Append(concatStr, sepStr);
|
||||
concatStr = base::StringHelper::Append(concatStrNew, nextStr);
|
||||
continue;
|
||||
}
|
||||
concatStr = base::StringHelper::Append(concatStr, nextStr);
|
||||
}
|
||||
char16_t *char16tData = concatStr.data();
|
||||
auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
|
||||
int32_t u16strSize = concatStr.size();
|
||||
return factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::GetIndexOfKey(int32_t key)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
TaggedArray *keyArray = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
int32_t index = BinarySearch(keyArray, 0, size, key);
|
||||
if (index < 0) {
|
||||
return JSTaggedValue(-1);
|
||||
}
|
||||
return JSTaggedValue(index);
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::GetIndexOfValue(JSTaggedValue value)
|
||||
{
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
int32_t size = GetLength();
|
||||
int32_t index = -1;
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
if (JSTaggedValue::SameValue(values->Get(i), value)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) {
|
||||
return JSTaggedValue(-1);
|
||||
}
|
||||
return JSTaggedValue(index);
|
||||
}
|
||||
|
||||
bool JSAPIPlainArray::IsEmpty()
|
||||
{
|
||||
int32_t length = GetLength();
|
||||
return length == 0;
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::GetKeyAt(int32_t index)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
TaggedArray *keyArray = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
if (index < 0 || index >= size) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
return keyArray->Get(index);
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::GetValueAt(int32_t index)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
if (index < 0 || index >= size) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
return values->Get(index);
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::Remove(JSThread *thread, JSTaggedValue key)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
TaggedArray *keyArray = TaggedArray::Cast(GetKeys().GetTaggedObject());
|
||||
int32_t index = BinarySearch(keyArray, 0, size, key.GetNumber());
|
||||
if (index < 0 || index >= size) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
JSTaggedValue value = values->Get(index);
|
||||
AdjustForward(thread, index, 1); // 1 means the length of array
|
||||
return value;
|
||||
}
|
||||
|
||||
JSTaggedValue JSAPIPlainArray::RemoveAt(JSThread *thread, JSTaggedValue index)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
int32_t seat = index.GetNumber();
|
||||
if (seat < 0 || seat >= size) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
JSTaggedValue value = values->Get(seat);
|
||||
AdjustForward(thread, seat, 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool JSAPIPlainArray::SetValueAt(JSThread *thread, JSTaggedValue index, JSTaggedValue value)
|
||||
{
|
||||
int32_t size = GetLength();
|
||||
int32_t seat = index.GetNumber();
|
||||
if (seat < 0 || seat >= size) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", false);
|
||||
}
|
||||
TaggedArray *values = TaggedArray::Cast(GetValues().GetTaggedObject());
|
||||
values->Set(thread, seat, value);
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
82
ecmascript/js_api_plain_array.h
Normal file
82
ecmascript/js_api_plain_array.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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_JSPLAIN_ARRAY_H
|
||||
#define ECMASCRIPT_JSPLAIN_ARRAY_H
|
||||
|
||||
#include "js_object.h"
|
||||
#include "js_tagged_value-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class JSAPIPlainArray : public JSObject {
|
||||
public:
|
||||
static constexpr int DEFAULT_CAPACITY_LENGTH = 8;
|
||||
static JSAPIPlainArray *Cast(ObjectHeader *object)
|
||||
{
|
||||
ASSERT(JSTaggedValue(object).IsJSAPIPlainArray());
|
||||
return static_cast<JSAPIPlainArray *>(object);
|
||||
}
|
||||
static void Add(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value);
|
||||
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc);
|
||||
static JSHandle<TaggedArray> CreateSlot(const JSThread *thread, const uint32_t capacity);
|
||||
static JSHandle<JSAPIPlainArray> Clone(JSThread *thread, const JSHandle<JSAPIPlainArray> &plainArray);
|
||||
static JSHandle<JSTaggedValue> GetIteratorObj(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
IterationKind kind);
|
||||
static JSTaggedValue ForEach(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
|
||||
const JSHandle<JSTaggedValue> &callbackFn, const JSHandle<JSTaggedValue> &thisArg);
|
||||
static JSTaggedValue ToString(JSThread *thread, const JSHandle<JSAPIPlainArray> &plainarray);
|
||||
static OperationResult GetProperty(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
const JSHandle<JSTaggedValue> &key);
|
||||
static JSTaggedValue Set(JSThread *thread, const JSHandle<JSAPIPlainArray> &obj,
|
||||
const uint32_t index, JSTaggedValue value);
|
||||
JSTaggedValue RemoveAt(JSThread *thread, JSTaggedValue index);
|
||||
JSTaggedValue GetIndexOfKey(int32_t key);
|
||||
JSTaggedValue GetIndexOfValue(JSTaggedValue value);
|
||||
JSTaggedValue GetKeyAt(int32_t index);
|
||||
JSTaggedValue GetValueAt(int32_t index);
|
||||
JSTaggedValue Get(const JSTaggedValue key);
|
||||
JSTaggedValue Remove(JSThread *thread, JSTaggedValue key);
|
||||
JSTaggedValue RemoveRangeFrom(JSThread *thread, int32_t index, int32_t batchSize);
|
||||
bool SetValueAt(JSThread *thread, JSTaggedValue index, JSTaggedValue value);
|
||||
bool Has(const int32_t key);
|
||||
bool IsEmpty();
|
||||
bool AdjustForward(JSThread *thread, int32_t index, int32_t forwardSize);
|
||||
int32_t BinarySearch(TaggedArray *array, int32_t fromIndex, int32_t toIndex, int32_t key);
|
||||
void Clear(JSThread *thread);
|
||||
void AdjustArray(JSThread *thread, TaggedArray *srcArray, int32_t fromIndex, int32_t toIndex,
|
||||
bool direction);
|
||||
inline int GetSize() const
|
||||
{
|
||||
return GetLength();
|
||||
}
|
||||
static constexpr size_t KEYS_OFFSET = JSObject::SIZE;
|
||||
ACCESSORS(Keys, KEYS_OFFSET, VALUES_OFFSET);
|
||||
ACCESSORS(Values, VALUES_OFFSET, LENGTH_OFFSET);
|
||||
ACCESSORS_PRIMITIVE_FIELD(Length, int32_t, LENGTH_OFFSET, LAST_OFFSET);
|
||||
DEFINE_ALIGN_SIZE(LAST_OFFSET);
|
||||
|
||||
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, KEYS_OFFSET, LENGTH_OFFSET)
|
||||
DECL_DUMP()
|
||||
private:
|
||||
inline static uint32_t ComputeCapacity(uint32_t oldCapacity)
|
||||
{
|
||||
uint32_t newCapacity = oldCapacity + (oldCapacity >> 1U);
|
||||
return newCapacity > DEFAULT_CAPACITY_LENGTH ? newCapacity : DEFAULT_CAPACITY_LENGTH;
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_JSPLAIN_ARRAY_H
|
65
ecmascript/js_api_plain_array_iterator.cpp
Normal file
65
ecmascript/js_api_plain_array_iterator.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 "js_api_plain_array_iterator.h"
|
||||
#include "builtins/builtins_errors.h"
|
||||
#include "ecmascript/base/typed_array_helper.h"
|
||||
#include "ecmascript/base/typed_array_helper-inl.h"
|
||||
#include "global_env.h"
|
||||
#include "js_api_plain_array.h"
|
||||
#include "js_array.h"
|
||||
#include "object_factory.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using BuiltinsBase = base::BuiltinsBase;
|
||||
JSTaggedValue JSAPIPlainArrayIterator::Next(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> input(BuiltinsBase::GetThis(argv));
|
||||
if (!input->IsJSAPIPlainArrayIterator()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not an plainarray iterator", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSAPIPlainArrayIterator> iter(input);
|
||||
JSHandle<JSTaggedValue> plainArray(thread, iter->GetIteratedPlainArray());
|
||||
JSHandle<JSTaggedValue> undefinedHandle(thread, JSTaggedValue::Undefined());
|
||||
if (plainArray->IsUndefined()) {
|
||||
return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue();
|
||||
}
|
||||
|
||||
JSHandle<JSAPIPlainArray> apiPlainArray(plainArray);
|
||||
ASSERT(plainArray->IsJSAPIPlainArray());
|
||||
|
||||
int32_t length = apiPlainArray->GetLength();
|
||||
int32_t index = iter->GetNextIndex();
|
||||
if (index >= length) {
|
||||
iter->SetIteratedPlainArray(thread, undefinedHandle);
|
||||
return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue();
|
||||
}
|
||||
iter->SetNextIndex(index + 1);
|
||||
JSHandle<TaggedArray> valueArray(thread, TaggedArray::Cast(apiPlainArray->GetValues().GetTaggedObject()));
|
||||
JSHandle<JSTaggedValue> value(thread, valueArray->Get(index));
|
||||
JSHandle<TaggedArray> keyArray(thread, TaggedArray::
|
||||
Cast(JSHandle<JSAPIPlainArray>(plainArray)->GetKeys().GetTaggedObject()));
|
||||
JSHandle<JSTaggedValue> keyHandle(thread, keyArray->Get(index));
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TaggedArray> array(factory->NewTaggedArray(2)); // 2 means the length of array
|
||||
array->Set(thread, 0, keyHandle);
|
||||
array->Set(thread, 1, value);
|
||||
JSHandle<JSTaggedValue> keyAndValue(JSArray::CreateArrayFromList(thread, array));
|
||||
return JSIterator::CreateIterResultObject(thread, keyAndValue, false).GetTaggedValue();
|
||||
}
|
||||
} // namespace panda::ecmascript
|
45
ecmascript/js_api_plain_array_iterator.h
Normal file
45
ecmascript/js_api_plain_array_iterator.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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_API_PLAIN_ARRAY_ITERATOR_H
|
||||
#define ECMASCRIPT_JS_API_PLAIN_ARRAY_ITERATOR_H
|
||||
|
||||
#include "js_iterator.h"
|
||||
#include "js_object.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class JSAPIPlainArrayIterator : public JSObject {
|
||||
public:
|
||||
static JSAPIPlainArrayIterator *Cast(ObjectHeader *obj)
|
||||
{
|
||||
ASSERT(JSTaggedValue(obj).IsJSAPIPlainArrayIterator());
|
||||
return static_cast<JSAPIPlainArrayIterator *>(obj);
|
||||
}
|
||||
static JSTaggedValue Next(EcmaRuntimeCallInfo *argv);
|
||||
static constexpr size_t ITERATED_PLAIN_ARRAY_OFFSET = JSObject::SIZE;
|
||||
ACCESSORS(IteratedPlainArray, ITERATED_PLAIN_ARRAY_OFFSET, NEXT_INDEX_OFFSET);
|
||||
ACCESSORS_PRIMITIVE_FIELD(NextIndex, int32_t, NEXT_INDEX_OFFSET, BIT_FIELD_OFFSET)
|
||||
ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
|
||||
DEFINE_ALIGN_SIZE(LAST_OFFSET);
|
||||
|
||||
// define BitField
|
||||
static constexpr size_t ITERATION_KIND_BITS = 2; // 2 is define bit field
|
||||
FIRST_BIT_FIELD(BitField, IterationKind, IterationKind, ITERATION_KIND_BITS)
|
||||
|
||||
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ITERATED_PLAIN_ARRAY_OFFSET, NEXT_INDEX_OFFSET)
|
||||
DECL_DUMP()
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_JS_API_PLAIN_ARRAY_ITERATOR_H
|
@ -98,6 +98,7 @@ class ProtoChangeDetails;
|
||||
JS_SET_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_ARRAYLIST_ITERATOR, /* /////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_DEQUE_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_PLAIN_ARRAY_ITERATOR, /* //////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_QUEUE_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_STACK_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_TREEMAP_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
@ -129,6 +130,7 @@ class ProtoChangeDetails;
|
||||
JS_API_TREE_SET, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_DEQUE, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_STACK, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_PLAIN_ARRAY, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_API_QUEUE, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_TYPED_ARRAY, /* JS_TYPED_ARRAY_BEGIN /////////////////////////////////////////////////////////////////// */ \
|
||||
JS_INT8_ARRAY, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
@ -661,10 +663,12 @@ public:
|
||||
{
|
||||
return GetObjectType() >= JSType::JS_API_ARRAY_LIST && GetObjectType() <= JSType::JS_API_QUEUE;
|
||||
}
|
||||
|
||||
inline bool IsJSAPIArrayList() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_ARRAY_LIST;
|
||||
}
|
||||
|
||||
inline bool IsJSAPIArrayListIterator() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_ARRAYLIST_ITERATOR;
|
||||
@ -684,6 +688,12 @@ public:
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_QUEUE;
|
||||
}
|
||||
|
||||
inline bool IsJSAPIPlainArray() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_PLAIN_ARRAY;
|
||||
}
|
||||
|
||||
inline bool IsJSAPIQueueIterator() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_QUEUE_ITERATOR;
|
||||
@ -693,14 +703,17 @@ public:
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_TREE_MAP;
|
||||
}
|
||||
|
||||
inline bool IsJSAPITreeSet() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_TREE_SET;
|
||||
}
|
||||
|
||||
inline bool IsJSAPITreeMapIterator() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_TREEMAP_ITERATOR;
|
||||
}
|
||||
|
||||
inline bool IsJSAPITreeSetIterator() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_TREESET_ITERATOR;
|
||||
@ -762,6 +775,11 @@ public:
|
||||
return GetObjectType() == JSType::JS_ARRAY_ITERATOR;
|
||||
}
|
||||
|
||||
inline bool IsJSAPIPlainArrayIterator() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_PLAIN_ARRAY_ITERATOR;
|
||||
}
|
||||
|
||||
inline bool IsJSAPIDequeIterator() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_API_DEQUE_ITERATOR;
|
||||
|
@ -609,6 +609,16 @@ inline bool JSTaggedValue::IsJSAPITreeSet() const
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPITreeSet();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsJSAPIPlainArray() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIPlainArray();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsJSAPIPlainArrayIterator() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIPlainArrayIterator();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsJSAPIQueue() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIQueue();
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/interpreter/interpreter.h"
|
||||
#include "ecmascript/js_api_deque.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_api_queue.h"
|
||||
#include "ecmascript/js_api_stack.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
@ -507,6 +508,10 @@ OperationResult JSTaggedValue::GetProperty(JSThread *thread, const JSHandle<JSTa
|
||||
return ModuleNamespace::GetProperty(thread, obj, key);
|
||||
}
|
||||
|
||||
if (obj->IsSpecialContainer()) {
|
||||
return GetJSAPIProperty(thread, obj, key);
|
||||
}
|
||||
|
||||
return JSObject::GetProperty(thread, obj, key);
|
||||
}
|
||||
|
||||
@ -526,6 +531,11 @@ OperationResult JSTaggedValue::GetProperty(JSThread *thread, const JSHandle<JSTa
|
||||
return JSTypedArray::GetProperty(thread, obj, key);
|
||||
}
|
||||
|
||||
if (obj->IsSpecialContainer()) {
|
||||
JSHandle<JSTaggedValue> keyHandle = JSHandle<JSTaggedValue>(thread, JSTaggedValue(key));
|
||||
return GetJSAPIProperty(thread, obj, keyHandle);
|
||||
}
|
||||
|
||||
return JSObject::GetProperty(thread, obj, key);
|
||||
}
|
||||
|
||||
@ -545,6 +555,10 @@ OperationResult JSTaggedValue::GetProperty(JSThread *thread, const JSHandle<JSTa
|
||||
return JSTypedArray::GetProperty(thread, obj, JSTypedArray::ToPropKey(thread, key), receiver);
|
||||
}
|
||||
|
||||
if (obj->IsSpecialContainer()) {
|
||||
return GetJSAPIProperty(thread, obj, key);
|
||||
}
|
||||
|
||||
return JSObject::GetProperty(thread, obj, key, receiver);
|
||||
}
|
||||
|
||||
@ -915,6 +929,9 @@ bool JSTaggedValue::HasContainerProperty(JSThread *thread, const JSHandle<JSTagg
|
||||
case JSType::JS_API_QUEUE: {
|
||||
return JSHandle<JSAPIQueue>::Cast(obj)->Has(key.GetTaggedValue());
|
||||
}
|
||||
case JSType::JS_API_PLAIN_ARRAY: {
|
||||
return JSObject::HasProperty(thread, JSHandle<JSObject>(obj), key);
|
||||
}
|
||||
case JSType::JS_API_DEQUE: {
|
||||
return JSHandle<JSAPIDeque>::Cast(obj)->Has(key.GetTaggedValue());
|
||||
}
|
||||
@ -943,6 +960,9 @@ JSHandle<TaggedArray> JSTaggedValue::GetOwnContainerPropertyKeys(JSThread *threa
|
||||
case JSType::JS_API_QUEUE: {
|
||||
return JSAPIQueue::OwnKeys(thread, JSHandle<JSAPIQueue>::Cast(obj));
|
||||
}
|
||||
case JSType::JS_API_PLAIN_ARRAY: {
|
||||
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(obj));
|
||||
}
|
||||
case JSType::JS_API_DEQUE: {
|
||||
return JSAPIDeque::OwnKeys(thread, JSHandle<JSAPIDeque>::Cast(obj));
|
||||
}
|
||||
@ -972,6 +992,9 @@ bool JSTaggedValue::GetContainerProperty(JSThread *thread, const JSHandle<JSTagg
|
||||
case JSType::JS_API_QUEUE: {
|
||||
return JSAPIQueue::GetOwnProperty(thread, JSHandle<JSAPIQueue>::Cast(obj), key, desc);
|
||||
}
|
||||
case JSType::JS_API_PLAIN_ARRAY: {
|
||||
return JSAPIPlainArray::GetOwnProperty(thread, JSHandle<JSAPIPlainArray>::Cast(obj), key, desc);
|
||||
}
|
||||
case JSType::JS_API_DEQUE: {
|
||||
return JSAPIDeque::GetOwnProperty(thread, JSHandle<JSAPIDeque>::Cast(obj), key, desc);
|
||||
}
|
||||
@ -1005,4 +1028,22 @@ JSHandle<JSTaggedValue> JSTaggedValue::ToNumeric(JSThread *thread, JSTaggedValue
|
||||
JSHandle<JSTaggedValue> value(thread, number);
|
||||
return value;
|
||||
}
|
||||
OperationResult JSTaggedValue::GetJSAPIProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
auto *hclass = obj->GetTaggedObject()->GetClass();
|
||||
JSType jsType = hclass->GetObjectType();
|
||||
if (key->IsNumber()) {
|
||||
switch (jsType) {
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
return JSAPIPlainArray::GetProperty(thread, JSHandle<JSAPIPlainArray>::Cast(obj), key);
|
||||
default: {
|
||||
return JSObject::GetProperty(thread, JSHandle<JSObject>(obj), key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return JSObject::GetProperty(thread, JSHandle<JSObject>(obj), key);
|
||||
}
|
||||
return OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false));
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -338,6 +338,8 @@ public:
|
||||
bool IsJSAPITreeSetIterator() const;
|
||||
bool IsJSAPIQueue() const;
|
||||
bool IsJSAPIQueueIterator() const;
|
||||
bool IsJSAPIPlainArray() const;
|
||||
bool IsJSAPIPlainArrayIterator() const;
|
||||
bool IsJSAPIDeque() const;
|
||||
bool IsJSAPIDequeIterator() const;
|
||||
bool IsJSAPIStack() const;
|
||||
@ -396,6 +398,8 @@ private:
|
||||
static JSHandle<TaggedArray> GetOwnContainerPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
|
||||
static bool GetContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc);
|
||||
static OperationResult GetJSAPIProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &key);
|
||||
};
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(JSTaggedValue), JSTaggedValue::SizeArch32, JSTaggedValue::SizeArch64);
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "ecmascript/jobs/pending_job.h"
|
||||
#include "ecmascript/js_api_deque.h"
|
||||
#include "ecmascript/js_api_deque_iterator.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_api_queue.h"
|
||||
#include "ecmascript/js_api_queue_iterator.h"
|
||||
#include "ecmascript/js_api_stack.h"
|
||||
@ -431,6 +433,12 @@ void ObjectXRay::VisitObjectBody(TaggedObject *object, JSHClass *klass, const Ec
|
||||
case JSType::JS_API_TREESET_ITERATOR:
|
||||
JSAPITreeSetIterator::Cast(object)->VisitRangeSlot(visitor);
|
||||
break;
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
JSAPIPlainArray::Cast(object)->VisitRangeSlot(visitor);
|
||||
break;
|
||||
case JSType::JS_API_PLAIN_ARRAY_ITERATOR:
|
||||
JSAPIPlainArrayIterator::Cast(object)->VisitRangeSlot(visitor);
|
||||
break;
|
||||
case JSType::JS_API_DEQUE:
|
||||
JSAPIDeque::Cast(object)->VisitRangeSlot(visitor);
|
||||
break;
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "ecmascript/jobs/pending_job.h"
|
||||
#include "ecmascript/js_api_deque.h"
|
||||
#include "ecmascript/js_api_deque_iterator.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_api_queue.h"
|
||||
#include "ecmascript/js_api_queue_iterator.h"
|
||||
#include "ecmascript/js_api_stack.h"
|
||||
@ -874,6 +876,11 @@ JSHandle<JSObject> ObjectFactory::NewJSObjectByConstructor(const JSHandle<JSFunc
|
||||
JSAPIQueue::Cast(*obj)->SetFront(0);
|
||||
JSAPIQueue::Cast(*obj)->SetTail(0);
|
||||
break;
|
||||
case JSType::JS_API_PLAIN_ARRAY:
|
||||
JSAPIPlainArray::Cast(*obj)->SetLength(0);
|
||||
JSAPIPlainArray::Cast(*obj)->SetValues(thread_, JSTaggedValue(0));
|
||||
JSAPIPlainArray::Cast(*obj)->SetKeys(thread_, JSTaggedValue(0));
|
||||
break;
|
||||
case JSType::JS_API_STACK:
|
||||
JSAPIStack::Cast(*obj)->SetTop(0);
|
||||
break;
|
||||
@ -893,6 +900,7 @@ JSHandle<JSObject> ObjectFactory::NewJSObjectByConstructor(const JSHandle<JSFunc
|
||||
case JSType::JS_API_DEQUE_ITERATOR:
|
||||
case JSType::JS_API_STACK_ITERATOR:
|
||||
case JSType::JS_ARRAY_ITERATOR:
|
||||
case JSType::JS_API_PLAIN_ARRAY_ITERATOR:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -2521,6 +2529,38 @@ JSHandle<JSAPIArrayListIterator> ObjectFactory::NewJSAPIArrayListIterator(const
|
||||
return iter;
|
||||
}
|
||||
|
||||
JSHandle<JSAPIPlainArray> ObjectFactory::NewJSAPIPlainArray(array_size_t capacity)
|
||||
{
|
||||
NewObjectHook();
|
||||
JSHandle<JSTaggedValue> builtinObj(thread_, thread_->GlobalConstants()->GetPlainArrayFunction());
|
||||
|
||||
JSHandle<JSAPIPlainArray> obj =
|
||||
JSHandle<JSAPIPlainArray>(NewJSObjectByConstructor(JSHandle<JSFunction>(builtinObj), builtinObj));
|
||||
ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(capacity);
|
||||
JSHandle<TaggedArray> valueArray = factory->NewTaggedArray(capacity);
|
||||
obj->SetKeys(thread_, keyArray);
|
||||
obj->SetValues(thread_, valueArray);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSHandle<JSAPIPlainArrayIterator> ObjectFactory::NewJSAPIPlainArrayIterator(const JSHandle<JSAPIPlainArray> &plainarray,
|
||||
IterationKind kind)
|
||||
{
|
||||
NewObjectHook();
|
||||
JSHandle<JSTaggedValue> protoValue(thread_, thread_->GlobalConstants()->GetPlainArrayIteratorPrototype());
|
||||
const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
|
||||
JSHandle<JSHClass> dynHandle(globalConst->GetHandledJSAPIPlainArrayIteratorClass());
|
||||
dynHandle->SetPrototype(thread_, protoValue);
|
||||
JSHandle<JSAPIPlainArrayIterator> iter(NewJSObject(dynHandle));
|
||||
iter->GetJSHClass()->SetExtensible(true);
|
||||
iter->SetIteratedPlainArray(thread_, plainarray);
|
||||
iter->SetNextIndex(0);
|
||||
iter->SetIterationKind(kind);
|
||||
return iter;
|
||||
}
|
||||
|
||||
JSHandle<JSAPIStackIterator> ObjectFactory::NewJSAPIStackIterator(const JSHandle<JSAPIStack> &stack)
|
||||
{
|
||||
NewObjectHook();
|
||||
|
@ -33,6 +33,7 @@ namespace panda::ecmascript {
|
||||
class JSMethod;
|
||||
class JSObject;
|
||||
class JSArray;
|
||||
class JSAPIPlainArray;
|
||||
class JSSymbol;
|
||||
class JSFunctionBase;
|
||||
class JSFunction;
|
||||
@ -57,6 +58,7 @@ class JSRegExp;
|
||||
class JSSetIterator;
|
||||
class JSMapIterator;
|
||||
class JSArrayIterator;
|
||||
class JSAPIPlainArrayIterator;
|
||||
class JSStringIterator;
|
||||
class JSGeneratorObject;
|
||||
class CompletionRecord;
|
||||
@ -404,6 +406,9 @@ public:
|
||||
JSHandle<JSHClass> NewEcmaDynClass(uint32_t size, JSType type, const JSHandle<JSTaggedValue> &prototype);
|
||||
|
||||
// It is used to provide iterators for non ECMA standard jsapi containers.
|
||||
JSHandle<JSAPIPlainArray> NewJSAPIPlainArray(array_size_t capacity);
|
||||
JSHandle<JSAPIPlainArrayIterator> NewJSAPIPlainArrayIterator(const JSHandle<JSAPIPlainArray> &plainarray,
|
||||
IterationKind kind);
|
||||
JSHandle<JSAPIArrayList> NewJSAPIArrayList(uint32_t capacity);
|
||||
JSHandle<TaggedArray> CopyQueue(const JSHandle<TaggedArray> &old, uint32_t oldLength,
|
||||
uint32_t newLength, uint32_t front, uint32_t tail);
|
||||
|
@ -559,6 +559,25 @@ namespace panda::ecmascript {
|
||||
V(ArrayList, Get) \
|
||||
V(ArrayList, Set) \
|
||||
V(ArrayList, GetSize) \
|
||||
V(PlainArray, Constructor) \
|
||||
V(PlainArray, Add) \
|
||||
V(PlainArray, Clear) \
|
||||
V(PlainArray, Clone) \
|
||||
V(PlainArray, Has) \
|
||||
V(PlainArray, Get) \
|
||||
V(PlainArray, GetIteratorObj) \
|
||||
V(PlainArray, ForEach) \
|
||||
V(PlainArray, ToString) \
|
||||
V(PlainArray, GetIndexOfKey) \
|
||||
V(PlainArray, GetIndexOfValue) \
|
||||
V(PlainArray, IsEmpty) \
|
||||
V(PlainArray, GetKeyAt) \
|
||||
V(PlainArray, Remove) \
|
||||
V(PlainArray, RemoveAt) \
|
||||
V(PlainArray, RemoveRangeFrom) \
|
||||
V(PlainArray, SetValueAt) \
|
||||
V(PlainArray, GetValueAt) \
|
||||
V(PlainArray, GetSize) \
|
||||
V(TreeMap, Constructor) \
|
||||
V(TreeMap, HasKey) \
|
||||
V(TreeMap, HasValue) \
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "ecmascript/builtins/builtins_weak_set.h"
|
||||
#include "ecmascript/containers/containers_arraylist.h"
|
||||
#include "ecmascript/containers/containers_deque.h"
|
||||
#include "ecmascript/containers/containers_plainarray.h"
|
||||
#include "ecmascript/containers/containers_private.h"
|
||||
#include "ecmascript/containers/containers_queue.h"
|
||||
#include "ecmascript/containers/containers_stack.h"
|
||||
@ -63,6 +64,7 @@
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_api_deque_iterator.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_api_queue_iterator.h"
|
||||
#include "ecmascript/js_api_stack_iterator.h"
|
||||
#include "ecmascript/js_api_tree_map_iterator.h"
|
||||
@ -131,6 +133,7 @@ using ArrayList = containers::ContainersArrayList;
|
||||
using TreeMap = containers::ContainersTreeMap;
|
||||
using TreeSet = containers::ContainersTreeSet;
|
||||
using Queue = containers::ContainersQueue;
|
||||
using PlainArray = containers::ContainersPlainArray;
|
||||
using Deque = containers::ContainersDeque;
|
||||
using ContainerStack = panda::ecmascript::containers::ContainersStack;
|
||||
using ContainersPrivate = containers::ContainersPrivate;
|
||||
@ -660,6 +663,26 @@ static uintptr_t g_nativeTable[] = {
|
||||
reinterpret_cast<uintptr_t>(Queue::GetIteratorObj),
|
||||
reinterpret_cast<uintptr_t>(Queue::GetSize),
|
||||
reinterpret_cast<uintptr_t>(JSAPIQueueIterator::Next),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::PlainArrayConstructor),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::Add),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::Clear),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::Clone),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::Has),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::Get),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::GetIteratorObj),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::ForEach),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::ToString),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::GetIndexOfKey),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::GetIndexOfValue),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::IsEmpty),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::GetKeyAt),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::Remove),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::RemoveAt),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::RemoveRangeFrom),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::SetValueAt),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::GetValueAt),
|
||||
reinterpret_cast<uintptr_t>(PlainArray::GetSize),
|
||||
reinterpret_cast<uintptr_t>(JSAPIPlainArrayIterator::Next),
|
||||
reinterpret_cast<uintptr_t>(ContainerStack::StackConstructor),
|
||||
reinterpret_cast<uintptr_t>(ContainerStack::Iterator),
|
||||
reinterpret_cast<uintptr_t>(ContainerStack::IsEmpty),
|
||||
|
@ -1049,6 +1049,33 @@ host_unittest_action("ConcurrentMarkingTest") {
|
||||
}
|
||||
}
|
||||
|
||||
host_unittest_action("JSAPIPlainArrayTest") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
sources = [
|
||||
# test file
|
||||
"js_api_plain_array_test.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
"//ark/js_runtime:ecma_test_config",
|
||||
"//ark/js_runtime:ark_jsruntime_public_config", # should add before
|
||||
# arkruntime_public_config
|
||||
"//ark/js_runtime:ark_jsruntime_common_config",
|
||||
"$ark_root/runtime:arkruntime_public_config",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"$ark_root/libpandabase:libarkbase",
|
||||
"//ark/js_runtime:libark_jsruntime_test",
|
||||
sdk_libc_secshared_dep,
|
||||
]
|
||||
|
||||
if (!is_standard_system) {
|
||||
deps += [ "$ark_root/runtime:libarkruntime" ]
|
||||
}
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
|
||||
@ -1067,6 +1094,7 @@ group("unittest") {
|
||||
":GlueRegsTest",
|
||||
":HugeObjectTest",
|
||||
":JSAPIDequeTest",
|
||||
":JSAPIPlainArrayTest",
|
||||
":JSAPIStackTest",
|
||||
":JSAPITreeMapTest",
|
||||
":JSAPITreeSetTest",
|
||||
@ -1122,6 +1150,7 @@ group("host_unittest") {
|
||||
":GlueRegsTestAction",
|
||||
":HugeObjectTestAction",
|
||||
":JSAPIDequeTestAction",
|
||||
":JSAPIPlainArrayTestAction",
|
||||
":JSAPIStackTestAction",
|
||||
":JSAPITreeMapTestAction",
|
||||
":JSAPITreeSetTestAction",
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "ecmascript/jobs/pending_job.h"
|
||||
#include "ecmascript/js_api_deque.h"
|
||||
#include "ecmascript/js_api_deque_iterator.h"
|
||||
#include "ecmascript/js_api_plain_array.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_api_queue.h"
|
||||
#include "ecmascript/js_api_queue_iterator.h"
|
||||
#include "ecmascript/js_api_stack.h"
|
||||
@ -182,6 +184,22 @@ static JSHandle<JSAPITreeSet> NewJSAPITreeSet(JSThread *thread, ObjectFactory *f
|
||||
return jsTreeSet;
|
||||
}
|
||||
|
||||
static JSHandle<JSAPIPlainArray> NewJSAPIPlainArray(JSThread *thread, ObjectFactory *factory)
|
||||
{
|
||||
auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
JSHandle<JSTaggedValue> proto = globalEnv->GetObjectFunctionPrototype();
|
||||
JSHandle<JSHClass> mapClass = factory->NewEcmaDynClass(JSAPIPlainArray::SIZE, JSType::JS_API_PLAIN_ARRAY, proto);
|
||||
JSHandle<JSAPIPlainArray> jSAPIPlainArray = JSHandle<JSAPIPlainArray>::Cast(factory->NewJSObject(mapClass));
|
||||
JSHandle<TaggedArray> keys =
|
||||
JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
|
||||
JSHandle<TaggedArray> values =
|
||||
JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
|
||||
jSAPIPlainArray->SetKeys(thread, keys);
|
||||
jSAPIPlainArray->SetValues(thread, values);
|
||||
jSAPIPlainArray->SetLength(0);
|
||||
return jSAPIPlainArray;
|
||||
}
|
||||
|
||||
static JSHandle<JSObject> NewJSObject(JSThread *thread, ObjectFactory *factory, JSHandle<GlobalEnv> globalEnv)
|
||||
{
|
||||
JSFunction *jsFunc = globalEnv->GetObjectFunction().GetObject<JSFunction>();
|
||||
@ -777,6 +795,20 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
|
||||
DUMP_FOR_HANDLE(jsQueueIter)
|
||||
break;
|
||||
}
|
||||
case JSType::JS_API_PLAIN_ARRAY: {
|
||||
CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIPlainArray::SIZE, 3)
|
||||
JSHandle<JSAPIPlainArray> jSAPIPlainArray = NewJSAPIPlainArray(thread, factory);
|
||||
DUMP_FOR_HANDLE(jSAPIPlainArray)
|
||||
break;
|
||||
}
|
||||
case JSType::JS_API_PLAIN_ARRAY_ITERATOR: {
|
||||
CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIPlainArrayIterator::SIZE, 2)
|
||||
JSHandle<JSAPIPlainArray> jSAPIPlainArray = NewJSAPIPlainArray(thread, factory);
|
||||
JSHandle<JSAPIPlainArrayIterator> jSAPIPlainArrayIter =
|
||||
factory->NewJSAPIPlainArrayIterator(jSAPIPlainArray, IterationKind::KEY);
|
||||
DUMP_FOR_HANDLE(jSAPIPlainArrayIter)
|
||||
break;
|
||||
}
|
||||
case JSType::JS_API_TREE_MAP: {
|
||||
// 1 : 1 dump fileds number
|
||||
CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPITreeMap::SIZE, 1)
|
||||
|
253
ecmascript/tests/js_api_plain_array_test.cpp
Normal file
253
ecmascript/tests/js_api_plain_array_test.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/js_api_plain_array.h"
|
||||
#include "ecmascript/containers/containers_private.h"
|
||||
#include "ecmascript/ecma_string.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_api_plain_array_iterator.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_iterator.h"
|
||||
#include "ecmascript/js_object-inl.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda;
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
|
||||
namespace panda::test {
|
||||
class JSAPIPlainArrayTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
||||
}
|
||||
|
||||
PandaVM *instance {nullptr};
|
||||
ecmascript::EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
|
||||
protected:
|
||||
JSAPIPlainArray *CreatePlainArray()
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
|
||||
JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
|
||||
JSHandle<JSTaggedValue> value =
|
||||
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
|
||||
|
||||
auto objCallInfo =
|
||||
TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
|
||||
objCallInfo->SetFunction(JSTaggedValue::Undefined());
|
||||
objCallInfo->SetThis(value.GetTaggedValue());
|
||||
objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::PlainArray)));
|
||||
|
||||
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get());
|
||||
JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo.get());
|
||||
TestHelper::TearDownFrame(thread, prev);
|
||||
|
||||
JSHandle<JSTaggedValue> constructor(thread, result);
|
||||
JSHandle<JSAPIPlainArray> plainArray(
|
||||
factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
|
||||
JSHandle<JSTaggedValue> keyArray = JSHandle<JSTaggedValue>(factory->NewTaggedArray(8)); // 8 means the value
|
||||
JSHandle<JSTaggedValue> valueArray = JSHandle<JSTaggedValue>(factory->NewTaggedArray(8)); // 8 means the value
|
||||
plainArray->SetKeys(thread, keyArray);
|
||||
plainArray->SetValues(thread, valueArray);
|
||||
return *plainArray;
|
||||
}
|
||||
};
|
||||
|
||||
HWTEST_F_L0(JSAPIPlainArrayTest, PlainArrayCreate)
|
||||
{
|
||||
JSAPIPlainArray *plainArray = CreatePlainArray();
|
||||
EXPECT_TRUE(plainArray != nullptr);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSAPIPlainArrayTest, PA_AddAndGetKeyAtAndClear)
|
||||
{
|
||||
constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
||||
|
||||
// test JSAPIPlainArray
|
||||
JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
|
||||
std::string myValue("myvalue");
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
uint32_t ikey = 100 + i;
|
||||
std::string ivalue = myValue + std::to_string(i);
|
||||
|
||||
key.Update(JSTaggedValue(ikey));
|
||||
value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
|
||||
|
||||
JSAPIPlainArray::Add(thread, array, key, value);
|
||||
}
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
uint32_t ikey = 100 + i;
|
||||
std::string ivalue = myValue + std::to_string(i);
|
||||
key.Update(JSTaggedValue(ikey));
|
||||
value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
|
||||
|
||||
// test getKeyAt
|
||||
JSTaggedValue gvalue = array->GetKeyAt(i);
|
||||
EXPECT_EQ(gvalue, key.GetTaggedValue());
|
||||
}
|
||||
// test clear
|
||||
array->Clear(thread);
|
||||
EXPECT_EQ(array->GetSize(), 0); // 0 means the value
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSAPIPlainArrayTest, PA_CloneAndHasAndGet)
|
||||
{
|
||||
constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
||||
|
||||
// test JSAPIPlainArray
|
||||
JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
|
||||
std::string myValue("myvalue");
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
uint32_t ikey = 100 + i;
|
||||
std::string ivalue = myValue + std::to_string(i);
|
||||
key.Update(JSTaggedValue(ikey));
|
||||
value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
|
||||
JSAPIPlainArray::Add(thread, array, key, value);
|
||||
}
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
|
||||
// test clone
|
||||
JSHandle<JSAPIPlainArray> newArray(thread, CreatePlainArray());
|
||||
EXPECT_EQ(newArray->GetSize(), 0); // 0 means the value
|
||||
newArray = JSAPIPlainArray::Clone(thread, array);
|
||||
EXPECT_EQ(newArray->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
|
||||
// test has
|
||||
key.Update(JSTaggedValue(103)); // 103 means the value
|
||||
int32_t lkey = 103;
|
||||
bool result = array->Has(lkey);
|
||||
EXPECT_TRUE(result);
|
||||
|
||||
// test get
|
||||
myValue = std::string("myvalue3");
|
||||
value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
|
||||
EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, array->Get(key.GetTaggedValue())), value));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom)
|
||||
{
|
||||
constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
||||
|
||||
JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
|
||||
EXPECT_TRUE(array->IsEmpty());
|
||||
std::string myValue("myvalue");
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
uint32_t ikey = 100 + i;
|
||||
std::string ivalue = myValue + std::to_string(i);
|
||||
key.Update(JSTaggedValue(ikey));
|
||||
value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
|
||||
JSAPIPlainArray::Add(thread, array, key, value);
|
||||
}
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
EXPECT_FALSE(array->IsEmpty());
|
||||
|
||||
value.Update(JSTaggedValue(103)); // 103 means the value
|
||||
int32_t lvalue = 103;
|
||||
JSTaggedValue value2 = array->GetIndexOfKey(lvalue);
|
||||
EXPECT_EQ(value2.GetNumber(), 3); // 3 means the value
|
||||
|
||||
myValue = "myvalue2";
|
||||
value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
|
||||
JSTaggedValue value3 = array->GetIndexOfValue(value.GetTaggedValue());
|
||||
EXPECT_EQ(value3.GetNumber(), 2); // 2 means the value
|
||||
|
||||
value.Update(JSTaggedValue(1));
|
||||
int32_t batchSize = 3; // 3 means the value
|
||||
lvalue = 1;
|
||||
value3 = array->RemoveRangeFrom(thread, lvalue, batchSize);
|
||||
EXPECT_EQ(value3.GetNumber(), 3); // 3 means the value
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 3));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSAPIPlainArrayTest, PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt)
|
||||
{
|
||||
constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
|
||||
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
||||
|
||||
JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
|
||||
EXPECT_TRUE(array->IsEmpty());
|
||||
std::string myValue("myvalue");
|
||||
for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
|
||||
uint32_t ikey = 100 + i;
|
||||
std::string ivalue = myValue + std::to_string(i);
|
||||
key.Update(JSTaggedValue(ikey));
|
||||
value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
|
||||
JSAPIPlainArray::Add(thread, array, key, value);
|
||||
}
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
|
||||
EXPECT_FALSE(array->IsEmpty());
|
||||
|
||||
// test Remove
|
||||
myValue = "myvalue2";
|
||||
value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
|
||||
JSTaggedValue taggedValue =
|
||||
array->Remove(thread, JSTaggedValue(102)); // 102 means the value
|
||||
EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
|
||||
|
||||
// test RemoveAt
|
||||
myValue = "myvalue4";
|
||||
value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
|
||||
taggedValue =
|
||||
array->RemoveAt(thread, JSTaggedValue(3)); // 3 means the value
|
||||
EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
|
||||
EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 2));
|
||||
|
||||
// test SetValueAt
|
||||
myValue = "myvalue14";
|
||||
value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
|
||||
array->SetValueAt(thread, JSTaggedValue(3), value.GetTaggedValue()); // 3 means the value
|
||||
int32_t lvalue = 3; // 3 means the value
|
||||
taggedValue = array->GetValueAt(lvalue);
|
||||
EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
|
||||
}
|
||||
} // namespace panda::test
|
Loading…
Reference in New Issue
Block a user