Преглед изворни кода

LibJS: Move TypedArray length getter to prototype

Linus Groh пре 4 година
родитељ
комит
0b086c759a

+ 0 - 6
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)                                                        \

+ 21 - 29
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
 

+ 24 - 0
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());
+}
+
 }

+ 3 - 0
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);
 };
 
 }

+ 10 - 0
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);
+    });
+});