summaryrefslogtreecommitdiff
path: root/Libraries/LibJS
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2020-12-02 12:11:21 +0000
committerAndreas Kling <kling@serenityos.org>2020-12-02 14:39:53 +0100
commit0b086c759a658a02cf7edb05e74ffac1d0a8b41d (patch)
treeaad942d9189e7fdfd1011ee03cd132a9228df41b /Libraries/LibJS
parent12cf6f86503cee499d093b7accebe6ad11bc1dae (diff)
downloadserenity-0b086c759a658a02cf7edb05e74ffac1d0a8b41d.zip
LibJS: Move TypedArray length getter to prototype
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r--Libraries/LibJS/Runtime/TypedArray.cpp6
-rw-r--r--Libraries/LibJS/Runtime/TypedArray.h50
-rw-r--r--Libraries/LibJS/Runtime/TypedArrayPrototype.cpp24
-rw-r--r--Libraries/LibJS/Runtime/TypedArrayPrototype.h3
-rw-r--r--Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.length.js10
5 files changed, 58 insertions, 35 deletions
diff --git a/Libraries/LibJS/Runtime/TypedArray.cpp b/Libraries/LibJS/Runtime/TypedArray.cpp
index 58b9eba1c3..a27023f9cd 100644
--- a/Libraries/LibJS/Runtime/TypedArray.cpp
+++ b/Libraries/LibJS/Runtime/TypedArray.cpp
@@ -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) \
diff --git a/Libraries/LibJS/Runtime/TypedArray.h b/Libraries/LibJS/Runtime/TypedArray.h
index d78f89c554..e7f98dfba8 100644
--- a/Libraries/LibJS/Runtime/TypedArray.h
+++ b/Libraries/LibJS/Runtime/TypedArray.h
@@ -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
diff --git a/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp
index cb398e2ba1..80547d3bfe 100644
--- a/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp
+++ b/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp
@@ -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());
+}
+
}
diff --git a/Libraries/LibJS/Runtime/TypedArrayPrototype.h b/Libraries/LibJS/Runtime/TypedArrayPrototype.h
index 1ef6b368f8..108ac5352b 100644
--- a/Libraries/LibJS/Runtime/TypedArrayPrototype.h
+++ b/Libraries/LibJS/Runtime/TypedArrayPrototype.h
@@ -37,6 +37,9 @@ public:
explicit TypedArrayPrototype(GlobalObject&);
virtual void initialize(GlobalObject&) override;
virtual ~TypedArrayPrototype() override;
+
+private:
+ JS_DECLARE_NATIVE_GETTER(length_getter);
};
}
diff --git a/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.length.js b/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.length.js
new file mode 100644
index 0000000000..bbe85a2bf1
--- /dev/null
+++ b/Libraries/LibJS/Tests/builtins/TypedArray/TypedArray.prototype.length.js
@@ -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);
+ });
+});