mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-10 13:00:29 +03:00
LibJS: Add all of the DataView.prototype.get* methods
This commit is contained in:
parent
e4d267d4fb
commit
c54b9a6920
Notes:
sideshowbarker
2024-07-18 12:17:06 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/c54b9a69201 Pull-request: https://github.com/SerenityOS/serenity/pull/8045 Reviewed-by: https://github.com/linusg
@ -47,6 +47,19 @@ public:
|
||||
static SignedBigInteger import_data(const StringView& data) { return import_data((const u8*)data.characters_without_null_termination(), data.length()); }
|
||||
static SignedBigInteger import_data(const u8* ptr, size_t length);
|
||||
|
||||
static SignedBigInteger create_from(i64 value)
|
||||
{
|
||||
auto sign = false;
|
||||
u64 unsigned_value;
|
||||
if (value < 0) {
|
||||
unsigned_value = static_cast<u64>(-(value + 1)) + 1;
|
||||
sign = true;
|
||||
} else {
|
||||
unsigned_value = value;
|
||||
}
|
||||
return SignedBigInteger { UnsignedBigInteger::create_from(unsigned_value), sign };
|
||||
}
|
||||
|
||||
size_t export_data(Bytes, bool remove_leading_zeros = false) const;
|
||||
|
||||
static SignedBigInteger from_base10(StringView str);
|
||||
|
@ -41,6 +41,16 @@ public:
|
||||
return UnsignedBigInteger(ptr, length);
|
||||
}
|
||||
|
||||
static UnsignedBigInteger create_from(u64 value)
|
||||
{
|
||||
VERIFY(sizeof(Word) == 4);
|
||||
UnsignedBigInteger integer;
|
||||
integer.m_words.resize(2);
|
||||
integer.m_words[0] = static_cast<Word>(value & 0xFFFFFFFF);
|
||||
integer.m_words[1] = static_cast<Word>((value >> 32) & 0xFFFFFFFF);
|
||||
return integer;
|
||||
}
|
||||
|
||||
size_t export_data(Bytes, bool remove_leading_zeros = false) const;
|
||||
|
||||
static UnsignedBigInteger from_base10(const String& str);
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
|
||||
namespace JS {
|
||||
@ -33,6 +34,13 @@ public:
|
||||
void detach_buffer() { m_buffer = Empty {}; }
|
||||
bool is_detached() const { return m_buffer.has<Empty>(); }
|
||||
|
||||
enum Order {
|
||||
SeqCst,
|
||||
Unordered
|
||||
};
|
||||
template<typename type>
|
||||
Value get_value(size_t byte_index, bool is_typed_array, Order, bool is_little_endian = true);
|
||||
|
||||
private:
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
@ -51,4 +59,53 @@ private:
|
||||
Value m_detach_key;
|
||||
};
|
||||
|
||||
// 25.1.2.9 RawBytesToNumeric ( type, rawBytes, isLittleEndian ), https://tc39.es/ecma262/#sec-rawbytestonumeric
|
||||
template<typename T>
|
||||
static Value raw_bytes_to_numeric(GlobalObject& global_object, ByteBuffer raw_value, bool is_little_endian)
|
||||
{
|
||||
if (!is_little_endian) {
|
||||
VERIFY(raw_value.size() % 2 == 0);
|
||||
for (size_t i = 0; i < raw_value.size() / 2; ++i)
|
||||
swap(raw_value[i], raw_value[raw_value.size() - 1 - i]);
|
||||
}
|
||||
if constexpr (IsSame<T, float>) {
|
||||
float value;
|
||||
raw_value.span().copy_to({ &value, sizeof(float) });
|
||||
if (isnan(value))
|
||||
return js_nan();
|
||||
return Value(value);
|
||||
}
|
||||
if constexpr (IsSame<T, double>) {
|
||||
double value;
|
||||
raw_value.span().copy_to({ &value, sizeof(double) });
|
||||
if (isnan(value))
|
||||
return js_nan();
|
||||
return Value(value);
|
||||
}
|
||||
if constexpr (!IsIntegral<T>)
|
||||
VERIFY_NOT_REACHED();
|
||||
T int_value = 0;
|
||||
raw_value.span().copy_to({ &int_value, sizeof(T) });
|
||||
if constexpr (sizeof(T) == 8) {
|
||||
if constexpr (IsSigned<T>)
|
||||
return js_bigint(global_object.heap(), Crypto::SignedBigInteger::create_from(int_value));
|
||||
else
|
||||
return js_bigint(global_object.heap(), Crypto::SignedBigInteger { Crypto::UnsignedBigInteger::create_from(int_value) });
|
||||
} else {
|
||||
return Value(int_value);
|
||||
}
|
||||
}
|
||||
|
||||
// 25.1.2.10 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getvaluefrombuffer
|
||||
template<typename T>
|
||||
Value ArrayBuffer::get_value(size_t byte_index, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian)
|
||||
{
|
||||
auto element_size = sizeof(T);
|
||||
|
||||
// FIXME: Check for shared buffer
|
||||
|
||||
auto raw_value = buffer_impl().slice(byte_index, element_size);
|
||||
return raw_bytes_to_numeric<T>(global_object(), move(raw_value), is_little_endian);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -128,10 +128,17 @@ namespace JS {
|
||||
P(fround) \
|
||||
P(gc) \
|
||||
P(get) \
|
||||
P(getBigInt64) \
|
||||
P(getBigUint64) \
|
||||
P(getDate) \
|
||||
P(getDay) \
|
||||
P(getFloat32) \
|
||||
P(getFloat64) \
|
||||
P(getFullYear) \
|
||||
P(getHours) \
|
||||
P(getInt8) \
|
||||
P(getInt16) \
|
||||
P(getInt32) \
|
||||
P(getMilliseconds) \
|
||||
P(getMinutes) \
|
||||
P(getMonth) \
|
||||
@ -142,6 +149,9 @@ namespace JS {
|
||||
P(getSeconds) \
|
||||
P(getTime) \
|
||||
P(getTimezoneOffset) \
|
||||
P(getUint8) \
|
||||
P(getUint16) \
|
||||
P(getUint32) \
|
||||
P(getUTCDate) \
|
||||
P(getUTCDay) \
|
||||
P(getUTCFullYear) \
|
||||
|
@ -17,6 +17,18 @@ void DataViewPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
|
||||
define_native_function(vm.names.getBigInt64, get_big_int_64, 1, attr);
|
||||
define_native_function(vm.names.getBigUint64, get_big_uint_64, 1, attr);
|
||||
define_native_function(vm.names.getFloat32, get_float_32, 1, attr);
|
||||
define_native_function(vm.names.getFloat64, get_float_64, 1, attr);
|
||||
define_native_function(vm.names.getInt8, get_int_8, 1, attr);
|
||||
define_native_function(vm.names.getInt16, get_int_16, 1, attr);
|
||||
define_native_function(vm.names.getInt32, get_int_32, 1, attr);
|
||||
define_native_function(vm.names.getUint8, get_uint_8, 1, attr);
|
||||
define_native_function(vm.names.getUint16, get_uint_16, 1, attr);
|
||||
define_native_function(vm.names.getUint32, get_uint_32, 1, attr);
|
||||
|
||||
define_native_accessor(vm.names.buffer, buffer_getter, {}, Attribute::Configurable);
|
||||
define_native_accessor(vm.names.byteLength, byte_length_getter, {}, Attribute::Configurable);
|
||||
@ -40,6 +52,99 @@ static DataView* typed_this(VM& vm, GlobalObject& global_object)
|
||||
return static_cast<DataView*>(&this_value.as_object());
|
||||
}
|
||||
|
||||
// 25.3.1.1 GetViewValue ( view, requestIndex, isLittleEndian, type ), https://tc39.es/ecma262/#sec-getviewvalue
|
||||
template<typename T>
|
||||
static Value get_view_value(GlobalObject& global_object, Value request_index, Value is_little_endian)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto* view = typed_this(vm, global_object);
|
||||
if (!view)
|
||||
return {};
|
||||
|
||||
auto get_index = request_index.to_index(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
auto little_endian = is_little_endian.to_boolean();
|
||||
|
||||
auto buffer = view->viewed_array_buffer();
|
||||
if (buffer->is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto view_offset = view->byte_offset();
|
||||
auto view_size = view->byte_length();
|
||||
|
||||
auto element_size = sizeof(T);
|
||||
if (get_index + element_size > view_size) {
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, get_index, view_size);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buffer_index = get_index + view_offset;
|
||||
return buffer->get_value<T>(buffer_index, false, ArrayBuffer::Order::Unordered, little_endian);
|
||||
}
|
||||
|
||||
// 25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getbigint64
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_big_int_64)
|
||||
{
|
||||
return get_view_value<i64>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getbiguint64
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_big_uint_64)
|
||||
{
|
||||
return get_view_value<u64>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.7 DataView.prototype.getFloat32 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getfloat32
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_float_32)
|
||||
{
|
||||
return get_view_value<float>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.8 DataView.prototype.getFloat64 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getfloat64
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_float_64)
|
||||
{
|
||||
return get_view_value<double>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.9 DataView.prototype.getInt8 ( byteOffset ), https://tc39.es/ecma262/#sec-dataview.prototype.getint8
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_int_8)
|
||||
{
|
||||
return get_view_value<i8>(global_object, vm.argument(0), Value(true));
|
||||
}
|
||||
|
||||
// 25.3.4.10 DataView.prototype.getInt16 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getint16
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_int_16)
|
||||
{
|
||||
return get_view_value<i16>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.11 DataView.prototype.getInt32 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getint32
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_int_32)
|
||||
{
|
||||
return get_view_value<i32>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.12 DataView.prototype.getUint8 ( byteOffset ), https://tc39.es/ecma262/#sec-dataview.prototype.getuint8
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_uint_8)
|
||||
{
|
||||
return get_view_value<u8>(global_object, vm.argument(0), Value(true));
|
||||
}
|
||||
|
||||
// 25.3.4.13 DataView.prototype.getUint16 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getuint16
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_uint_16)
|
||||
{
|
||||
return get_view_value<u16>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.14 DataView.prototype.getUint32 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getuint32
|
||||
JS_DEFINE_NATIVE_FUNCTION(DataViewPrototype::get_uint_32)
|
||||
{
|
||||
return get_view_value<u32>(global_object, vm.argument(0), vm.argument(1));
|
||||
}
|
||||
|
||||
// 25.3.4.1 get DataView.prototype.buffer, https://tc39.es/ecma262/#sec-get-dataview.prototype.buffer
|
||||
JS_DEFINE_NATIVE_GETTER(DataViewPrototype::buffer_getter)
|
||||
{
|
||||
|
@ -19,6 +19,17 @@ public:
|
||||
virtual ~DataViewPrototype() override;
|
||||
|
||||
private:
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_big_int_64);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_big_uint_64);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_float_32);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_float_64);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_int_8);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_int_16);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_int_32);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_uint_8);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_uint_16);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_uint_32);
|
||||
|
||||
JS_DECLARE_NATIVE_GETTER(buffer_getter);
|
||||
JS_DECLARE_NATIVE_GETTER(byte_length_getter);
|
||||
JS_DECLARE_NATIVE_GETTER(byte_offset_getter);
|
||||
|
Loading…
Reference in New Issue
Block a user