LibJS: Add six typed arrays (signed and unsigned 8/16/32-bit)

This patch adds six of the standard type arrays and tries to share as
much code as possible:

- Uint8Array
- Uint16Array
- Uint32Array
- Int8Array
- Int16Array
- Int32Array
This commit is contained in:
Andreas Kling 2020-12-01 21:05:25 +01:00
parent 93feb7a81f
commit 3565d3c60c
Notes: sideshowbarker 2024-07-19 01:07:26 +09:00
15 changed files with 402 additions and 43 deletions

View file

@ -72,6 +72,7 @@ set(SOURCES
Runtime/SymbolConstructor.cpp
Runtime/SymbolObject.cpp
Runtime/SymbolPrototype.cpp
Runtime/TypedArray.cpp
Runtime/Uint8ClampedArray.cpp
Runtime/VM.cpp
Runtime/Value.cpp

View file

@ -45,28 +45,36 @@
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 \
__JS_ENUMERATE(Array, array, ArrayPrototype, ArrayConstructor) \
__JS_ENUMERATE(BigIntObject, bigint, BigIntPrototype, BigIntConstructor) \
__JS_ENUMERATE(BooleanObject, boolean, BooleanPrototype, BooleanConstructor) \
__JS_ENUMERATE(Date, date, DatePrototype, DateConstructor) \
__JS_ENUMERATE(Error, error, ErrorPrototype, ErrorConstructor) \
__JS_ENUMERATE(Function, function, FunctionPrototype, FunctionConstructor) \
__JS_ENUMERATE(NumberObject, number, NumberPrototype, NumberConstructor) \
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor) \
__JS_ENUMERATE(RegExpObject, regexp, RegExpPrototype, RegExpConstructor) \
__JS_ENUMERATE(StringObject, string, StringPrototype, StringConstructor) \
__JS_ENUMERATE(SymbolObject, symbol, SymbolPrototype, SymbolConstructor)
#define JS_ENUMERATE_NATIVE_OBJECTS \
__JS_ENUMERATE(Array, array, ArrayPrototype, ArrayConstructor, void) \
__JS_ENUMERATE(BigIntObject, bigint, BigIntPrototype, BigIntConstructor, void) \
__JS_ENUMERATE(BooleanObject, boolean, BooleanPrototype, BooleanConstructor, void) \
__JS_ENUMERATE(Date, date, DatePrototype, DateConstructor, void) \
__JS_ENUMERATE(Error, error, ErrorPrototype, ErrorConstructor, void) \
__JS_ENUMERATE(Function, function, FunctionPrototype, FunctionConstructor, void) \
__JS_ENUMERATE(NumberObject, number, NumberPrototype, NumberConstructor, void) \
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor, void) \
__JS_ENUMERATE(RegExpObject, regexp, RegExpPrototype, RegExpConstructor, void) \
__JS_ENUMERATE(StringObject, string, StringPrototype, StringConstructor, void) \
__JS_ENUMERATE(SymbolObject, symbol, SymbolPrototype, SymbolConstructor, void)
#define JS_ENUMERATE_ERROR_SUBCLASSES \
__JS_ENUMERATE(EvalError, eval_error, EvalErrorPrototype, EvalErrorConstructor) \
__JS_ENUMERATE(InternalError, internal_error, InternalErrorPrototype, InternalErrorConstructor) \
__JS_ENUMERATE(InvalidCharacterError, invalid_character_error, InvalidCharacterErrorPrototype, InvalidCharacterErrorConstructor) \
__JS_ENUMERATE(RangeError, range_error, RangeErrorPrototype, RangeErrorConstructor) \
__JS_ENUMERATE(ReferenceError, reference_error, ReferenceErrorPrototype, ReferenceErrorConstructor) \
__JS_ENUMERATE(SyntaxError, syntax_error, SyntaxErrorPrototype, SyntaxErrorConstructor) \
__JS_ENUMERATE(TypeError, type_error, TypeErrorPrototype, TypeErrorConstructor) \
__JS_ENUMERATE(URIError, uri_error, URIErrorPrototype, URIErrorConstructor)
#define JS_ENUMERATE_ERROR_SUBCLASSES \
__JS_ENUMERATE(EvalError, eval_error, EvalErrorPrototype, EvalErrorConstructor, void) \
__JS_ENUMERATE(InternalError, internal_error, InternalErrorPrototype, InternalErrorConstructor, void) \
__JS_ENUMERATE(InvalidCharacterError, invalid_character_error, InvalidCharacterErrorPrototype, InvalidCharacterErrorConstructor, void) \
__JS_ENUMERATE(RangeError, range_error, RangeErrorPrototype, RangeErrorConstructor, void) \
__JS_ENUMERATE(ReferenceError, reference_error, ReferenceErrorPrototype, ReferenceErrorConstructor, void) \
__JS_ENUMERATE(SyntaxError, syntax_error, SyntaxErrorPrototype, SyntaxErrorConstructor, void) \
__JS_ENUMERATE(TypeError, type_error, TypeErrorPrototype, TypeErrorConstructor, void) \
__JS_ENUMERATE(URIError, uri_error, URIErrorPrototype, URIErrorConstructor, void)
#define JS_ENUMERATE_TYPED_ARRAYS \
__JS_ENUMERATE(Uint8Array, uint8_array, Uint8ArrayPrototype, Uint8ArrayConstructor, u8) \
__JS_ENUMERATE(Uint16Array, uint16_array, Uint16ArrayPrototype, Uint16ArrayConstructor, u16) \
__JS_ENUMERATE(Uint32Array, uint32_array, Uint32ArrayPrototype, Uint32ArrayConstructor, u32) \
__JS_ENUMERATE(Int8Array, int8_array, Int8ArrayPrototype, Int8ArrayConstructor, i8) \
__JS_ENUMERATE(Int16Array, int16_array, Int16ArrayPrototype, Int16ArrayConstructor, i16) \
__JS_ENUMERATE(Int32Array, int32_array, Int32ArrayPrototype, Int32ArrayConstructor, i32)
#define JS_ENUMERATE_ITERATOR_PROTOTYPES \
__JS_ENUMERATE(Iterator, iterator) \
@ -75,7 +83,8 @@
#define JS_ENUMERATE_BUILTIN_TYPES \
JS_ENUMERATE_NATIVE_OBJECTS \
JS_ENUMERATE_ERROR_SUBCLASSES
JS_ENUMERATE_ERROR_SUBCLASSES \
JS_ENUMERATE_TYPED_ARRAYS
#define JS_ENUMERATE_WELL_KNOWN_SYMBOLS \
__JS_ENUMERATE(iterator, iterator) \
@ -138,9 +147,9 @@ enum class DeclarationKind;
class ProxyObject;
class ProxyConstructor;
#define __JS_ENUMERATE(ClassName, snake_name, ConstructorName, PrototypeName) \
class ClassName; \
class ConstructorName; \
#define __JS_ENUMERATE(ClassName, snake_name, ConstructorName, PrototypeName, ArrayType) \
class ClassName; \
class ConstructorName; \
class PrototypeName;
JS_ENUMERATE_BUILTIN_TYPES
#undef __JS_ENUMERATE

