|
@@ -13,6 +13,9 @@
|
|
|
|
|
|
namespace JS {
|
|
|
|
|
|
+struct ClampedU8 {
|
|
|
+};
|
|
|
+
|
|
|
class ArrayBuffer : public Object {
|
|
|
JS_OBJECT(ArrayBuffer, Object);
|
|
|
|
|
@@ -70,26 +73,27 @@ static Value raw_bytes_to_numeric(GlobalObject& global_object, ByteBuffer raw_va
|
|
|
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>) {
|
|
|
+ using UnderlyingBufferDataType = Conditional<IsSame<ClampedU8, T>, u8, T>;
|
|
|
+ if constexpr (IsSame<UnderlyingBufferDataType, 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>) {
|
|
|
+ if constexpr (IsSame<UnderlyingBufferDataType, double>) {
|
|
|
double value;
|
|
|
raw_value.span().copy_to({ &value, sizeof(double) });
|
|
|
if (isnan(value))
|
|
|
return js_nan();
|
|
|
return Value(value);
|
|
|
}
|
|
|
- if constexpr (!IsIntegral<T>)
|
|
|
+ if constexpr (!IsIntegral<UnderlyingBufferDataType>)
|
|
|
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>)
|
|
|
+ UnderlyingBufferDataType int_value = 0;
|
|
|
+ raw_value.span().copy_to({ &int_value, sizeof(UnderlyingBufferDataType) });
|
|
|
+ if constexpr (sizeof(UnderlyingBufferDataType) == 8) {
|
|
|
+ if constexpr (IsSigned<UnderlyingBufferDataType>)
|
|
|
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) });
|
|
@@ -114,41 +118,62 @@ Value ArrayBuffer::get_value(size_t byte_index, [[maybe_unused]] bool is_typed_a
|
|
|
template<typename T>
|
|
|
static ByteBuffer numeric_to_raw_bytes(GlobalObject& global_object, Value value, bool is_little_endian)
|
|
|
{
|
|
|
- ByteBuffer raw_bytes = ByteBuffer::create_uninitialized(sizeof(T));
|
|
|
+ using UnderlyingBufferDataType = Conditional<IsSame<ClampedU8, T>, u8, T>;
|
|
|
+ ByteBuffer raw_bytes = ByteBuffer::create_uninitialized(sizeof(UnderlyingBufferDataType));
|
|
|
auto flip_if_needed = [&]() {
|
|
|
if (is_little_endian)
|
|
|
return;
|
|
|
- VERIFY(sizeof(T) % 2 == 0);
|
|
|
- for (size_t i = 0; i < sizeof(T) / 2; ++i)
|
|
|
- swap(raw_bytes[i], raw_bytes[sizeof(T) - 1 - i]);
|
|
|
+ VERIFY(sizeof(UnderlyingBufferDataType) % 2 == 0);
|
|
|
+ for (size_t i = 0; i < sizeof(UnderlyingBufferDataType) / 2; ++i)
|
|
|
+ swap(raw_bytes[i], raw_bytes[sizeof(UnderlyingBufferDataType) - 1 - i]);
|
|
|
};
|
|
|
- if constexpr (IsSame<T, float>) {
|
|
|
+ if constexpr (IsSame<UnderlyingBufferDataType, float>) {
|
|
|
float raw_value = value.to_double(global_object);
|
|
|
ReadonlyBytes { &raw_value, sizeof(float) }.copy_to(raw_bytes);
|
|
|
flip_if_needed();
|
|
|
return raw_bytes;
|
|
|
}
|
|
|
- if constexpr (IsSame<T, double>) {
|
|
|
+ if constexpr (IsSame<UnderlyingBufferDataType, double>) {
|
|
|
double raw_value = value.to_double(global_object);
|
|
|
ReadonlyBytes { &raw_value, sizeof(double) }.copy_to(raw_bytes);
|
|
|
flip_if_needed();
|
|
|
return raw_bytes;
|
|
|
}
|
|
|
- if constexpr (!IsIntegral<T>)
|
|
|
+ if constexpr (!IsIntegral<UnderlyingBufferDataType>)
|
|
|
VERIFY_NOT_REACHED();
|
|
|
- if constexpr (sizeof(T) == 8) {
|
|
|
- u64 int_value = value.as_bigint().big_integer().to_u64();
|
|
|
- ReadonlyBytes { &int_value, sizeof(u64) }.copy_to(raw_bytes);
|
|
|
+ if constexpr (sizeof(UnderlyingBufferDataType) == 8) {
|
|
|
+ UnderlyingBufferDataType int_value;
|
|
|
+
|
|
|
+ if constexpr (IsSigned<UnderlyingBufferDataType>)
|
|
|
+ int_value = value.to_bigint_int64(global_object);
|
|
|
+ else
|
|
|
+ int_value = value.to_bigint_uint64(global_object);
|
|
|
+
|
|
|
+ ReadonlyBytes { &int_value, sizeof(UnderlyingBufferDataType) }.copy_to(raw_bytes);
|
|
|
flip_if_needed();
|
|
|
return raw_bytes;
|
|
|
} else {
|
|
|
- T int_value;
|
|
|
- if constexpr (IsSigned<T>)
|
|
|
- int_value = value.to_i32(global_object);
|
|
|
- else
|
|
|
- int_value = value.to_u32(global_object);
|
|
|
- ReadonlyBytes { &int_value, sizeof(T) }.copy_to(raw_bytes);
|
|
|
- flip_if_needed();
|
|
|
+ UnderlyingBufferDataType int_value;
|
|
|
+ if constexpr (IsSigned<UnderlyingBufferDataType>) {
|
|
|
+ if constexpr (sizeof(UnderlyingBufferDataType) == 4)
|
|
|
+ int_value = value.to_i32(global_object);
|
|
|
+ else if constexpr (sizeof(UnderlyingBufferDataType) == 2)
|
|
|
+ int_value = value.to_i16(global_object);
|
|
|
+ else
|
|
|
+ int_value = value.to_i8(global_object);
|
|
|
+ } else {
|
|
|
+ if constexpr (sizeof(UnderlyingBufferDataType) == 4)
|
|
|
+ int_value = value.to_u32(global_object);
|
|
|
+ else if constexpr (sizeof(UnderlyingBufferDataType) == 2)
|
|
|
+ int_value = value.to_u16(global_object);
|
|
|
+ else if constexpr (!IsSame<T, ClampedU8>)
|
|
|
+ int_value = value.to_u8(global_object);
|
|
|
+ else
|
|
|
+ int_value = value.to_u8_clamp(global_object);
|
|
|
+ }
|
|
|
+ ReadonlyBytes { &int_value, sizeof(UnderlyingBufferDataType) }.copy_to(raw_bytes);
|
|
|
+ if constexpr (sizeof(UnderlyingBufferDataType) % 2 == 0)
|
|
|
+ flip_if_needed();
|
|
|
return raw_bytes;
|
|
|
}
|
|
|
}
|