diff --git a/Libraries/LibJS/CMakeLists.txt b/Libraries/LibJS/CMakeLists.txt index 778d2d71f9..61d9bb17af 100644 --- a/Libraries/LibJS/CMakeLists.txt +++ b/Libraries/LibJS/CMakeLists.txt @@ -73,6 +73,8 @@ set(SOURCES Runtime/SymbolObject.cpp Runtime/SymbolPrototype.cpp Runtime/TypedArray.cpp + Runtime/TypedArrayConstructor.cpp + Runtime/TypedArrayPrototype.cpp Runtime/Uint8ClampedArray.cpp Runtime/VM.cpp Runtime/Value.cpp diff --git a/Libraries/LibJS/Forward.h b/Libraries/LibJS/Forward.h index a351738cf6..bcde508370 100644 --- a/Libraries/LibJS/Forward.h +++ b/Libraries/LibJS/Forward.h @@ -45,7 +45,7 @@ void name([[maybe_unused]] JS::VM& vm, [[maybe_unused]] JS::GlobalObject& global_object, JS::Value value) // NOTE: Proxy is not included here as it doesn't have a prototype - m_proxy_constructor is initialized separately. -#define JS_ENUMERATE_NATIVE_OBJECTS \ +#define JS_ENUMERATE_NATIVE_OBJECTS_EXCLUDING_TEMPLATES \ __JS_ENUMERATE(Array, array, ArrayPrototype, ArrayConstructor, void) \ __JS_ENUMERATE(BigIntObject, bigint, BigIntPrototype, BigIntConstructor, void) \ __JS_ENUMERATE(BooleanObject, boolean, BooleanPrototype, BooleanConstructor, void) \ @@ -58,6 +58,10 @@ __JS_ENUMERATE(StringObject, string, StringPrototype, StringConstructor, void) \ __JS_ENUMERATE(SymbolObject, symbol, SymbolPrototype, SymbolConstructor, void) +#define JS_ENUMERATE_NATIVE_OBJECTS \ + JS_ENUMERATE_NATIVE_OBJECTS_EXCLUDING_TEMPLATES \ + __JS_ENUMERATE(TypedArray, typed_array, TypedArrayPrototype, TypedArrayConstructor, void) + #define JS_ENUMERATE_ERROR_SUBCLASSES \ __JS_ENUMERATE(EvalError, eval_error, EvalErrorPrototype, EvalErrorConstructor, void) \ __JS_ENUMERATE(InternalError, internal_error, InternalErrorPrototype, InternalErrorConstructor, void) \ @@ -147,11 +151,16 @@ enum class DeclarationKind; class ProxyObject; class ProxyConstructor; +class TypedArrayConstructor; +class TypedArrayPrototype; + #define __JS_ENUMERATE(ClassName, snake_name, ConstructorName, PrototypeName, ArrayType) \ class ClassName; \ class ConstructorName; \ class PrototypeName; -JS_ENUMERATE_BUILTIN_TYPES +JS_ENUMERATE_NATIVE_OBJECTS_EXCLUDING_TEMPLATES +JS_ENUMERATE_ERROR_SUBCLASSES +JS_ENUMERATE_TYPED_ARRAYS #undef __JS_ENUMERATE struct Argument; diff --git a/Libraries/LibJS/Runtime/ErrorTypes.h b/Libraries/LibJS/Runtime/ErrorTypes.h index 629b33928e..295fc647d3 100644 --- a/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Libraries/LibJS/Runtime/ErrorTypes.h @@ -37,6 +37,7 @@ M(BigIntIntArgument, "BigInt argument must be an integer") \ M(BigIntInvalidValue, "Invalid value for BigInt: {}") \ M(ClassConstructorWithoutNew, "Class constructor {} must be called with 'new'") \ + M(ClassIsAbstract, "Abstract class {} cannot be constructed directly") \ M(ClassDoesNotExtendAConstructorOrNull, "Class extends value {} is not a constructor or null") \ M(Convert, "Cannot convert {} to {}") \ M(ConvertUndefinedToObject, "Cannot convert undefined to object") \ diff --git a/Libraries/LibJS/Runtime/GlobalObject.cpp b/Libraries/LibJS/Runtime/GlobalObject.cpp index 7a0b939a02..921d1efc83 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -63,6 +63,8 @@ #include #include #include +#include +#include #include namespace JS { @@ -137,6 +139,8 @@ void GlobalObject::initialize() add_constructor(vm.names.String, m_string_constructor, m_string_prototype); add_constructor(vm.names.Symbol, m_symbol_constructor, m_symbol_prototype); + initialize_constructor(vm.names.TypedArray, m_typed_array_constructor, m_typed_array_prototype); + #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \ add_constructor(vm.names.ClassName, m_##snake_name##_constructor, m_##snake_name##_prototype); JS_ENUMERATE_ERROR_SUBCLASSES diff --git a/Libraries/LibJS/Runtime/GlobalObject.h b/Libraries/LibJS/Runtime/GlobalObject.h index 154aa5b2aa..cef31ba877 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.h +++ b/Libraries/LibJS/Runtime/GlobalObject.h @@ -70,6 +70,8 @@ public: protected: virtual void visit_edges(Visitor&) override; + template + void initialize_constructor(const FlyString& property_name, ConstructorType*&, Object* prototype); template void add_constructor(const FlyString& property_name, ConstructorType*&, Object* prototype); @@ -103,7 +105,7 @@ private: }; template -inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object* prototype) +inline void GlobalObject::initialize_constructor(const FlyString& property_name, ConstructorType*& constructor, Object* prototype) { auto& vm = this->vm(); constructor = heap().allocate(*this, *this); @@ -115,6 +117,12 @@ inline void GlobalObject::add_constructor(const FlyString& property_name, Constr if (vm.exception()) return; } +} + +template +inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object* prototype) +{ + initialize_constructor(property_name, constructor, prototype); define_property(property_name, constructor, Attribute::Writable | Attribute::Configurable); } diff --git a/Libraries/LibJS/Runtime/TypedArray.cpp b/Libraries/LibJS/Runtime/TypedArray.cpp index 99d0487ab3..6302956349 100644 --- a/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Libraries/LibJS/Runtime/TypedArray.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace JS { @@ -42,7 +43,7 @@ namespace JS { } \ \ PrototypeName::PrototypeName(GlobalObject& global_object) \ - : Object(*global_object.object_prototype()) \ + : Object(*global_object.typed_array_prototype()) \ { \ } \ void PrototypeName::initialize(GlobalObject& global_object) \ @@ -56,7 +57,7 @@ namespace JS { ConstructorName::~ConstructorName() { } \ Value ConstructorName::construct(Function&) { return call(); } \ ConstructorName::ConstructorName(GlobalObject& global_object) \ - : NativeFunction(vm().names.ClassName, *global_object.function_prototype()) \ + : TypedArrayConstructor(vm().names.ClassName, *global_object.typed_array_constructor()) \ { \ } \ void ConstructorName::initialize(GlobalObject& global_object) \ diff --git a/Libraries/LibJS/Runtime/TypedArray.h b/Libraries/LibJS/Runtime/TypedArray.h index 8f8c928704..d78f89c554 100644 --- a/Libraries/LibJS/Runtime/TypedArray.h +++ b/Libraries/LibJS/Runtime/TypedArray.h @@ -27,7 +27,7 @@ #pragma once #include -#include +#include #include namespace JS { @@ -98,6 +98,7 @@ protected: , 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)); } @@ -141,8 +142,8 @@ inline JS_DEFINE_NATIVE_GETTER(TypedArray::length_getter) virtual void initialize(GlobalObject&) override; \ virtual ~PrototypeName() override; \ }; \ - class ConstructorName final : public NativeFunction { \ - JS_OBJECT(ConstructorName, NativeFunction); \ + class ConstructorName final : public TypedArrayConstructor { \ + JS_OBJECT(ConstructorName, TypedArrayConstructor); \ \ public: \ explicit ConstructorName(GlobalObject&); \ diff --git a/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp b/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp new file mode 100644 index 0000000000..14af8c2eb8 --- /dev/null +++ b/Libraries/LibJS/Runtime/TypedArrayConstructor.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020, Linus Groh +#include + +namespace JS { + +TypedArrayConstructor::TypedArrayConstructor(const FlyString& name, Object& prototype) + : NativeFunction(name, prototype) +{ +} + +TypedArrayConstructor::TypedArrayConstructor(GlobalObject& global_object) + : NativeFunction(vm().names.TypedArray, *global_object.function_prototype()) +{ +} + +void TypedArrayConstructor::initialize(GlobalObject& global_object) +{ + auto& vm = this->vm(); + NativeFunction::initialize(global_object); + define_property(vm.names.prototype, global_object.typed_array_prototype(), 0); + define_property(vm.names.length, Value(0), Attribute::Configurable); +} + +TypedArrayConstructor::~TypedArrayConstructor() +{ +} + +Value TypedArrayConstructor::call() +{ + return construct(*this); +} + +Value TypedArrayConstructor::construct(Function&) +{ + vm().throw_exception(global_object(), ErrorType::ClassIsAbstract, "TypedArray"); + return {}; +} + +} diff --git a/Libraries/LibJS/Runtime/TypedArrayConstructor.h b/Libraries/LibJS/Runtime/TypedArrayConstructor.h new file mode 100644 index 0000000000..cd43298e80 --- /dev/null +++ b/Libraries/LibJS/Runtime/TypedArrayConstructor.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, Linus Groh + +namespace JS { + +class TypedArrayConstructor : public NativeFunction { + JS_OBJECT(TypedArrayConstructor, NativeFunction); + +public: + TypedArrayConstructor(const FlyString& name, Object& prototype); + explicit TypedArrayConstructor(GlobalObject&); + virtual void initialize(GlobalObject&) override; + virtual ~TypedArrayConstructor() override; + + virtual Value call() override; + virtual Value construct(Function& new_target) override; + +private: + virtual bool has_constructor() const override { return true; } +}; + +} diff --git a/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp new file mode 100644 index 0000000000..cb398e2ba1 --- /dev/null +++ b/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Linus Groh +#include + +namespace JS { + +TypedArrayPrototype::TypedArrayPrototype(GlobalObject& global_object) + : Object(*global_object.object_prototype()) +{ +} + +void TypedArrayPrototype::initialize(GlobalObject& object) +{ + Object::initialize(object); +} + +TypedArrayPrototype::~TypedArrayPrototype() +{ +} + +} diff --git a/Libraries/LibJS/Runtime/TypedArrayPrototype.h b/Libraries/LibJS/Runtime/TypedArrayPrototype.h new file mode 100644 index 0000000000..1ef6b368f8 --- /dev/null +++ b/Libraries/LibJS/Runtime/TypedArrayPrototype.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, Linus Groh + +namespace JS { + +class TypedArrayPrototype final : public Object { + JS_OBJECT(TypedArrayPrototype, Object); + +public: + explicit TypedArrayPrototype(GlobalObject&); + virtual void initialize(GlobalObject&) override; + virtual ~TypedArrayPrototype() override; +}; + +}