View file

@ -223,7 +223,7 @@ struct CommonPropertyNames {
#define __ENUMERATE(x) FlyString x { #x };
ENUMERATE_STANDARD_PROPERTY_NAMES(__ENUMERATE)
#undef __ENUMERATE
#define __JS_ENUMERATE(x, a, b, c) FlyString x { #x };
#define __JS_ENUMERATE(x, a, b, c, t) FlyString x { #x };
JS_ENUMERATE_BUILTIN_TYPES
#undef __JS_ENUMERATE
#define __JS_ENUMERATE(x, a) FlyString x { #x };

View file

@ -45,7 +45,7 @@ Error::~Error()
{
}
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
ClassName* ClassName::create(GlobalObject& global_object, const String& message) \
{ \
return global_object.heap().allocate<ClassName>(global_object, message, *global_object.snake_name##_prototype()); \

View file

@ -63,7 +63,7 @@ private:
virtual ~ClassName() override; \
};
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
DECLARE_ERROR_SUBCLASS(ClassName, snake_name, PrototypeName, ConstructorName)
JS_ENUMERATE_ERROR_SUBCLASSES
#undef __JS_ENUMERATE

View file

@ -64,7 +64,7 @@ Value ErrorConstructor::construct(Function&)
return Error::create(global_object(), vm.names.Error, message);
}
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
ConstructorName::ConstructorName(GlobalObject& global_object) \
: NativeFunction(*global_object.function_prototype()) \
{ \

View file

@ -61,7 +61,7 @@ private:
virtual bool has_constructor() const override { return true; } \
};
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(ClassName, snake_name, PrototypeName, ConstructorName)
JS_ENUMERATE_ERROR_SUBCLASSES
#undef __JS_ENUMERATE

View file

@ -127,11 +127,11 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
return js_string(vm, String::formatted("{}: {}", name, message));
}
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
PrototypeName::PrototypeName(GlobalObject& global_object) \
: Object(*global_object.error_prototype()) \
{ \
} \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
PrototypeName::PrototypeName(GlobalObject& global_object) \
: Object(*global_object.error_prototype()) \
{ \
} \
PrototypeName::~PrototypeName() { }
JS_ENUMERATE_ERROR_SUBCLASSES

View file

