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

LibJS: ArrayBuffer.prototype.slice

Implements the aforementioned native Javascript function, following the
specification's [1] implementation.

[1] https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
This commit is contained in:
Jamie Mansfield 2021-04-02 21:31:23 +01:00 committed by Andreas Kling
parent b50de19cd3
commit 01187e58f2
4 changed files with 82 additions and 1 deletions

View file

@ -34,12 +34,23 @@ ArrayBuffer* ArrayBuffer::create(GlobalObject& global_object, size_t byte_size)
return global_object.heap().allocate<ArrayBuffer>(global_object, byte_size, *global_object.array_buffer_prototype());
}
ArrayBuffer* ArrayBuffer::create(GlobalObject& global_object, ByteBuffer& buffer)
{
return global_object.heap().allocate<ArrayBuffer>(global_object, buffer, *global_object.array_buffer_prototype());
}
ArrayBuffer::ArrayBuffer(size_t byte_size, Object& prototype)
: Object(prototype)
, m_buffer(ByteBuffer::create_zeroed(byte_size))
{
}
ArrayBuffer::ArrayBuffer(ByteBuffer& buffer, Object& prototype)
: Object(prototype)
, m_buffer(buffer)
{
}
ArrayBuffer::~ArrayBuffer()
{
}

View file

@ -36,8 +36,10 @@ class ArrayBuffer : public Object {
public:
static ArrayBuffer* create(GlobalObject&, size_t);
static ArrayBuffer* create(GlobalObject&, ByteBuffer&);
ArrayBuffer(size_t, Object& prototype);
ArrayBuffer(ByteBuffer& buffer, Object& prototype);
virtual ~ArrayBuffer() override;
size_t byte_length() const { return m_buffer.size(); }

View file

@ -66,12 +66,51 @@ static ArrayBuffer* array_buffer_object_from(VM& vm, GlobalObject& global_object
return static_cast<ArrayBuffer*>(&this_object);
}
// 25.1.5.3 ArrayBuffer.prototype.slice, https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::slice)
{
const auto start = vm.argument(0);
const auto end = vm.argument(1);
auto array_buffer_object = array_buffer_object_from(vm, global_object);
if (!array_buffer_object)
return {};
TODO();
// FIXME: Check for shared buffer
// FIXME: Check for detached buffer
const auto len = array_buffer_object->byte_length();
const auto relative_start = start.is_negative_infinity()
? 0
: start.to_integer_or_infinity(global_object);
if (vm.exception())
return {};
const auto first = relative_start < 0
? max(len + relative_start, 0.0)
: min(relative_start, static_cast<double>(len));
const auto relative_end = end.is_undefined()
? len
: end.to_integer_or_infinity(global_object);
if (vm.exception())
return {};
double final_;
if (end.is_negative_infinity())
final_ = 0;
else if (relative_end < 0)
final_ = max(len + relative_end, 0.0);
else
final_ = min(relative_end, static_cast<double>(len));
const auto new_len = max(final_ - first, 0.0);
// FIXME: this is a bit more involved in the specification
auto sliced = array_buffer_object->buffer().slice(first, new_len);
auto buffer = ArrayBuffer::create(global_object, sliced);
return buffer;
}
JS_DEFINE_NATIVE_GETTER(ArrayBufferPrototype::byte_length_getter)

View file

@ -0,0 +1,29 @@
test("single parameter", () => {
const buffer = new ArrayBuffer(16);
const fullView = new Int32Array(buffer);
// modify some value that we can check in the sliced buffer
fullView[3] = 7;
// slice the buffer and use a new int32 view to perform basic checks
const slicedBuffer = buffer.slice(12);
const slicedView = new Int32Array(slicedBuffer);
expect(slicedView).toHaveLength(1);
expect(slicedView[0]).toBe(7);
});
test("both parameters", () => {
const buffer = new ArrayBuffer(16);
const fullView = new Int32Array(buffer);
// modify some value that we can check in the sliced buffer
fullView[1] = 12;
// slice the buffer and use a new int32 view to perform basic checks
const slicedBuffer = buffer.slice(4, 8);
const slicedView = new Int32Array(slicedBuffer);
expect(slicedView).toHaveLength(1);
expect(slicedView[0]).toBe(12);
});