mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
188 lines
6.4 KiB
C++
188 lines
6.4 KiB
C++
#include "Escargot.h"
|
|
#include "ArrayObject.h"
|
|
#include "Context.h"
|
|
|
|
namespace Escargot {
|
|
|
|
ArrayObject::ArrayObject(ExecutionState& state)
|
|
: Object(state, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER + 1, true)
|
|
{
|
|
m_structure = state.context()->defaultStructureForArrayObject();
|
|
m_values[ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER] = Value(0);
|
|
setPrototype(state, state.context()->globalObject()->arrayPrototype());
|
|
|
|
if (UNLIKELY(state.context()->didSomePrototypeObjectDefineIndexedProperty())) {
|
|
ensureObjectRareData()->m_isFastModeArrayObject = false;
|
|
ASSERT(m_fastModeData.size() == 0);
|
|
}
|
|
}
|
|
|
|
ObjectGetResult ArrayObject::getOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
|
{
|
|
ObjectGetResult v = getFastModeValue(state, P);
|
|
if (LIKELY(v.hasValue())) {
|
|
return v;
|
|
} else {
|
|
return Object::getOwnProperty(state, P);
|
|
}
|
|
}
|
|
|
|
bool ArrayObject::defineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptor& desc) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
|
{
|
|
if (LIKELY(setFastModeValue(state, P, desc))) {
|
|
return true;
|
|
}
|
|
|
|
ObjectGetResult oldLenDesc = getOwnProperty(state, state.context()->staticStrings().length);
|
|
uint32_t oldLen = getArrayLength(state);
|
|
|
|
if (!P.isUIntType() && P.propertyName() == state.context()->staticStrings().length) {
|
|
if (!desc.isValuePresent()) {
|
|
return Object::defineOwnProperty(state, P, desc);
|
|
}
|
|
|
|
ObjectPropertyDescriptor newLenDesc(desc);
|
|
uint32_t newLen = desc.value().toUint32(state);
|
|
if (newLen != desc.value().toNumber(state))
|
|
ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Invalid array length");
|
|
newLenDesc.setValue(Value(newLen));
|
|
|
|
if (newLen >= oldLen) {
|
|
return Object::defineOwnProperty(state, P, newLenDesc);
|
|
}
|
|
|
|
if (!oldLenDesc.isWritable()) {
|
|
return false;
|
|
}
|
|
|
|
bool newWritable;
|
|
if (!newLenDesc.isWritablePresent() || newLenDesc.isWritable()) {
|
|
newWritable = true;
|
|
} else {
|
|
newWritable = false;
|
|
newLenDesc.setWritable(true);
|
|
}
|
|
|
|
bool succeeded = Object::defineOwnProperty(state, P, newLenDesc);
|
|
if (!succeeded) {
|
|
return false;
|
|
}
|
|
|
|
while (newLen < oldLen) {
|
|
oldLen--;
|
|
bool deleteSucceeded = deleteOwnProperty(state, ObjectPropertyName(state, Value(oldLen)));
|
|
if (!deleteSucceeded) {
|
|
newLenDesc.setValue(Value(oldLen + 1));
|
|
if (!newWritable)
|
|
newLenDesc.setWritable(false);
|
|
Object::defineOwnProperty(state, P, newLenDesc);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!newWritable) {
|
|
bool ret = Object::defineOwnProperty(state, P, ObjectPropertyDescriptor((ObjectPropertyDescriptor::PresentAttribute)ObjectPropertyDescriptor::NonWritablePresent));
|
|
ASSERT(ret);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
uint64_t idx = P.toValue(state).toArrayIndex(state);
|
|
if (idx != Value::InvalidArrayIndexValue) {
|
|
uint32_t index = P.toValue(state).toUint32(state);
|
|
if ((index >= oldLen) && !oldLenDesc.isWritable())
|
|
return false;
|
|
bool succeeded = Object::defineOwnProperty(state, P, desc);
|
|
if (!succeeded)
|
|
return false;
|
|
if (index >= oldLen) {
|
|
setArrayLength(state, index + 1);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return Object::defineOwnProperty(state, P, desc);
|
|
}
|
|
|
|
bool ArrayObject::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
|
{
|
|
if (LIKELY(isFastModeArray())) {
|
|
uint64_t idx;
|
|
if (LIKELY(P.isUIntType())) {
|
|
idx = P.uintValue();
|
|
} else {
|
|
idx = P.string(state)->tryToUseAsArrayIndex();
|
|
}
|
|
if (LIKELY(idx != Value::InvalidArrayIndexValue)) {
|
|
uint64_t len = m_fastModeData.size();
|
|
ASSERT(len == getArrayLength(state));
|
|
if (idx < len) {
|
|
m_fastModeData[idx] = Value(Value::EmptyValue);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return Object::deleteOwnProperty(state, P);
|
|
}
|
|
|
|
void ArrayObject::enumeration(ExecutionState& state, std::function<bool(const ObjectPropertyName&, const ObjectStructurePropertyDescriptor& desc)> callback) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
|
{
|
|
if (LIKELY(isFastModeArray())) {
|
|
size_t len = m_fastModeData.size();
|
|
for (size_t i = 0; i < len; i++) {
|
|
ASSERT(isFastModeArray());
|
|
if (m_fastModeData[i].isEmpty())
|
|
continue;
|
|
if (!callback(ObjectPropertyName(state, Value(i)), ObjectStructurePropertyDescriptor::createDataDescriptor(ObjectStructurePropertyDescriptor::AllPresent))) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
Object::enumeration(state, callback);
|
|
}
|
|
|
|
void ArrayObject::sort(ExecutionState& state, std::function<bool(const Value& a, const Value& b)> comp)
|
|
{
|
|
if (isFastModeArray()) {
|
|
if (m_fastModeData.size()) {
|
|
std::vector<Value, gc_malloc_ignore_off_page_allocator<Value>> values(&m_fastModeData[0], m_fastModeData.data() + m_fastModeData.size());
|
|
std::sort(values.begin(), values.end(), comp);
|
|
for (size_t i = 0; i < values.size(); i++) {
|
|
m_fastModeData[i] = values[i];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
Object::sort(state, comp);
|
|
}
|
|
|
|
void* ArrayObject::operator new(size_t size)
|
|
{
|
|
return CustomAllocator<ArrayObject>().allocate(1);
|
|
}
|
|
|
|
void ArrayObject::iterateArrays(ExecutionState& state, HeapObjectIteratorCallback callback)
|
|
{
|
|
iterateSpecificKindOfObject(state, HeapObjectKind::ArrayObjectKind, callback);
|
|
}
|
|
|
|
void ArrayObject::convertIntoNonFastMode(ExecutionState& state)
|
|
{
|
|
if (!isFastModeArray())
|
|
return;
|
|
|
|
if (!structure()->isStructureWithFastAccess()) {
|
|
m_structure = structure()->convertToWithFastAccess(state);
|
|
}
|
|
|
|
ensureObjectRareData()->m_isFastModeArrayObject = false;
|
|
|
|
for (size_t i = 0; i < m_fastModeData.size(); i++) {
|
|
if (!m_fastModeData[i].isEmpty()) {
|
|
defineOwnPropertyThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, Value(i)), ObjectPropertyDescriptor(m_fastModeData[i], ObjectPropertyDescriptor::AllPresent));
|
|
}
|
|
}
|
|
|
|
m_fastModeData.clear();
|
|
}
|
|
}
|