@ -57,7 +57,7 @@ private:
virtual ~PrototypeName() override; \
};
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
DECLARE_ERROR_SUBCLASS_PROTOTYPE(ClassName, snake_name, PrototypeName, ConstructorName)
JS_ENUMERATE_ERROR_SUBCLASSES
#undef __JS_ENUMERATE

View file

@ -62,6 +62,7 @@
#include <LibJS/Runtime/StringPrototype.h>
#include <LibJS/Runtime/SymbolConstructor.h>
#include <LibJS/Runtime/SymbolPrototype.h>
#include <LibJS/Runtime/TypedArray.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
@ -95,8 +96,8 @@ void GlobalObject::initialize()
set_prototype(m_object_prototype);
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
if (!m_##snake_name##_prototype) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
if (!m_##snake_name##_prototype) \
m_##snake_name##_prototype = heap().allocate<PrototypeName>(*this, *this);
JS_ENUMERATE_BUILTIN_TYPES
#undef __JS_ENUMERATE
@ -136,9 +137,10 @@ 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);
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#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
JS_ENUMERATE_TYPED_ARRAYS
#undef __JS_ENUMERATE
}
@ -154,7 +156,7 @@ void GlobalObject::visit_edges(Visitor& visitor)
visitor.visit(m_new_object_shape);
visitor.visit(m_new_script_function_prototype_object_shape);
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
visitor.visit(m_##snake_name##_constructor);
JS_ENUMERATE_ERROR_SUBCLASSES
#undef __JS_ENUMERATE

View file

@ -56,7 +56,7 @@ public:
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
ProxyConstructor* proxy_constructor() { return m_proxy_constructor; }
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; } \
Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
JS_ENUMERATE_BUILTIN_TYPES
@ -90,8 +90,8 @@ private:
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
ProxyConstructor* m_proxy_constructor { nullptr };
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ConstructorName* m_##snake_name##_constructor { nullptr }; \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
ConstructorName* m_##snake_name##_constructor { nullptr }; \
Object* m_##snake_name##_prototype { nullptr };
JS_ENUMERATE_BUILTIN_TYPES
#undef __JS_ENUMERATE

View file

