mirror of
https://github.com/openharmony/ark_js_runtime.git
synced 2026-07-19 19:43:48 -04:00
1.add arraylist and ArkPrivate. 2.add special container in stub. 3.fix Switch
Signed-off-by: xliu <liuxin259@huawei.com> Change-Id: I4082326fa075bce0c5c7bf8e6873282086fe5d6e
This commit is contained in:
@@ -281,6 +281,8 @@ ecma_source = [
|
||||
"ecmascript/builtins/builtins_weak_map.cpp",
|
||||
"ecmascript/builtins/builtins_weak_set.cpp",
|
||||
"ecmascript/class_linker/panda_file_translator.cpp",
|
||||
"ecmascript/containers/containers_arraylist.cpp",
|
||||
"ecmascript/containers/containers_private.cpp",
|
||||
"ecmascript/cpu_profiler/cpu_profiler.cpp",
|
||||
"ecmascript/cpu_profiler/profile_processor.cpp",
|
||||
"ecmascript/cpu_profiler/profile_generator.cpp",
|
||||
@@ -318,6 +320,7 @@ ecma_source = [
|
||||
"ecmascript/js_array.cpp",
|
||||
"ecmascript/js_array_iterator.cpp",
|
||||
"ecmascript/js_arraybuffer.cpp",
|
||||
"ecmascript/js_arraylist.cpp",
|
||||
"ecmascript/js_async_function.cpp",
|
||||
"ecmascript/js_dataview.cpp",
|
||||
"ecmascript/js_date.cpp",
|
||||
|
||||
+34
-3
@@ -54,9 +54,11 @@
|
||||
#include "ecmascript/builtins/builtins_typedarray.h"
|
||||
#include "ecmascript/builtins/builtins_weak_map.h"
|
||||
#include "ecmascript/builtins/builtins_weak_set.h"
|
||||
#include "ecmascript/containers/containers_private.h"
|
||||
#include "ecmascript/ecma_runtime_call_info.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_async_function.h"
|
||||
#include "ecmascript/js_collator.h"
|
||||
@@ -132,6 +134,7 @@ using RelativeTimeFormat = builtins::BuiltinsRelativeTimeFormat;
|
||||
using NumberFormat = builtins::BuiltinsNumberFormat;
|
||||
using Collator = builtins::BuiltinsCollator;
|
||||
using PluralRules = builtins::BuiltinsPluralRules;
|
||||
using ContainersPrivate = containers::ContainersPrivate;
|
||||
|
||||
void Builtins::Initialize(const JSHandle<GlobalEnv> &env, JSThread *thread)
|
||||
{
|
||||
@@ -306,9 +309,14 @@ void Builtins::InitializeGlobalObject(const JSHandle<GlobalEnv> &env, const JSHa
|
||||
|
||||
JSRuntimeOptions options = vm_->GetJSOptions();
|
||||
if (options.IsEnableArkTools()) {
|
||||
SetConstant(globalObject, "ArkTools", InitializeArkTools(env).GetTaggedValue());
|
||||
JSHandle<JSTaggedValue> arkTools(InitializeArkTools(env));
|
||||
SetConstantObject(globalObject, "ArkTools", arkTools);
|
||||
}
|
||||
|
||||
// Set ArkPrivate
|
||||
JSHandle<JSTaggedValue> arkPrivate(InitializeArkPrivate(env));
|
||||
SetConstantObject(globalObject, "ArkPrivate", arkPrivate);
|
||||
|
||||
// Global object function
|
||||
SetFunction(env, globalObject, "eval", Global::NotSupportEval, FunctionLength::ONE);
|
||||
SetFunction(env, globalObject, "isFinite", Global::IsFinite, FunctionLength::ONE);
|
||||
@@ -2211,6 +2219,15 @@ void Builtins::SetFunction(const JSHandle<GlobalEnv> &env, const JSHandle<JSObje
|
||||
JSObject::DefineOwnProperty(thread_, obj, key, descriptor);
|
||||
}
|
||||
|
||||
void Builtins::SetFrozenFunction(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj, const char *key,
|
||||
EcmaEntrypoint func, int length) const
|
||||
{
|
||||
JSHandle<JSTaggedValue> keyString(factory_->NewFromString(key));
|
||||
JSHandle<JSFunction> function = NewFunction(env, keyString, func, length);
|
||||
PropertyDescriptor descriptor(thread_, JSHandle<JSTaggedValue>(function), false, false, false);
|
||||
JSObject::DefineOwnProperty(thread_, obj, keyString, descriptor);
|
||||
}
|
||||
|
||||
template<int flag>
|
||||
void Builtins::SetFunctionAtSymbol(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj,
|
||||
const JSHandle<JSTaggedValue> &symbol, const char *name, EcmaEntrypoint func,
|
||||
@@ -2274,6 +2291,14 @@ void Builtins::SetConstant(const JSHandle<JSObject> &obj, const char *key, JSTag
|
||||
PropertyDescriptor descriptor(thread_, JSHandle<JSTaggedValue>(thread_, value), false, false, false);
|
||||
JSObject::DefineOwnProperty(thread_, obj, keyString, descriptor);
|
||||
}
|
||||
|
||||
void Builtins::SetConstantObject(const JSHandle<JSObject> &obj, const char *key, JSHandle<JSTaggedValue> &value) const
|
||||
{
|
||||
JSHandle<JSTaggedValue> keyString(factory_->NewFromString(key));
|
||||
PropertyDescriptor descriptor(thread_, value, false, false, false);
|
||||
JSObject::DefineOwnProperty(thread_, obj, keyString, descriptor);
|
||||
}
|
||||
|
||||
void Builtins::SetGlobalThis(const JSHandle<JSObject> &obj, const char *key, const JSHandle<JSTaggedValue> &globalValue)
|
||||
{
|
||||
JSHandle<JSTaggedValue> keyString(factory_->NewFromString(key));
|
||||
@@ -2734,10 +2759,16 @@ void Builtins::InitializePluralRules(const JSHandle<GlobalEnv> &env)
|
||||
|
||||
JSHandle<JSObject> Builtins::InitializeArkTools(const JSHandle<GlobalEnv> &env) const
|
||||
{
|
||||
[[maybe_unused]] EcmaHandleScope scope(thread_);
|
||||
|
||||
JSHandle<JSObject> tools = factory_->NewEmptyJSObject();
|
||||
SetFunction(env, tools, "print", builtins::BuiltinsArkTools::ObjectDump, FunctionLength::ZERO);
|
||||
return tools;
|
||||
}
|
||||
|
||||
JSHandle<JSObject> Builtins::InitializeArkPrivate(const JSHandle<GlobalEnv> &env) const
|
||||
{
|
||||
JSHandle<JSObject> arkPrivate = factory_->NewEmptyJSObject();
|
||||
SetFrozenFunction(env, arkPrivate, "Load", ContainersPrivate::Load, FunctionLength::ZERO);
|
||||
SetConstant(arkPrivate, "ArrayList", JSTaggedValue(static_cast<int>(containers::ContainerTag::ArrayList)));
|
||||
return arkPrivate;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
@@ -209,6 +209,10 @@ private:
|
||||
void SetGetter(const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
|
||||
const JSHandle<JSTaggedValue> &getter) const;
|
||||
JSHandle<JSObject> InitializeArkTools(const JSHandle<GlobalEnv> &env) const;
|
||||
JSHandle<JSObject> InitializeArkPrivate(const JSHandle<GlobalEnv> &env) const;
|
||||
void SetConstantObject(const JSHandle<JSObject> &obj, const char *key, JSHandle<JSTaggedValue> &value) const;
|
||||
void SetFrozenFunction(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj, const char *key,
|
||||
EcmaEntrypoint func, int length) const;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_BUILTINS_H
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace panda::ecmascript::builtins {
|
||||
class BuiltinsArkTools : public base::BuiltinsBase {
|
||||
public:
|
||||
// Make sure the ECMASCRIPT_OBJECT_DUMP in config.h has been opened before use it
|
||||
// Use through arkTools.print(msg, [obj1, obj2, ... objn]) in js
|
||||
// Use through ArkTools.print(msg, [obj1, obj2, ... objn]) in js
|
||||
static JSTaggedValue ObjectDump(EcmaRuntimeCallInfo *msg);
|
||||
};
|
||||
} // namespace panda::ecmascript::builtins
|
||||
|
||||
@@ -155,7 +155,7 @@ GateRef CircuitBuilder::NewIfFalse(GateRef ifBranch)
|
||||
return circuit_->NewGate(OpCode(OpCode::IF_FALSE), 0, { ifBranch }, TypeCode::NOTYPE);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::NewSwitchCase(GateRef switchBranch, int32_t value)
|
||||
GateRef CircuitBuilder::NewSwitchCase(GateRef switchBranch, int64_t value)
|
||||
{
|
||||
return circuit_->NewGate(OpCode(OpCode::SWITCH_CASE), value, { switchBranch }, TypeCode::NOTYPE);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
GateRef LoopEnd(GateRef state);
|
||||
GateRef NewIfTrue(GateRef ifBranch);
|
||||
GateRef NewIfFalse(GateRef ifBranch);
|
||||
GateRef NewSwitchCase(GateRef switchBranch, int32_t value);
|
||||
GateRef NewSwitchCase(GateRef switchBranch, int64_t value);
|
||||
GateRef NewDefaultCase(GateRef switchBranch);
|
||||
GateRef NewLoadGate(MachineType type, GateRef val, GateRef depend);
|
||||
GateRef NewStoreGate(MachineType type, GateRef ptr, GateRef val, GateRef depend);
|
||||
@@ -89,4 +89,4 @@ private:
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
#endif // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
|
||||
#endif // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
|
||||
|
||||
@@ -47,4 +47,4 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "++++++++++++++++++++++++++++++++++"
|
||||
echo "++++++++++++++++++++++++++++++++++"
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace panda::ecmascript::kungfu {
|
||||
V(CallGetter2, 4) \
|
||||
V(CallInternalGetter, 3) \
|
||||
V(ThrowTypeError, 2) \
|
||||
V(JSArrayListSetByIndex, 4) \
|
||||
V(JSProxySetProperty, 6) \
|
||||
V(GetHash32, 2) \
|
||||
V(FindElementWithCache, 4) \
|
||||
|
||||
@@ -1349,4 +1349,4 @@ bool OpCode::IsNop() const
|
||||
{
|
||||
return (op_ == OpCode::NOP);
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
@@ -1013,13 +1013,14 @@ void LLVMIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector<G
|
||||
}
|
||||
LLVMValueRef result = LLVMBuildSwitch(builder_, cond, llvmDefaultOutBB, caseNum - 1);
|
||||
LLVMBasicBlockRef llvmCurOutBB = nullptr;
|
||||
for (int i = 0; i < static_cast<int>(caseNum - 1); i++) {
|
||||
for (int i = 0; i < static_cast<int>(caseNum); i++) {
|
||||
if (circuit_->GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) {
|
||||
continue;
|
||||
}
|
||||
curOutBB = EnsureBasicBlock(instIdMapBbId_[circuit_->GetId(outList[i])]);
|
||||
llvmCurOutBB = curOutBB->GetImpl<LLVMTFBuilderBasicBlockImpl>()->llvm_bb_;
|
||||
LLVMAddCase(result, LLVMConstInt(LLVMInt64Type(), circuit_->GetBitField(outList[i]), 0), llvmCurOutBB);
|
||||
LLVMAddCase(result, LLVMConstInt(ConvertLLVMTypeFromGate(input), circuit_->GetBitField(outList[i]), 0),
|
||||
llvmCurOutBB);
|
||||
}
|
||||
EndCurrentBlock();
|
||||
gateToLLVMMaps_[gate] = result;
|
||||
|
||||
@@ -1360,32 +1360,6 @@ GateRef Stub::GetValueFromTaggedArray(MachineType returnType, GateRef array, Gat
|
||||
return Load(returnType, array, dataOffset);
|
||||
}
|
||||
|
||||
GateRef Stub::GetElementRepresentation(GateRef hClass)
|
||||
{
|
||||
GateRef bitfieldOffset = GetArchRelateConstant(JSHClass::BIT_FIELD_OFFSET);
|
||||
GateRef bitfield = Load(MachineType::UINT32, hClass, bitfieldOffset);
|
||||
return Word32And(
|
||||
Word32LSR(bitfield, GetInt32Constant(JSHClass::ElementRepresentationBits::START_BIT)),
|
||||
GetInt32Constant(((1LLU << JSHClass::ElementRepresentationBits::SIZE) - 1)));
|
||||
}
|
||||
|
||||
void Stub::SetElementRepresentation(GateRef glue, GateRef hClass, GateRef value)
|
||||
{
|
||||
GateRef bitfieldOffset = GetArchRelateConstant(JSHClass::BIT_FIELD_OFFSET);
|
||||
GateRef oldValue = Load(MachineType::UINT32, hClass, bitfieldOffset);
|
||||
GateRef oldWithMask = Word32And(oldValue,
|
||||
GetInt32Constant(~static_cast<int32_t>(JSHClass::ElementRepresentationBits::Mask())));
|
||||
GateRef newValue = Word32LSR(value, GetInt32Constant(JSHClass::ElementRepresentationBits::START_BIT));
|
||||
Store(MachineType::UINT32, glue, hClass, bitfieldOffset, Word32Or(oldWithMask, newValue));
|
||||
}
|
||||
|
||||
void Stub::UpdateAndStoreRepresention(GateRef glue, GateRef hClass, GateRef value)
|
||||
{
|
||||
GateRef rep = GetElementRepresentation(hClass);
|
||||
GateRef newRep = UpdateRepresention(rep, value);
|
||||
SetElementRepresentation(glue, hClass, newRep);
|
||||
}
|
||||
|
||||
void Stub::UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index, GateRef value, GateRef attr)
|
||||
{
|
||||
GateRef arrayIndex =
|
||||
@@ -1407,6 +1381,13 @@ GateRef Stub::IsSpecialIndexedObj(GateRef jsType)
|
||||
return Int32GreaterThan(jsType, GetInt32Constant(static_cast<int32_t>(JSType::JS_ARRAY)));
|
||||
}
|
||||
|
||||
GateRef Stub::IsSpecialContainer(GateRef jsType)
|
||||
{
|
||||
return TruncInt32ToInt1(Word32And(
|
||||
ZExtInt1ToInt32(Int32GreaterThanOrEqual(jsType, GetInt32Constant(static_cast<int32_t>(JSType::JS_ARRAY_LIST)))),
|
||||
ZExtInt1ToInt32(Int32LessThanOrEqual(jsType, GetInt32Constant(static_cast<int32_t>(JSType::JS_QUEUE))))));
|
||||
}
|
||||
|
||||
GateRef Stub::IsAccessorInternal(GateRef value)
|
||||
{
|
||||
return Word32Equal(GetObjectType(LoadHClass(value)),
|
||||
|
||||
+188
-105
@@ -16,6 +16,7 @@
|
||||
#include "ecmascript/compiler/stub.h"
|
||||
#include "ecmascript/compiler/llvm_ir_builder.h"
|
||||
#include "ecmascript/compiler/stub-inl.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_object.h"
|
||||
#include "ecmascript/tagged_hash_table-inl.h"
|
||||
#include "libpandabase/macros.h"
|
||||
@@ -306,7 +307,7 @@ void Stub::Branch(GateRef condition, Label *trueLabel, Label *falseLabel)
|
||||
env_.SetCurrentLabel(nullptr);
|
||||
}
|
||||
|
||||
void Stub::Switch(GateRef index, Label *defaultLabel, int32_t *keysValue, Label *keysLabel, int numberOfKeys)
|
||||
void Stub::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
|
||||
{
|
||||
auto currentLabel = env_.GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
@@ -1138,102 +1139,6 @@ GateRef Stub::TaggedToRepresentation(GateRef value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef Stub::UpdateRepresention(GateRef oldRep, GateRef value)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->PushCurrentLabel(&entry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(resultRep, MachineType::INT64, oldRep);
|
||||
Label isMixedRep(env);
|
||||
Label notMiexedRep(env);
|
||||
Branch(Word64Equal(oldRep, GetWord64Constant(static_cast<int64_t>(Representation::MIXED))),
|
||||
&isMixedRep, ¬MiexedRep);
|
||||
Bind(&isMixedRep);
|
||||
Jump(&exit);
|
||||
Bind(¬MiexedRep);
|
||||
{
|
||||
GateRef newRep = TaggedToRepresentation(value);
|
||||
Label isNoneRep(env);
|
||||
Label notNoneRep(env);
|
||||
Branch(Word64Equal(oldRep, GetWord64Constant(static_cast<int64_t>(Representation::NONE))),
|
||||
&isNoneRep, ¬NoneRep);
|
||||
Bind(&isNoneRep);
|
||||
{
|
||||
resultRep = newRep;
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬NoneRep);
|
||||
{
|
||||
Label isEqaulNewRep(env);
|
||||
Label notEqaualNewRep(env);
|
||||
Branch(Word64NotEqual(oldRep, newRep), &isEqaulNewRep, ¬EqaualNewRep);
|
||||
Bind(&isEqaulNewRep);
|
||||
{
|
||||
resultRep = newRep;
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬EqaualNewRep);
|
||||
{
|
||||
Label defaultLabel(env);
|
||||
Label intLabel(env);
|
||||
Label doubleLabel(env);
|
||||
Label numberLabel(env);
|
||||
Label objectLabel(env);
|
||||
// 4 : 4 means that there are 4 args in total.
|
||||
std::array<Label, 4> repCaseLabels = {
|
||||
intLabel,
|
||||
doubleLabel,
|
||||
numberLabel,
|
||||
objectLabel,
|
||||
};
|
||||
// 4 : 4 means that there are 4 args in total.
|
||||
std::array<int32_t, 4> keyValues = {
|
||||
static_cast<int32_t>(Representation::INT),
|
||||
static_cast<int32_t>(Representation::DOUBLE),
|
||||
static_cast<int32_t>(Representation::NUMBER),
|
||||
static_cast<int32_t>(Representation::OBJECT),
|
||||
};
|
||||
// 4 : 4 means that there are 4 cases in total.
|
||||
Switch(oldRep, &defaultLabel, keyValues.data(), repCaseLabels.data(), 4);
|
||||
Bind(&intLabel);
|
||||
Jump(&numberLabel);
|
||||
Bind(&doubleLabel);
|
||||
Jump(&numberLabel);
|
||||
Bind(&numberLabel);
|
||||
{
|
||||
Label isObjectNewRep(env);
|
||||
Label notObjectNewRep(env);
|
||||
Branch(Word64NotEqual(newRep, GetWord64Constant(
|
||||
static_cast<int32_t>(Representation::OBJECT))),
|
||||
¬ObjectNewRep, &isObjectNewRep);
|
||||
Bind(¬ObjectNewRep);
|
||||
{
|
||||
resultRep = GetWord64Constant(static_cast<int32_t>(Representation::NUMBER));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&isObjectNewRep);
|
||||
{
|
||||
resultRep = GetWord64Constant(static_cast<int32_t>(Representation::MIXED));
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(&objectLabel);
|
||||
{
|
||||
resultRep = GetWord64Constant(static_cast<int32_t>(Representation::MIXED));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&defaultLabel);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *resultRep;
|
||||
env->PopCurrentLabel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef Stub::Store(MachineType type, GateRef glue, GateRef base, GateRef offset, GateRef value)
|
||||
{
|
||||
auto depend = env_.GetCurrentLabel()->GetDepend();
|
||||
@@ -2023,8 +1928,20 @@ GateRef Stub::GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index)
|
||||
Branch(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed);
|
||||
Bind(&isSpecialIndexed);
|
||||
{
|
||||
result = GetHoleConstant();
|
||||
Jump(&exit);
|
||||
Label isSpecialContainer(env);
|
||||
Label notSpecialContainer(env);
|
||||
// Add SpecialContainer
|
||||
Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
|
||||
Bind(&isSpecialContainer);
|
||||
{
|
||||
result = GetContainerProperty(glue, *holder, index, jsType);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SpecialContainer);
|
||||
{
|
||||
result = GetHoleConstant();
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(¬SpecialIndexed);
|
||||
{
|
||||
@@ -2402,8 +2319,22 @@ GateRef Stub::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index,
|
||||
Label notSpecialIndex(env);
|
||||
Branch(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
|
||||
Bind(&isSpecialIndex);
|
||||
returnValue = GetHoleConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
{
|
||||
Label isSpecialContainer(env);
|
||||
Label notSpecialContainer(env);
|
||||
// Add SpecialContainer
|
||||
Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
|
||||
Bind(&isSpecialContainer);
|
||||
{
|
||||
returnValue = SetContainerProperty(glue, *holder, index, value, jsType);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SpecialContainer);
|
||||
{
|
||||
returnValue = GetHoleConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(¬SpecialIndex);
|
||||
{
|
||||
GateRef elements = GetElementsArray(*holder);
|
||||
@@ -2510,8 +2441,25 @@ GateRef Stub::SetPropertyByName(GateRef glue, GateRef receiver, GateRef key, Gat
|
||||
// if branch condition : IsSpecialIndexedObj(jsType)
|
||||
Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
|
||||
Bind(&isSIndexObj);
|
||||
result = GetHoleConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
{
|
||||
Label isSpecialContainer(env);
|
||||
Label notSpecialContainer(env);
|
||||
// Add SpecialContainer
|
||||
Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
|
||||
Bind(&isSpecialContainer);
|
||||
{
|
||||
GateRef taggedId = GetInt32Constant(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
|
||||
CallRuntime(GET_STUBDESCRIPTOR(ThrowTypeError), glue, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)),
|
||||
{glue, taggedId});
|
||||
result = GetExceptionConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SpecialContainer);
|
||||
{
|
||||
result = GetHoleConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(¬SIndexObj);
|
||||
{
|
||||
Label isDicMode(env);
|
||||
@@ -2730,8 +2678,25 @@ GateRef Stub::SetPropertyByNameWithOwn(GateRef glue, GateRef receiver, GateRef k
|
||||
// if branch condition : IsSpecialIndexedObj(jsType)
|
||||
Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
|
||||
Bind(&isSIndexObj);
|
||||
result = GetHoleConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
{
|
||||
Label isSpecialContainer(env);
|
||||
Label notSpecialContainer(env);
|
||||
// Add SpecialContainer
|
||||
Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
|
||||
Bind(&isSpecialContainer);
|
||||
{
|
||||
GateRef taggedId = GetInt32Constant(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
|
||||
CallRuntime(GET_STUBDESCRIPTOR(ThrowTypeError), glue, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)),
|
||||
{glue, taggedId});
|
||||
result = GetExceptionConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SpecialContainer);
|
||||
{
|
||||
result = GetHoleConstant(MachineType::UINT64);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(¬SIndexObj);
|
||||
{
|
||||
Label isDicMode(env);
|
||||
@@ -2949,4 +2914,122 @@ void Stub::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef newHClas
|
||||
env->PopCurrentLabel();
|
||||
return;
|
||||
}
|
||||
|
||||
GateRef Stub::GetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef jsType)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->PushCurrentLabel(&entry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(result, MachineType::TAGGED, GetUndefinedConstant());
|
||||
|
||||
Label arrayListLabel(env);
|
||||
Label queueLabel(env);
|
||||
Label defaultLabel(env);
|
||||
std::array<Label, 2> repCaseLabels = { // 2 : 2 means that there are 2 args in total.
|
||||
arrayListLabel,
|
||||
queueLabel,
|
||||
};
|
||||
std::array<int64_t, 2> keyValues = { // 2 : 2 means that there are 2 args in total.
|
||||
static_cast<int64_t>(JSType::JS_ARRAY_LIST),
|
||||
static_cast<int64_t>(JSType::JS_QUEUE),
|
||||
};
|
||||
// 2 : 2 means that there are 2 cases.
|
||||
Switch(ZExtInt32ToInt64(jsType), &defaultLabel, keyValues.data(), repCaseLabels.data(), 2);
|
||||
Bind(&arrayListLabel);
|
||||
{
|
||||
result = JSArrayListGet(glue, receiver, index);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&queueLabel);
|
||||
{
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&defaultLabel);
|
||||
{
|
||||
Jump(&exit);
|
||||
}
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->PopCurrentLabel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef Stub::JSArrayListGet(GateRef glue, GateRef receiver, GateRef index)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->PushCurrentLabel(&entry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(result, MachineType::TAGGED, GetUndefinedConstant());
|
||||
|
||||
GateRef lengthOffset = GetArchRelateConstant(panda::ecmascript::JSArrayList::LENGTH_OFFSET);
|
||||
GateRef length = TaggedCastToInt32(Load(MachineType::UINT64, receiver, lengthOffset));
|
||||
Label isVailedIndex(env);
|
||||
Label notValidIndex(env);
|
||||
Branch(TruncInt32ToInt1(Word32And(ZExtInt1ToInt32(Int32GreaterThanOrEqual(index, GetInt32Constant(0))),
|
||||
ZExtInt1ToInt32(Int32LessThan(index, length)))), &isVailedIndex, ¬ValidIndex);
|
||||
Bind(&isVailedIndex);
|
||||
{
|
||||
GateRef elements = GetElementsArray(receiver);
|
||||
result = GetValueFromTaggedArray(MachineType::TAGGED, elements, index);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬ValidIndex);
|
||||
{
|
||||
GateRef taggedId = GetInt32Constant(GET_MESSAGE_STRING_ID(GetPropertyOutOfBounds));
|
||||
CallRuntime(GET_STUBDESCRIPTOR(ThrowTypeError), glue, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)),
|
||||
{glue, taggedId});
|
||||
result = GetExceptionConstant();
|
||||
Jump(&exit);
|
||||
}
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->PopCurrentLabel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef Stub::SetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef jsType)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->PushCurrentLabel(&entry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(result, MachineType::UINT64, GetUndefinedConstant(MachineType::UINT64));
|
||||
Label arrayListLabel(env);
|
||||
Label queueLabel(env);
|
||||
Label defaultLabel(env);
|
||||
std::array<Label, 2> repCaseLabels = { // 2 : 2 means that there are 2 args in total.
|
||||
arrayListLabel,
|
||||
queueLabel,
|
||||
};
|
||||
std::array<int64_t, 2> keyValues = { // 2 : 2 means that there are 2 args in total.
|
||||
static_cast<int64_t>(JSType::JS_ARRAY_LIST),
|
||||
static_cast<int64_t>(JSType::JS_QUEUE),
|
||||
};
|
||||
// 2 : 2 means that there are 2 cases.
|
||||
Switch(ZExtInt32ToInt64(jsType), &defaultLabel, keyValues.data(), repCaseLabels.data(), 2);
|
||||
Bind(&arrayListLabel);
|
||||
{
|
||||
StubDescriptor *jsarraylistSetByIndex = GET_STUBDESCRIPTOR(JSArrayListSetByIndex);
|
||||
CallRuntime(jsarraylistSetByIndex, glue, GetWord64Constant(FAST_STUB_ID(JSArrayListSetByIndex)),
|
||||
{ glue, receiver, index, value });
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&queueLabel);
|
||||
{
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&defaultLabel);
|
||||
{
|
||||
Jump(&exit);
|
||||
}
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->PopCurrentLabel();
|
||||
return ret;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
@@ -450,7 +450,7 @@ public:
|
||||
inline void Bind(Label *label);
|
||||
void Jump(Label *label);
|
||||
void Branch(GateRef condition, Label *trueLabel, Label *falseLabel);
|
||||
void Switch(GateRef index, Label *defaultLabel, int32_t *keysValue, Label *keysLabel, int numberOfKeys);
|
||||
void Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys);
|
||||
void Seal(Label *label)
|
||||
{
|
||||
label->Seal();
|
||||
@@ -638,13 +638,10 @@ public:
|
||||
void ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val);
|
||||
inline GateRef GetValueFromTaggedArray(MachineType returnType, GateRef elements, GateRef index);
|
||||
inline void SetValueToTaggedArray(MachineType valType, GateRef glue, GateRef array, GateRef index, GateRef val);
|
||||
inline GateRef GetElementRepresentation(GateRef hClass);
|
||||
inline void SetElementRepresentation(GateRef glue, GateRef hClass, GateRef value);
|
||||
inline void UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index, GateRef value, GateRef attr);
|
||||
inline GateRef IsSpecialIndexedObj(GateRef jsType);
|
||||
inline GateRef IsSpecialContainer(GateRef jsType);
|
||||
inline GateRef IsAccessorInternal(GateRef value);
|
||||
inline void UpdateAndStoreRepresention(GateRef glue, GateRef hClass, GateRef value);
|
||||
GateRef UpdateRepresention(GateRef oldRep, GateRef value);
|
||||
template<typename DictionaryT = NameDictionary>
|
||||
GateRef GetAttributesFromDictionary(GateRef elements, GateRef entry);
|
||||
template<typename DictionaryT = NameDictionary>
|
||||
@@ -730,6 +727,11 @@ public:
|
||||
GateRef SetPropertyByNameWithOwn(GateRef glue, GateRef receiver, GateRef key,
|
||||
GateRef value); // Do not crawl the prototype chain
|
||||
|
||||
// Add SpecialContainer
|
||||
GateRef GetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef jsType);
|
||||
GateRef SetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef jsType);
|
||||
GateRef JSArrayListGet(GateRef glue, GateRef receiver, GateRef index);
|
||||
|
||||
private:
|
||||
Environment env_;
|
||||
std::string methodName_;
|
||||
|
||||
@@ -720,6 +720,22 @@ CALL_STUB_INIT_DESCRIPTOR(LoopTest1)
|
||||
descriptor->SetStubKind(StubDescriptor::CallStubKind::TEST_FUNC);
|
||||
}
|
||||
|
||||
CALL_STUB_INIT_DESCRIPTOR(JSArrayListSetByIndex)
|
||||
{
|
||||
// 4 : 4 input parameters
|
||||
StubDescriptor arraylistSetByIndex("JSArrayListSetByIndex", 0, 4, ArgumentsOrder::DEFAULT_ORDER, MachineType::NONE);
|
||||
*descriptor = arraylistSetByIndex;
|
||||
// 4 : 4 input parameters
|
||||
std::array<MachineType, 4> params = {
|
||||
MachineType::NATIVE_POINTER,
|
||||
MachineType::TAGGED_POINTER,
|
||||
MachineType::INT32,
|
||||
MachineType::TAGGED,
|
||||
};
|
||||
descriptor->SetParameters(params.data());
|
||||
descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB);
|
||||
}
|
||||
|
||||
void FastStubDescriptors::InitializeStubDescriptors()
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_arraylist.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
|
||||
namespace panda::ecmascript::containers {
|
||||
JSTaggedValue ContainersArrayList::ArrayListConstructor(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
BUILTINS_API_TRACE(argv->GetThread(), ArrayList, Constructor);
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[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);
|
||||
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersArrayList::Add(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
BUILTINS_API_TRACE(argv->GetThread(), ArrayList, Add);
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> self = GetThis(argv);
|
||||
|
||||
if (!self->IsJSArrayList()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSArrayList", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
|
||||
JSArrayList::Add(thread, JSHandle<JSArrayList>::Cast(self), value);
|
||||
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
|
||||
return JSTaggedValue::True();
|
||||
}
|
||||
|
||||
JSTaggedValue ContainersArrayList::Iterator(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
ASSERT(argv);
|
||||
BUILTINS_API_TRACE(argv->GetThread(), ArrayList, Iterator);
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
} // namespace panda::ecmascript::containers
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_ARRAYLIST_H
|
||||
#define ECMASCRIPT_CONTAINERS_CONTAINERS_ARRAYLIST_H
|
||||
|
||||
#include "ecmascript/base/builtins_base.h"
|
||||
#include "ecmascript/ecma_runtime_call_info.h"
|
||||
|
||||
namespace panda::ecmascript::containers {
|
||||
class ContainersArrayList : public base::BuiltinsBase {
|
||||
public:
|
||||
static JSTaggedValue ArrayListConstructor(EcmaRuntimeCallInfo *argv);
|
||||
|
||||
static JSTaggedValue Add(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue Iterator(EcmaRuntimeCallInfo *argv);
|
||||
};
|
||||
} // namespace panda::ecmascript::containers
|
||||
#endif // ECMASCRIPT_CONTAINERS_CONTAINERS_ARRAYLIST_H
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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/containers/containers_private.h"
|
||||
|
||||
#include "containers_arraylist.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/interpreter/fast_runtime_stub-inl.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
|
||||
namespace panda::ecmascript::containers {
|
||||
JSTaggedValue ContainersPrivate::Load(EcmaRuntimeCallInfo *msg)
|
||||
{
|
||||
ASSERT(msg);
|
||||
JSThread *thread = msg->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSTaggedValue> argv = GetCallArg(msg, 0);
|
||||
JSHandle<JSObject> thisValue(GetThis(msg));
|
||||
|
||||
uint32_t tag = 0;
|
||||
if (!JSTaggedValue::ToElementIndex(argv.GetTaggedValue(), &tag) || tag >= ContainerTag::END) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Incorrect input parameters", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSTaggedValue res = JSTaggedValue::Undefined();
|
||||
switch (tag) {
|
||||
case ContainerTag::ArrayList: {
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("ArrayListConstructor"));
|
||||
JSTaggedValue value =
|
||||
FastRuntimeStub::GetPropertyByName<true>(thread, thisValue.GetTaggedValue(), key.GetTaggedValue());
|
||||
if (value != JSTaggedValue::Undefined()) {
|
||||
res = value;
|
||||
} else {
|
||||
JSHandle<JSTaggedValue> arrayList = InitializeArrayList(thread);
|
||||
SetFrozenConstructor(thread, thisValue, "ArrayListConstructor", arrayList);
|
||||
res = arrayList.GetTaggedValue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ContainerTag::Queue:
|
||||
case ContainerTag::END:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
JSHandle<JSFunction> ContainersPrivate::NewContainerConstructor(JSThread *thread, const JSHandle<JSObject> &prototype,
|
||||
EcmaEntrypoint ctorFunc, const char *name, int length)
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSFunction> ctor =
|
||||
factory->NewJSFunction(env, reinterpret_cast<void *>(ctorFunc), FunctionKind::BUILTIN_CONSTRUCTOR);
|
||||
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
JSFunction::SetFunctionLength(thread, ctor, JSTaggedValue(length));
|
||||
JSHandle<JSTaggedValue> nameString(factory->NewFromCanBeCompressString(name));
|
||||
JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(ctor), nameString,
|
||||
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
|
||||
JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
|
||||
PropertyDescriptor descriptor1(thread, JSHandle<JSTaggedValue>::Cast(ctor), true, false, true);
|
||||
JSObject::DefineOwnProperty(thread, prototype, constructorKey, descriptor1);
|
||||
|
||||
/* set "prototype" in constructor */
|
||||
ctor->SetFunctionPrototype(thread, prototype.GetTaggedValue());
|
||||
|
||||
return ctor;
|
||||
}
|
||||
|
||||
void ContainersPrivate::SetFrozenFunction(JSThread *thread, const JSHandle<JSObject> &obj, const char *key,
|
||||
EcmaEntrypoint func, int length)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> keyString(factory->NewFromCanBeCompressString(key));
|
||||
JSHandle<JSFunction> function = NewFunction(thread, keyString, func, length);
|
||||
PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>(function), false, false, false);
|
||||
JSObject::DefineOwnProperty(thread, obj, keyString, descriptor);
|
||||
}
|
||||
|
||||
void ContainersPrivate::SetFrozenConstructor(JSThread *thread, const JSHandle<JSObject> &obj, const char *keyChar,
|
||||
JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
JSObject::PreventExtensions(thread, obj);
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString(keyChar));
|
||||
PropertyDescriptor descriptor(thread, value, false, false, false);
|
||||
JSObject::DefineOwnProperty(thread, obj, key, descriptor);
|
||||
}
|
||||
|
||||
JSHandle<JSFunction> ContainersPrivate::NewFunction(JSThread *thread, const JSHandle<JSTaggedValue> &key,
|
||||
EcmaEntrypoint func, int length)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSFunction> function =
|
||||
factory->NewJSFunction(thread->GetEcmaVM()->GetGlobalEnv(), reinterpret_cast<void *>(func));
|
||||
JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
|
||||
JSHandle<JSFunctionBase> baseFunction(function);
|
||||
JSFunction::SetFunctionName(thread, baseFunction, key, thread->GlobalConstants()->GetHandledUndefined());
|
||||
return function;
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> ContainersPrivate::CreateGetter(JSThread *thread, EcmaEntrypoint func, const char *name,
|
||||
int length)
|
||||
{
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSFunction> function = factory->NewJSFunction(env, reinterpret_cast<void *>(func));
|
||||
JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
|
||||
JSHandle<JSTaggedValue> funcName(factory->NewFromString(name));
|
||||
JSHandle<JSTaggedValue> prefix = thread->GlobalConstants()->GetHandledGetString();
|
||||
JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(function), funcName, prefix);
|
||||
return JSHandle<JSTaggedValue>(function);
|
||||
}
|
||||
|
||||
void ContainersPrivate::SetGetter(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
|
||||
const JSHandle<JSTaggedValue> &getter)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<AccessorData> accessor = factory->NewAccessorData();
|
||||
accessor->SetGetter(thread, getter);
|
||||
PropertyAttributes attr = PropertyAttributes::DefaultAccessor(false, false, false);
|
||||
JSObject::AddAccessor(thread, JSHandle<JSTaggedValue>::Cast(obj), key, accessor, attr);
|
||||
}
|
||||
|
||||
void ContainersPrivate::SetFunctionAtSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
|
||||
const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &symbol,
|
||||
const char *name, EcmaEntrypoint func, int length)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSFunction> function = factory->NewJSFunction(env, reinterpret_cast<void *>(func));
|
||||
JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
|
||||
JSHandle<JSTaggedValue> nameString(factory->NewFromString(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);
|
||||
}
|
||||
|
||||
void ContainersPrivate::SetStringTagSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
|
||||
const JSHandle<JSObject> &obj, const char *key)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> tag(factory->NewFromString(key));
|
||||
JSHandle<JSTaggedValue> symbol = env->GetToStringTagSymbol();
|
||||
PropertyDescriptor desc(thread, tag, false, false, false);
|
||||
JSObject::DefineOwnProperty(thread, obj, symbol, desc);
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> ContainersPrivate::InitializeArrayList(JSThread *thread)
|
||||
{
|
||||
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
// ArrayList.prototype
|
||||
JSHandle<JSObject> arrayListFuncPrototype = factory->NewEmptyJSObject();
|
||||
JSHandle<JSTaggedValue> arrayListFuncPrototypeValue(arrayListFuncPrototype);
|
||||
// ArrayList.prototype_or_dynclass
|
||||
JSHandle<JSHClass> arrayListInstanceDynclass =
|
||||
factory->NewEcmaDynClass(JSArrayList::SIZE, JSType::JS_ARRAY_LIST, arrayListFuncPrototypeValue);
|
||||
// ArrayList() = new Function()
|
||||
JSHandle<JSTaggedValue> arrayListFunction(NewContainerConstructor(
|
||||
thread, arrayListFuncPrototype, ContainersArrayList::ArrayListConstructor, "ArrayList", FuncLength::ZERO));
|
||||
JSHandle<JSFunction>(arrayListFunction)->SetFunctionPrototype(thread, arrayListInstanceDynclass.GetTaggedValue());
|
||||
|
||||
// "constructor" property on the prototype
|
||||
JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(arrayListFuncPrototype), constructorKey, arrayListFunction);
|
||||
|
||||
// ArrayList.prototype.add()
|
||||
SetFrozenFunction(thread, arrayListFuncPrototype, "add", ContainersArrayList::Add, FuncLength::ONE);
|
||||
|
||||
return arrayListFunction;
|
||||
}
|
||||
} // namespace panda::ecmascript::containers
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_PRIVATE_H
|
||||
#define ECMASCRIPT_CONTAINERS_CONTAINERS_PRIVATE_H
|
||||
|
||||
#include "ecmascript/base/builtins_base.h"
|
||||
|
||||
namespace panda::ecmascript::containers {
|
||||
enum FuncLength : uint8_t { ZERO = 0, ONE, TWO, THREE, FOUR };
|
||||
enum ContainerTag : uint8_t { ArrayList = 0, Queue, END };
|
||||
// Using Lazy-loading container, including ArrayList, Queue, Stack, Vector, List, LinkedList, Deque,
|
||||
// TreeMap, TreeSet, HashMap, HashSet, LightWightMap, LightWightSet, PlainArray.
|
||||
// Use through ArkPrivate.Load([ContainerTag]) in js, ContainTag was declaerd in ArkPrivate like ArkPrivate::ArrayList.
|
||||
class ContainersPrivate : public base::BuiltinsBase {
|
||||
public:
|
||||
static JSTaggedValue Load(EcmaRuntimeCallInfo *msg);
|
||||
|
||||
private:
|
||||
static JSHandle<JSFunction> NewContainerConstructor(JSThread *thread, const JSHandle<JSObject> &prototype,
|
||||
EcmaEntrypoint ctorFunc, const char *name, int length);
|
||||
static JSHandle<JSFunction> NewFunction(JSThread *thread, const JSHandle<JSTaggedValue> &key, EcmaEntrypoint func,
|
||||
int length);
|
||||
static void SetFrozenFunction(JSThread *thread, const JSHandle<JSObject> &obj, const char *key, EcmaEntrypoint func,
|
||||
int length);
|
||||
static void SetFrozenConstructor(JSThread *thread, const JSHandle<JSObject> &obj, const char *keyChar,
|
||||
JSHandle<JSTaggedValue> &value);
|
||||
static JSHandle<JSTaggedValue> CreateGetter(JSThread *thread, EcmaEntrypoint func, const char *name,
|
||||
int length);
|
||||
static void SetGetter(JSThread *thread, const JSHandle<JSObject> &obj,
|
||||
const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &getter);
|
||||
static void SetFunctionAtSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
|
||||
const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &symbol,
|
||||
const char *name, EcmaEntrypoint func, int length);
|
||||
static void SetStringTagSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
|
||||
const JSHandle<JSObject> &obj, const char *key);
|
||||
static JSHandle<JSTaggedValue> InitializeArrayList(JSThread *thread);
|
||||
};
|
||||
} // namespace panda::ecmascript::containers
|
||||
|
||||
#endif // ECMASCRIPT_CONTAINERS_CONTAINERS_PRIVATE_H
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_async_function.h"
|
||||
#include "ecmascript/js_collator.h"
|
||||
#include "ecmascript/js_dataview.h"
|
||||
@@ -254,6 +255,8 @@ CString JSHClass::DumpJSType(JSType type)
|
||||
return "EcmaModule";
|
||||
case JSType::CLASS_INFO_EXTRACTOR:
|
||||
return "ClassInfoExtractor";
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
return "ArrayList";
|
||||
default: {
|
||||
CString ret = "unknown type ";
|
||||
return ret + static_cast<char>(type);
|
||||
@@ -597,6 +600,9 @@ static void DumpObject(JSThread *thread, TaggedObject *obj, std::ostream &os)
|
||||
case JSType::CLASS_INFO_EXTRACTOR:
|
||||
ClassInfoExtractor::Cast(obj)->Dump(thread, os);
|
||||
break;
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
JSArrayList::Cast(obj)->Dump(thread, os);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
@@ -1088,6 +1094,12 @@ void JSArray::Dump(JSThread *thread, std::ostream &os) const
|
||||
JSObject::Dump(thread, os);
|
||||
}
|
||||
|
||||
void JSArrayList::Dump(JSThread *thread, std::ostream &os) const
|
||||
{
|
||||
os << " - length: " << std::dec << GetLength().GetArrayLength() << "\n";
|
||||
JSObject::Dump(thread, os);
|
||||
}
|
||||
|
||||
void JSArrayIterator::Dump(JSThread *thread, std::ostream &os) const
|
||||
{
|
||||
JSArray *array = JSArray::Cast(GetIteratedArray().GetTaggedObject());
|
||||
@@ -2139,6 +2151,9 @@ static void DumpObject(JSThread *thread, TaggedObject *obj,
|
||||
case JSType::ECMA_MODULE:
|
||||
EcmaModule::Cast(obj)->DumpForSnapshot(thread, vec);
|
||||
return;
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
JSArrayList::Cast(obj)->DumpForSnapshot(thread, vec);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2486,6 +2501,12 @@ void JSArray::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
JSObject::DumpForSnapshot(thread, vec);
|
||||
}
|
||||
|
||||
void JSArrayList::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
std::vector<std::pair<CString, JSTaggedValue>> &vec) const
|
||||
{
|
||||
JSObject::DumpForSnapshot(thread, vec);
|
||||
}
|
||||
|
||||
void JSArrayIterator::DumpForSnapshot([[maybe_unused]] JSThread *thread,
|
||||
std::vector<std::pair<CString, JSTaggedValue>> &vec) const
|
||||
{
|
||||
|
||||
@@ -339,6 +339,8 @@ CString *HeapSnapShot::GenerateNodeName(JSThread *thread, TaggedObject *entry)
|
||||
return GetString("CompletionRecord");
|
||||
case JSType::ECMA_MODULE:
|
||||
return GetString("EcmaModule");
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
return GetString("ArrayList");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ecmascript/global_dictionary-inl.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/internal_call_params.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_hclass-inl.h"
|
||||
#include "ecmascript/js_proxy.h"
|
||||
@@ -161,6 +162,11 @@ bool FastRuntimeStub::IsSpecialReceiverObj(JSType jsType)
|
||||
return jsType > JSType::JS_PRIMITIVE_REF;
|
||||
}
|
||||
|
||||
bool FastRuntimeStub::IsSpecialContainer(JSType jsType)
|
||||
{
|
||||
return jsType >= JSType::JS_ARRAY_LIST && jsType <= JSType::JS_QUEUE;
|
||||
}
|
||||
|
||||
int32_t FastRuntimeStub::TryToElementsIndex(JSTaggedValue key)
|
||||
{
|
||||
if (LIKELY(key.IsInt())) {
|
||||
@@ -309,6 +315,9 @@ JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValu
|
||||
auto *hclass = holder.GetTaggedObject()->GetClass();
|
||||
JSType jsType = hclass->GetObjectType();
|
||||
if (IsSpecialIndexedObj(jsType)) {
|
||||
if (IsSpecialContainer(jsType)) {
|
||||
return GetContainerProperty(thread, holder, index, jsType);
|
||||
}
|
||||
return JSTaggedValue::Hole();
|
||||
}
|
||||
TaggedArray *elements = TaggedArray::Cast(JSObject::Cast(holder)->GetElements().GetTaggedObject());
|
||||
@@ -437,6 +446,9 @@ JSTaggedValue FastRuntimeStub::SetPropertyByName(JSThread *thread, JSTaggedValue
|
||||
auto *hclass = holder.GetTaggedObject()->GetClass();
|
||||
JSType jsType = hclass->GetObjectType();
|
||||
if (IsSpecialIndexedObj(jsType)) {
|
||||
if (IsSpecialContainer(jsType)) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot set property on Container", JSTaggedValue::Exception());
|
||||
}
|
||||
return JSTaggedValue::Hole();
|
||||
}
|
||||
// UpdateRepresentation
|
||||
@@ -518,6 +530,9 @@ JSTaggedValue FastRuntimeStub::SetPropertyByIndex(JSThread *thread, JSTaggedValu
|
||||
auto *hclass = holder.GetTaggedObject()->GetClass();
|
||||
JSType jsType = hclass->GetObjectType();
|
||||
if (IsSpecialIndexedObj(jsType)) {
|
||||
if (IsSpecialContainer(jsType)) {
|
||||
return SetContainerProperty(thread, holder, index, value, jsType);
|
||||
}
|
||||
return JSTaggedValue::Hole();
|
||||
}
|
||||
TaggedArray *elements = TaggedArray::Cast(JSObject::Cast(holder)->GetElements().GetTaggedObject());
|
||||
@@ -1317,5 +1332,33 @@ JSTaggedValue FastRuntimeStub::HasOwnProperty(JSThread *thread, JSObject *obj, J
|
||||
|
||||
return FastRuntimeStub::FindOwnProperty(thread, obj, key);
|
||||
}
|
||||
|
||||
JSTaggedValue FastRuntimeStub::GetContainerProperty(JSThread *thread, JSTaggedValue receiver, uint32_t index,
|
||||
JSType jsType)
|
||||
{
|
||||
JSTaggedValue res = JSTaggedValue::Undefined();
|
||||
switch (jsType) {
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
res = JSArrayList::Cast(receiver.GetTaggedObject())->Get(thread, index);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
JSTaggedValue FastRuntimeStub::SetContainerProperty(JSThread *thread, JSTaggedValue receiver, uint32_t index,
|
||||
JSTaggedValue value, JSType jsType)
|
||||
{
|
||||
JSTaggedValue res = JSTaggedValue::Undefined();
|
||||
switch (jsType) {
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
res = JSArrayList::Cast(receiver.GetTaggedObject())->Set(thread, index, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_INL_H
|
||||
|
||||
@@ -101,6 +101,7 @@ private:
|
||||
friend class ICRuntimeStub;
|
||||
static inline bool IsSpecialIndexedObj(JSType jsType);
|
||||
static inline bool IsSpecialReceiverObj(JSType jsType);
|
||||
static inline bool IsSpecialContainer(JSType jsType);
|
||||
static inline int32_t TryToElementsIndex(JSTaggedValue key);
|
||||
static inline JSTaggedValue CallGetter(JSThread *thread, JSTaggedValue receiver, JSTaggedValue holder,
|
||||
JSTaggedValue value);
|
||||
@@ -110,6 +111,10 @@ private:
|
||||
PropertyAttributes attr);
|
||||
static inline JSTaggedValue AddPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index,
|
||||
JSTaggedValue value);
|
||||
static inline JSTaggedValue GetContainerProperty(JSThread *thread, JSTaggedValue receiver, uint32_t index,
|
||||
JSType jsType);
|
||||
static inline JSTaggedValue SetContainerProperty(JSThread *thread, JSTaggedValue receiver, uint32_t index,
|
||||
JSTaggedValue value, JSType jsType);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_arraylist.h"
|
||||
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void JSArrayList::Add(JSThread *thread, const JSHandle<JSArrayList> &arrayList, const JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
// GrowCapacity
|
||||
array_size_t length = arrayList->GetLength().GetArrayLength();
|
||||
JSHandle<TaggedArray> elements = GrowCapacity(thread, arrayList, length + 1);
|
||||
|
||||
ASSERT(!elements->IsDictionaryMode());
|
||||
elements->Set(thread, length, value);
|
||||
arrayList->SetLength(thread, JSTaggedValue(++length));
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> JSArrayList::GrowCapacity(const JSThread *thread, const JSHandle<JSArrayList> &obj,
|
||||
array_size_t capacity)
|
||||
{
|
||||
JSHandle<TaggedArray> oldElements(thread, obj->GetElements());
|
||||
array_size_t oldLength = oldElements->GetLength();
|
||||
if (capacity < oldLength) {
|
||||
return oldElements;
|
||||
}
|
||||
array_size_t newCapacity = ComputeCapacity(capacity);
|
||||
JSHandle<TaggedArray> newElements =
|
||||
thread->GetEcmaVM()->GetFactory()->CopyArray(oldElements, oldLength, newCapacity);
|
||||
|
||||
obj->SetElements(thread, newElements);
|
||||
return newElements;
|
||||
}
|
||||
|
||||
JSTaggedValue JSArrayList::Get(JSThread *thread, const uint32_t index)
|
||||
{
|
||||
if (index < 0 || index >= GetLength().GetArrayLength()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Get property index out-of-bounds", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
|
||||
return elements->Get(index);
|
||||
}
|
||||
|
||||
JSTaggedValue JSArrayList::Set(JSThread *thread, const uint32_t index, JSTaggedValue value)
|
||||
{
|
||||
if (index < 0 || index >= GetLength().GetArrayLength()) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Set property index out-of-bounds", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
|
||||
elements->Set(thread, index, value);
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
bool JSArrayList::Delete(JSThread *thread, const JSHandle<JSArrayList> &obj, const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
if (UNLIKELY(JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Can not delete a type other than number", false);
|
||||
}
|
||||
array_size_t length = obj->GetLength().GetArrayLength();
|
||||
if (index < 0 || index >= length) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Delete property index out-of-bounds", false);
|
||||
}
|
||||
TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
|
||||
for (array_size_t i = 0; i < length - 1; i++) {
|
||||
elements->Set(thread, i, elements->Get(i + 1));
|
||||
}
|
||||
obj->SetLength(thread, JSTaggedValue(--length));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSArrayList::Has(JSTaggedValue value) const
|
||||
{
|
||||
TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
|
||||
return !(elements->GetIdx(value) == TaggedArray::MAX_ARRAY_INDEX);
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> JSArrayList::OwnKeys(JSThread *thread, const JSHandle<JSArrayList> &obj)
|
||||
{
|
||||
array_size_t length = obj->GetLength().GetArrayLength();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
|
||||
|
||||
for (array_size_t i = 0; i < length; i++) {
|
||||
keys->Set(thread, i, JSTaggedValue(i));
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
bool JSArrayList::GetOwnProperty(JSThread *thread, const JSHandle<JSArrayList> &obj,
|
||||
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
|
||||
{
|
||||
uint32_t index = 0;
|
||||
if (UNLIKELY(JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Can not get property whose type is not number", false);
|
||||
}
|
||||
|
||||
array_size_t length = obj->GetLength().GetArrayLength();
|
||||
if (index < 0 || index >= length) {
|
||||
THROW_RANGE_ERROR_AND_RETURN(thread, "Get property index out-of-bounds", false);
|
||||
}
|
||||
return JSObject::GetOwnProperty(thread, JSHandle<JSObject>::Cast(obj), key, desc);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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_JSARRAYLIST_H
|
||||
#define ECMASCRIPT_JSARRAYLIST_H
|
||||
|
||||
#include "js_object.h"
|
||||
#include "js_tagged_value-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class JSArrayList : public JSObject {
|
||||
public:
|
||||
static constexpr int DEFAULT_CAPACITY_LENGTH = 10;
|
||||
static JSArrayList *Cast(ObjectHeader *object)
|
||||
{
|
||||
return static_cast<JSArrayList *>(object);
|
||||
}
|
||||
|
||||
static void Add(JSThread *thread, const JSHandle<JSArrayList> &arrayList, const JSHandle<JSTaggedValue> &value);
|
||||
|
||||
JSTaggedValue Get(JSThread *thread, const uint32_t index);
|
||||
|
||||
JSTaggedValue Set(JSThread *thread, const uint32_t index, JSTaggedValue value);
|
||||
bool Has(JSTaggedValue value) const;
|
||||
|
||||
static bool Delete(JSThread *thread, const JSHandle<JSArrayList> &obj, const JSHandle<JSTaggedValue> &key);
|
||||
static JSHandle<TaggedArray> OwnKeys(JSThread *thread, const JSHandle<JSArrayList> &obj);
|
||||
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSArrayList> &obj, const JSHandle<JSTaggedValue> &key,
|
||||
PropertyDescriptor &desc);
|
||||
|
||||
inline int GetSize() const
|
||||
{
|
||||
return GetLength().GetArrayLength();
|
||||
}
|
||||
|
||||
static constexpr size_t LENGTH_OFFSET = JSObject::SIZE;
|
||||
ACCESSORS(Length, LENGTH_OFFSET, SIZE);
|
||||
|
||||
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LENGTH_OFFSET, SIZE)
|
||||
DECL_DUMP()
|
||||
private:
|
||||
inline static array_size_t ComputeCapacity(array_size_t oldCapacity)
|
||||
{
|
||||
array_size_t newCapacity = oldCapacity + (oldCapacity >> 1U);
|
||||
return newCapacity > DEFAULT_CAPACITY_LENGTH ? newCapacity : DEFAULT_CAPACITY_LENGTH;
|
||||
}
|
||||
static JSHandle<TaggedArray> GrowCapacity(const JSThread *thread, const JSHandle<JSArrayList> &obj,
|
||||
array_size_t capacity);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_JSARRAYLIST_H
|
||||
@@ -112,6 +112,8 @@ class ProtoChangeDetails;
|
||||
\
|
||||
/* SPECIAL indexed objects begin, DON'T CHANGE HERE ///////////////////////////////////////////////-PADDING */ \
|
||||
JS_ARRAY, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_ARRAY_LIST, /* /////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_QUEUE, /* /////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_TYPED_ARRAY, /* JS_TYPED_ARRAY_BEGIN /////////////////////////////////////////////////////////////////// */ \
|
||||
JS_INT8_ARRAY, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
JS_UINT8_ARRAY, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
@@ -603,6 +605,21 @@ public:
|
||||
return GetObjectType() == JSType::JS_PLURAL_RULES;
|
||||
}
|
||||
|
||||
inline bool IsJSArrayList() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_ARRAY_LIST;
|
||||
}
|
||||
|
||||
inline bool IsJSQueue() const
|
||||
{
|
||||
return GetObjectType() == JSType::JS_QUEUE;
|
||||
}
|
||||
|
||||
inline bool IsSpecialContainer() const
|
||||
{
|
||||
return GetObjectType() >= JSType::JS_ARRAY_LIST && GetObjectType() <= JSType::JS_QUEUE;
|
||||
}
|
||||
|
||||
inline bool IsAccessorData() const
|
||||
{
|
||||
return GetObjectType() == JSType::ACCESSOR_DATA;
|
||||
|
||||
@@ -502,6 +502,16 @@ inline bool JSTaggedValue::IsJSPluralRules() const
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSPluralRules();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsJSArrayList() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSArrayList();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsSpecialContainer() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsSpecialContainer();
|
||||
}
|
||||
|
||||
inline bool JSTaggedValue::IsPromiseIteratorRecord() const
|
||||
{
|
||||
return IsHeapObject() && GetTaggedObject()->GetClass()->IsPromiseIteratorRecord();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/internal_call_params.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_handle.h"
|
||||
#include "ecmascript/js_primitive_ref.h"
|
||||
#include "ecmascript/js_proxy.h"
|
||||
@@ -552,6 +553,10 @@ bool JSTaggedValue::DeleteProperty(JSThread *thread, const JSHandle<JSTaggedValu
|
||||
return JSProxy::DeleteProperty(thread, JSHandle<JSProxy>(obj), key);
|
||||
}
|
||||
|
||||
if (obj->IsSpecialContainer()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Can not delete property in Container Object", false);
|
||||
}
|
||||
|
||||
return JSObject::DeleteProperty(thread, JSHandle<JSObject>(obj), key);
|
||||
}
|
||||
|
||||
@@ -609,6 +614,10 @@ bool JSTaggedValue::DefineOwnProperty(JSThread *thread, const JSHandle<JSTaggedV
|
||||
return JSTypedArray::DefineOwnProperty(thread, obj, JSTypedArray::ToPropKey(thread, key), desc);
|
||||
}
|
||||
|
||||
if (obj->IsSpecialContainer()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Can not defineProperty on Container Object", false);
|
||||
}
|
||||
|
||||
return JSObject::DefineOwnProperty(thread, JSHandle<JSObject>(obj), key, desc);
|
||||
}
|
||||
|
||||
@@ -621,6 +630,9 @@ bool JSTaggedValue::GetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValu
|
||||
if (obj->IsTypedArray()) {
|
||||
return JSTypedArray::GetOwnProperty(thread, obj, JSTypedArray::ToPropKey(thread, key), desc);
|
||||
}
|
||||
if (obj->IsSpecialContainer()) {
|
||||
return GetContainerProperty(thread, obj, key, desc);
|
||||
}
|
||||
return JSObject::GetOwnProperty(thread, JSHandle<JSObject>(obj), key, desc);
|
||||
}
|
||||
|
||||
@@ -630,6 +642,9 @@ bool JSTaggedValue::SetPrototype(JSThread *thread, const JSHandle<JSTaggedValue>
|
||||
if (obj->IsJSProxy()) {
|
||||
return JSProxy::SetPrototype(thread, JSHandle<JSProxy>(obj), proto);
|
||||
}
|
||||
if (obj->IsSpecialContainer()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Can not set Prototype on Container Object", false);
|
||||
}
|
||||
|
||||
return JSObject::SetPrototype(thread, JSHandle<JSObject>(obj), proto);
|
||||
}
|
||||
@@ -650,6 +665,9 @@ JSHandle<TaggedArray> JSTaggedValue::GetOwnPropertyKeys(JSThread *thread, const
|
||||
if (obj->IsTypedArray()) {
|
||||
return JSTypedArray::OwnPropertyKeys(thread, obj);
|
||||
}
|
||||
if (obj->IsSpecialContainer()) {
|
||||
return GetOwnContainerPropertyKeys(thread, obj);
|
||||
}
|
||||
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(obj));
|
||||
}
|
||||
|
||||
@@ -663,6 +681,9 @@ bool JSTaggedValue::HasProperty(JSThread *thread, const JSHandle<JSTaggedValue>
|
||||
if (obj->IsTypedArray()) {
|
||||
return JSTypedArray::HasProperty(thread, obj, JSTypedArray::ToPropKey(thread, key));
|
||||
}
|
||||
if (obj->IsSpecialContainer()) {
|
||||
return HasContainerProperty(thread, obj, key);
|
||||
}
|
||||
return JSObject::HasProperty(thread, JSHandle<JSObject>(obj), key);
|
||||
}
|
||||
|
||||
@@ -676,6 +697,9 @@ bool JSTaggedValue::HasProperty(JSThread *thread, const JSHandle<JSTaggedValue>
|
||||
JSHandle<JSTaggedValue> key_handle(thread, JSTaggedValue(key));
|
||||
return JSTypedArray::HasProperty(thread, obj, JSHandle<JSTaggedValue>(ToString(thread, key_handle)));
|
||||
}
|
||||
if (obj->IsSpecialContainer()) {
|
||||
return HasContainerProperty(thread, obj, JSHandle<JSTaggedValue>(thread, JSTaggedValue(key)));
|
||||
}
|
||||
return JSObject::HasProperty(thread, JSHandle<JSObject>(obj), key);
|
||||
}
|
||||
|
||||
@@ -748,4 +772,57 @@ JSTaggedValue JSTaggedValue::GetSuperBase(JSThread *thread, const JSHandle<JSTag
|
||||
ASSERT(obj->IsECMAObject());
|
||||
return JSObject::Cast(obj.GetTaggedValue())->GetPrototype(thread);
|
||||
}
|
||||
|
||||
bool JSTaggedValue::HasContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
auto *hclass = obj->GetTaggedObject()->GetClass();
|
||||
JSType jsType = hclass->GetObjectType();
|
||||
switch (jsType) {
|
||||
case JSType::JS_ARRAY_LIST: {
|
||||
return JSHandle<JSArrayList>::Cast(obj)->Has(key.GetTaggedValue());
|
||||
}
|
||||
case JSType::JS_QUEUE:
|
||||
break;
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> JSTaggedValue::GetOwnContainerPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
|
||||
{
|
||||
auto *hclass = obj->GetTaggedObject()->GetClass();
|
||||
JSType jsType = hclass->GetObjectType();
|
||||
switch (jsType) {
|
||||
case JSType::JS_ARRAY_LIST: {
|
||||
return JSArrayList::OwnKeys(thread, JSHandle<JSArrayList>::Cast(obj));
|
||||
}
|
||||
case JSType::JS_QUEUE:
|
||||
break;
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return thread->GetEcmaVM()->GetFactory()->EmptyArray();
|
||||
}
|
||||
|
||||
bool JSTaggedValue::GetContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
|
||||
{
|
||||
auto *hclass = obj->GetTaggedObject()->GetClass();
|
||||
JSType jsType = hclass->GetObjectType();
|
||||
switch (jsType) {
|
||||
case JSType::JS_ARRAY_LIST: {
|
||||
return JSArrayList::GetOwnProperty(thread, JSHandle<JSArrayList>::Cast(obj), key, desc);
|
||||
}
|
||||
case JSType::JS_QUEUE:
|
||||
break;
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
@@ -312,6 +312,8 @@ public:
|
||||
bool IsJSNumberFormat() const;
|
||||
bool IsJSCollator() const;
|
||||
bool IsJSPluralRules() const;
|
||||
bool IsJSArrayList() const;
|
||||
bool IsSpecialContainer() const;
|
||||
|
||||
bool IsPrototypeHandler() const;
|
||||
bool IsTransitionHandler() const;
|
||||
@@ -343,6 +345,11 @@ private:
|
||||
|
||||
void DumpSpecialValue([[maybe_unused]] JSThread *thread, std::ostream &os) const;
|
||||
void DumpHeapObjectType([[maybe_unused]] JSThread *thread, std::ostream &os) const;
|
||||
static bool HasContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &key);
|
||||
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);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_JS_TAGGED_VALUE_H
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "ecmascript/jobs/pending_job.h"
|
||||
#include "ecmascript/js_arguments.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_async_function.h"
|
||||
@@ -300,6 +301,10 @@ void ObjectXRay::VisitObjectBody(TaggedObject *object, JSHClass *klass, const Ec
|
||||
case JSType::CLASS_INFO_EXTRACTOR:
|
||||
ClassInfoExtractor::Cast(object)->VisitRangeSlot(visitor);
|
||||
break;
|
||||
case JSType::JS_QUEUE:
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
JSArrayList::Cast(object)->VisitRangeSlot(visitor);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
|
||||
namespace panda::ecmascript {
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define MESSAGE_STRING_LIST(V) \
|
||||
V(SetReadOnlyProperty, "Cannot set readonly property") \
|
||||
V(FunctionCallNotConstructor, "class constructor cannot call") \
|
||||
V(SetPropertyWhenNotExtensible, "Cannot add property in prevent extensions ")
|
||||
#define MESSAGE_STRING_LIST(V) \
|
||||
V(SetReadOnlyProperty, "Cannot set readonly property") \
|
||||
V(FunctionCallNotConstructor, "class constructor cannot call") \
|
||||
V(SetPropertyWhenNotExtensible, "Cannot add property in prevent extensions ") \
|
||||
V(GetPropertyOutOfBounds, "Get Property index out-of-bounds") \
|
||||
V(CanNotSetPropertyOnContainer, "Cannot set property on Container")
|
||||
|
||||
class MessageString {
|
||||
public:
|
||||
@@ -40,4 +42,4 @@ public:
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define GET_MESSAGE_STRING_ID(name) static_cast<int>((MessageString::MessageId::Message_##name))
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_MESSAGE_STRING_H
|
||||
#endif // ECMASCRIPT_MESSAGE_STRING_H
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_async_function.h"
|
||||
#include "ecmascript/js_dataview.h"
|
||||
#include "ecmascript/js_date.h"
|
||||
@@ -812,6 +813,9 @@ JSHandle<JSObject> ObjectFactory::NewJSObjectByConstructor(const JSHandle<JSFunc
|
||||
JSDataView::Cast(*obj)->SetByteLength(thread_, JSTaggedValue(0));
|
||||
JSDataView::Cast(*obj)->SetByteOffset(thread_, JSTaggedValue(0));
|
||||
break;
|
||||
case JSType::JS_ARRAY_LIST:
|
||||
JSArrayList::Cast(*obj)->SetLength(thread_, JSTaggedValue(0));
|
||||
break;
|
||||
case JSType::JS_FUNCTION:
|
||||
case JSType::JS_GENERATOR_FUNCTION:
|
||||
case JSType::JS_FORIN_ITERATOR:
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ecmascript/ic/profile_type_info.h"
|
||||
#include "ecmascript/ic/properties_cache.h"
|
||||
#include "ecmascript/interpreter/interpreter-inl.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_object.h"
|
||||
#include "ecmascript/js_proxy.h"
|
||||
#include "ecmascript/layout_info.h"
|
||||
@@ -372,4 +373,12 @@ void RuntimeTrampolines::NoticeThroughChainAndRefreshUser(uintptr_t argGlue, JST
|
||||
JSHClass::NoticeThroughChain(thread, oldHClassHandle);
|
||||
JSHClass::RefreshUsers(thread, oldHClassHandle, newHClassHandle);
|
||||
}
|
||||
|
||||
void RuntimeTrampolines::JSArrayListSetByIndex(uintptr_t argGlue, JSTaggedValue obj, int32_t index, JSTaggedValue value)
|
||||
{
|
||||
auto thread = JSThread::GlueToJSThread(argGlue);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSArrayList> arrayList(thread, obj);
|
||||
arrayList->Set(thread, index, value);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
JSTaggedType argElement, uint32_t elementIndex, uint32_t capacity);
|
||||
static void DebugPrint(int fmtMessageId, ...);
|
||||
static void NoticeThroughChainAndRefreshUser(uintptr_t argGlue, uint64_t argoldHClass, uint64_t argnewHClass);
|
||||
static void JSArrayListSetByIndex(uintptr_t argGlue, JSTaggedValue obj, int32_t index, JSTaggedValue value);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "ecmascript/builtins/builtins_weak_map.h"
|
||||
#include "ecmascript/builtins/builtins_weak_set.h"
|
||||
#include "ecmascript/class_linker/program_object.h"
|
||||
#include "ecmascript/containers/containers_arraylist.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_for_in_iterator.h"
|
||||
@@ -110,6 +111,7 @@ using NumberFormat = builtins::BuiltinsNumberFormat;
|
||||
using RelativeTimeFormat = builtins::BuiltinsRelativeTimeFormat;
|
||||
using Collator = builtins::BuiltinsCollator;
|
||||
using PluralRules = builtins::BuiltinsPluralRules;
|
||||
using ArrayList = containers::ContainersArrayList;
|
||||
|
||||
constexpr int TAGGED_SIZE = JSTaggedValue::TaggedTypeSize();
|
||||
constexpr int OBJECT_HEADER_SIZE = TaggedObject::TaggedObjectSize();
|
||||
@@ -544,6 +546,9 @@ static uintptr_t g_nativeTable[] = {
|
||||
reinterpret_cast<uintptr_t>(PluralRules::SupportedLocalesOf),
|
||||
reinterpret_cast<uintptr_t>(PluralRules::Select),
|
||||
reinterpret_cast<uintptr_t>(PluralRules::ResolvedOptions),
|
||||
reinterpret_cast<uintptr_t>(ArrayList::ArrayListConstructor),
|
||||
reinterpret_cast<uintptr_t>(ArrayList::Add),
|
||||
reinterpret_cast<uintptr_t>(ArrayList::Iterator),
|
||||
|
||||
// not builtins method
|
||||
reinterpret_cast<uintptr_t>(JSFunction::PrototypeSetter),
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ecmascript/jobs/pending_job.h"
|
||||
#include "ecmascript/js_arguments.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_arraylist.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_async_function.h"
|
||||
@@ -621,6 +622,12 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
|
||||
DUMP_FOR_HANDLE(classInfoExtractor)
|
||||
break;
|
||||
}
|
||||
case JSType::JS_QUEUE:
|
||||
case JSType::JS_ARRAY_LIST: {
|
||||
CHECK_DUMP_FILEDS(JSObject::SIZE, JSArrayList::SIZE, 1)
|
||||
// unused
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ECMA_MEM(ERROR) << "JSType " << static_cast<int>(type) << " cannot be dumped.";
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -18,6 +18,7 @@ group("ark_js_moduletest") {
|
||||
"bitwiseop:bitwiseopAction",
|
||||
"callframe:callframeAction",
|
||||
"class:classAction",
|
||||
"container:containerAction",
|
||||
"dyninstruction:dyninstructionAction",
|
||||
"fortest:fortestAction",
|
||||
"generator:generatorAction",
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2021 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.
|
||||
|
||||
import("//ark/js_runtime/test/test_helper.gni")
|
||||
|
||||
host_moduletest_action("container_arraylist") {
|
||||
deps = []
|
||||
}
|
||||
|
||||
host_moduletest_action("container") {
|
||||
extra_modules = [ "container_arraylist" ]
|
||||
deps = [ ":gen_container_arraylist_abc" ]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
var helloworld = "container test start"
|
||||
print(helloworld)
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
var fastarray = undefined;
|
||||
if (globalThis["ArkPrivate"] != undefined) {
|
||||
fastarray = ArkPrivate.Load(ArkPrivate.ArrayList);
|
||||
}
|
||||
|
||||
let arr = new fastarray();
|
||||
arr.add(1);
|
||||
arr.add(2);
|
||||
print(arr[0]);
|
||||
|
||||
try {
|
||||
arr["aa"] = 3;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copyright (c) 2021 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.
|
||||
|
||||
container test start
|
||||
1
|
||||
TypeError: Cannot set property on Container
|
||||
Reference in New Issue
Block a user