LibJS: Move TypedArray length getter to prototype

This commit is contained in:
Linus Groh 2020-12-02 12:11:21 +00:00 committed by Andreas Kling
parent 12cf6f8650
commit 0b086c759a
Notes: sideshowbarker 2024-07-19 01:05:42 +09:00
5 changed files with 58 additions and 35 deletions

View file

@ -46,12 +46,6 @@ namespace JS {
: Object(*global_object.typed_array_prototype()) \
{ \
} \
void PrototypeName::initialize(GlobalObject& global_object) \
{ \
auto& vm = this->vm(); \
Object::initialize(global_object); \
define_property(vm.names.length, Value(0), Attribute::Configurable); \
} \
PrototypeName::~PrototypeName() { } \
\
ConstructorName::ConstructorName(GlobalObject& global_object) \

View file

@ -32,9 +32,25 @@
namespace JS {
class TypedArrayBase : public Object {
JS_OBJECT(TypedArrayBase, Object);
public:
u32 length() const { return m_length; }
protected:
TypedArrayBase(u32 length, Object& prototype)
: Object(prototype)
, m_length(length)
{
}
u32 m_length { 0 };
};
template<typename T>
class TypedArray : public Object {
JS_OBJECT(TypedArray, Object);
class TypedArray : public TypedArrayBase {
JS_OBJECT(TypedArray, TypedArrayBase);
public:
virtual ~TypedArray() override
@ -44,8 +60,6 @@ public:
m_data = nullptr;
}
i32 length() const { return m_length; }
virtual bool put_by_index(u32 property_index, Value value) override
{
if (property_index >= m_length)
@ -94,37 +108,17 @@ public:
protected:
TypedArray(u32 length, Object& prototype)
: Object(prototype)
, m_length(length)
: TypedArrayBase(length, prototype)
{
auto& vm = this->vm();
// FIXME: This belongs to TypedArray.prototype
define_native_property(vm.names.length, length_getter, nullptr);
m_data = (T*)calloc(m_length, sizeof(T));
}
private:
virtual bool is_typed_array() const final { return true; }
JS_DECLARE_NATIVE_GETTER(length_getter);
T* m_data { nullptr };
u32 m_length { 0 };
};
template<typename T>
inline JS_DEFINE_NATIVE_GETTER(TypedArray<T>::length_getter)
{
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_typed_array()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "TypedArray");
return {};
}
return Value(static_cast<const TypedArray*>(this_object)->length());
}
#define JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
class ClassName : public TypedArray<Type> { \
JS_OBJECT(ClassName, TypedArray); \
@ -139,7 +133,6 @@ inline JS_DEFINE_NATIVE_GETTER(TypedArray<T>::length_getter)
\
public: \
PrototypeName(GlobalObject&); \
virtual void initialize(GlobalObject&) override; \
virtual ~PrototypeName() override; \
}; \
class ConstructorName final : public TypedArrayConstructor { \
@ -157,9 +150,8 @@ inline JS_DEFINE_NATIVE_GETTER(TypedArray<T>::length_getter)
virtual bool has_constructor() const override { return true; } \
};
#undef __JS_ENUMERATE
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType);
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type);
JS_ENUMERATE_TYPED_ARRAYS
#undef __JS_ENUMERATE

View file

@ -25,6 +25,7 @@
*/
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/TypedArray.h>
#include <LibJS/Runtime/TypedArrayPrototype.h>
namespace JS {
@ -36,11 +37,34 @@ TypedArrayPrototype::TypedArrayPrototype(GlobalObject& global_object)
void TypedArrayPrototype::initialize(GlobalObject& object)
{
auto& vm = this->vm();
Object::initialize(object);
// FIXME: This should be an accessor property
define_native_property(vm.names.length, length_getter, nullptr, Attribute::Configurable);
}
TypedArrayPrototype::~TypedArrayPrototype()
{
}
static TypedArrayBase* typed_array_from(VM& vm, GlobalObject& global_object)
{
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_typed_array()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "TypedArray");
return nullptr;
}
return static_cast<TypedArrayBase*>(this_object);
}
JS_DEFINE_NATIVE_GETTER(TypedArrayPrototype::length_getter)
{
auto typed_array = typed_array_from(vm, global_object);
if (!typed_array)
return {};
return Value(typed_array->length());
}
}

View file

@ -37,6 +37,9 @@ public:
explicit TypedArrayPrototype(GlobalObject&);
virtual void initialize(GlobalObject&) override;
virtual ~TypedArrayPrototype() override;
private:
JS_DECLARE_NATIVE_GETTER(length_getter);
};
}

View file

@ -0,0 +1,10 @@
// Update when more typed arrays get added
const TYPED_ARRAYS = [Uint8Array, Uint16Array, Uint32Array, Int8Array, Int16Array, Int32Array];
test("basic functionality", () => {
TYPED_ARRAYS.forEach(T => {
const typedArray = new T(42);
expect(Object.hasOwnProperty(typedArray, "length")).toBeFalse();
expect(typedArray.length).toBe(42);
});
});