1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:37:35 +00:00

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
5 changed files with 58 additions and 35 deletions

View file

@ -46,12 +46,6 @@ namespace JS {
: Object(*global_object.typed_array_prototype()) \ : 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() { } \ PrototypeName::~PrototypeName() { } \
\ \
ConstructorName::ConstructorName(GlobalObject& global_object) \ ConstructorName::ConstructorName(GlobalObject& global_object) \

View file

@ -32,9 +32,25 @@
namespace JS { 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> template<typename T>
class TypedArray : public Object { class TypedArray : public TypedArrayBase {
JS_OBJECT(TypedArray, Object); JS_OBJECT(TypedArray, TypedArrayBase);
public: public:
virtual ~TypedArray() override virtual ~TypedArray() override
@ -44,8 +60,6 @@ public:
m_data = nullptr; m_data = nullptr;
} }
i32 length() const { return m_length; }
virtual bool put_by_index(u32 property_index, Value value) override virtual bool put_by_index(u32 property_index, Value value) override
{ {
if (property_index >= m_length) if (property_index >= m_length)
@ -94,37 +108,17 @@ public:
protected: protected:
TypedArray(u32 length, Object& prototype) TypedArray(u32 length, Object& prototype)
: Object(prototype) : TypedArrayBase(length, prototype)
, m_length(length)
{ {
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)); m_data = (T*)calloc(m_length, sizeof(T));
} }
private: private:
virtual bool is_typed_array() const final { return true; } virtual bool is_typed_array() const final { return true; }
JS_DECLARE_NATIVE_GETTER(length_getter);
T* m_data { nullptr }; 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) \ #define JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
class ClassName : public TypedArray<Type> { \ class ClassName : public TypedArray<Type> { \
JS_OBJECT(ClassName, TypedArray); \ JS_OBJECT(ClassName, TypedArray); \
@ -139,7 +133,6 @@ inline JS_DEFINE_NATIVE_GETTER(TypedArray<T>::length_getter)
\ \
public: \ public: \
PrototypeName(GlobalObject&); \ PrototypeName(GlobalObject&); \
virtual void initialize(GlobalObject&) override; \
virtual ~PrototypeName() override; \ virtual ~PrototypeName() override; \
}; \ }; \
class ConstructorName final : public TypedArrayConstructor { \ 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; } \ virtual bool has_constructor() const override { return true; } \
}; };
#undef __JS_ENUMERATE #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \ JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type);
JS_DECLARE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType);
JS_ENUMERATE_TYPED_ARRAYS JS_ENUMERATE_TYPED_ARRAYS
#undef __JS_ENUMERATE #undef __JS_ENUMERATE

View file

@ -25,6 +25,7 @@
*/ */
#include <LibJS/Runtime/GlobalObject.h> #include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/TypedArray.h>
#include <LibJS/Runtime/TypedArrayPrototype.h> #include <LibJS/Runtime/TypedArrayPrototype.h>
namespace JS { namespace JS {
@ -36,11 +37,34 @@ TypedArrayPrototype::TypedArrayPrototype(GlobalObject& global_object)
void TypedArrayPrototype::initialize(GlobalObject& object) void TypedArrayPrototype::initialize(GlobalObject& object)
{ {
auto& vm = this->vm();
Object::initialize(object); Object::initialize(object);
// FIXME: This should be an accessor property
define_native_property(vm.names.length, length_getter, nullptr, Attribute::Configurable);
} }
TypedArrayPrototype::~TypedArrayPrototype() 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&); explicit TypedArrayPrototype(GlobalObject&);
virtual void initialize(GlobalObject&) override; virtual void initialize(GlobalObject&) override;
virtual ~TypedArrayPrototype() 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);
});
});