@ -129,6 +129,7 @@ public:
virtual bool is_array_iterator_object() const { return false; }
virtual bool is_lexical_environment() const { return false; }
virtual bool is_global_object() const { return false; }
virtual bool is_typed_array() const { return false; }
virtual const char* class_name() const override { return "Object"; }
virtual void visit_edges(Cell::Visitor&) override;

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/TypedArray.h>
namespace JS {
#define JS_DEFINE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, Type) \
ClassName::~ClassName() { } \
ClassName* ClassName::create(GlobalObject& global_object, u32 length) \
{ \
return global_object.heap().allocate<ClassName>(global_object, length, *global_object.snake_name##_prototype()); \
} \
\
ClassName::ClassName(u32 length, Object& prototype) \
: TypedArray(length, prototype) \
{ \
} \
\
PrototypeName::PrototypeName(GlobalObject& global_object) \
: Object(*global_object.object_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() { } \
Value ConstructorName::construct(Function&) { return call(); } \
ConstructorName::ConstructorName(GlobalObject& global_object) \
: NativeFunction(vm().names.ClassName, *global_object.function_prototype()) \
{ \
} \
void ConstructorName::initialize(GlobalObject& global_object) \
{ \
auto& vm = this->vm(); \
NativeFunction::initialize(global_object); \
define_property(vm.names.prototype, global_object.snake_name##_prototype(), 0); \
define_property(vm.names.length, Value(1), Attribute::Configurable); \
} \
Value ConstructorName::call() \
{ \
if (vm().argument_count() <= 0) \
return ClassName::create(global_object(), 0); \
\
if (vm().argument_count() == 1 && vm().argument(0).is_number()) { \
auto array_length_value = vm().argument(0); \
if (!array_length_value.is_integer() || array_length_value.as_i32() < 0) { \
vm().throw_exception<TypeError>(global_object(), ErrorType::ArrayInvalidLength); \
return {}; \
} \
auto* array = ClassName::create(global_object(), array_length_value.as_i32()); \
return array; \
} \
auto* array = ClassName::create(global_object(), vm().argument_count()); \
for (size_t i = 0; i < vm().argument_count(); ++i) \
array->put_by_index(i, vm().argument(i)); \
return array; \
}
#undef __JS_ENUMERATE
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
JS_DEFINE_TYPED_ARRAY(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType);
JS_ENUMERATE_TYPED_ARRAYS
#undef __JS_ENUMERATE
}

View file

@ -0,0 +1,165 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/VM.h>
namespace JS {
template<typename T>
class TypedArray : public Object {
JS_OBJECT(TypedArray, Object);
public:
virtual ~TypedArray() override
{
ASSERT(m_data);
free(m_data);
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)
return Base::put_by_index(property_index, value);
if constexpr (sizeof(T) < 4) {
auto number = value.to_i32(global_object());
if (vm().exception())
return {};
m_data[property_index] = number;
} else if constexpr (sizeof(T) == 4) {
auto number = value.to_double(global_object());
if (vm().exception())
return {};
m_data[property_index] = number;
} else {
static_assert(DependentFalse<T>, "TypedArray::put_by_index with unhandled type size");
}
return true;
}
virtual Value get_by_index(u32 property_index) const override
{
if (property_index >= m_length)
return Base::get_by_index(property_index);
if constexpr (sizeof(T) < 4) {
return Value((i32)m_data[property_index]);
} else if constexpr (sizeof(T) == 4) {
auto value = m_data[property_index];
if constexpr (NumericLimits<T>::is_signed()) {
if (value > NumericLimits<i32>::max() || value < NumericLimits<i32>::min())
return Value((double)value);
} else {
if (value > NumericLimits<i32>::max())
return Value((double)value);
}
return Value((i32)value);
} else {
static_assert(DependentFalse<T>, "TypedArray::get_by_index with unhandled type size");
}
}
T* data() { return m_data; }
const T* data() const { return m_data; }
protected:
TypedArray(u32 length, Object& prototype)
: Object(prototype)
, m_length(length)
{
auto& vm = this->vm();
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); \
\
public: \
virtual ~ClassName(); \
static ClassName* create(GlobalObject&, u32 length); \
ClassName(u32 length, Object& prototype); \
}; \
class PrototypeName final : public Object { \
JS_OBJECT(PrototypeName, Object); \
\
public: \
PrototypeName(GlobalObject&); \
virtual void initialize(GlobalObject&) override; \
virtual ~PrototypeName() override; \
}; \
class ConstructorName final : public NativeFunction { \
JS_OBJECT(ConstructorName, NativeFunction); \
\
public: \
explicit ConstructorName(GlobalObject&); \
virtual void initialize(GlobalObject&) override; \
virtual ~ConstructorName() override; \
\
virtual Value call() override; \
virtual Value construct(Function& new_target) override; \
\
private: \
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);
JS_ENUMERATE_TYPED_ARRAYS
#undef __JS_ENUMERATE
}

View file

@ -0,0 +1,86 @@
test("basic Uint8Array", () => {
var a = new Uint8Array(1);
expect(typeof a).toBe("object");
expect(a instanceof Uint8Array).toBe(true);
expect(a.length).toBe(1);
a[0] = 1;
expect(a[0]).toBe(1);
a[0] -= 2;
expect(a[0]).toBe(0xff);
++a[0];
expect(a[0]).toBe(0);
});
test("basic Uint16Array", () => {
var a = new Uint16Array(1);
expect(typeof a).toBe("object");
expect(a instanceof Uint16Array).toBe(true);
expect(a.length).toBe(1);
a[0] = 1;
expect(a[0]).toBe(1);
a[0] -= 2;
expect(a[0]).toBe(0xffff);
++a[0];
expect(a[0]).toBe(0);
});
test("basic Uint32Array", () => {
var a = new Uint32Array(1);
expect(typeof a).toBe("object");
expect(a instanceof Uint32Array).toBe(true);
expect(a.length).toBe(1);
a[0] = 1;
expect(a[0]).toBe(1);
a[0] -= 2;
expect(a[0]).toBe(0xffffffff);
++a[0];
expect(a[0]).toBe(0);
});
test("basic Int8Array", () => {
var a = new Int8Array(1);
expect(typeof a).toBe("object");
expect(a instanceof Int8Array).toBe(true);
expect(a.length).toBe(1);
a[0] = 1;
expect(a[0]).toBe(1);
a[0] -= 2;
expect(a[0]).toBe(-1);
++a[0];
expect(a[0]).toBe(0);
a[0] = 127;
a[0]++;
expect(a[0]).toBe(-128);
});
test("basic Int16Array", () => {
var a = new Int16Array(1);
expect(typeof a).toBe("object");
expect(a instanceof Int16Array).toBe(true);
expect(a.length).toBe(1);
a[0] = 1;
expect(a[0]).toBe(1);
a[0] -= 2;
expect(a[0]).toBe(-1);
++a[0];
expect(a[0]).toBe(0);
a[0] = 32767;
a[0]++;
expect(a[0]).toBe(-32768);
});
test("basic Int32Array", () => {
var a = new Int32Array(1);
expect(typeof a).toBe("object");
expect(a instanceof Int32Array).toBe(true);
expect(a.length).toBe(1);
a[0] = 1;
expect(a[0]).toBe(1);
a[0] -= 2;
expect(a[0]).toBe(-1);
++a[0];
expect(a[0]).toBe(0);
a[0] = 0x7fffffff;
a[0]++;
expect(a[0]).toBe(-0x80000000);
});