Просмотр исходного кода

LibJS: Refactor numeric_to_raw_bytes and raw_bytes_to_numeric

This is to make use of the new Value conversion methods.
This also moves the clamped u8 tag to ArrayBuffer from TypedArray and
the conversion to these methods, as the spec does it here.
Luke 4 лет назад
Родитель
Сommit
80edf6f5b6
2 измененных файлов с 49 добавлено и 27 удалено
  1. 49 24
      Userland/Libraries/LibJS/Runtime/ArrayBuffer.h
  2. 0 3
      Userland/Libraries/LibJS/Runtime/TypedArray.h

+ 49 - 24
Userland/Libraries/LibJS/Runtime/ArrayBuffer.h

@@ -13,6 +13,9 @@
 
 
 namespace JS {
 namespace JS {
 
 
+struct ClampedU8 {
+};
+
 class ArrayBuffer : public Object {
 class ArrayBuffer : public Object {
     JS_OBJECT(ArrayBuffer, 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)
         for (size_t i = 0; i < raw_value.size() / 2; ++i)
             swap(raw_value[i], raw_value[raw_value.size() - 1 - 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;
         float value;
         raw_value.span().copy_to({ &value, sizeof(float) });
         raw_value.span().copy_to({ &value, sizeof(float) });
         if (isnan(value))
         if (isnan(value))
             return js_nan();
             return js_nan();
         return Value(value);
         return Value(value);
     }
     }
-    if constexpr (IsSame<T, double>) {
+    if constexpr (IsSame<UnderlyingBufferDataType, double>) {
         double value;
         double value;
         raw_value.span().copy_to({ &value, sizeof(double) });
         raw_value.span().copy_to({ &value, sizeof(double) });
         if (isnan(value))
         if (isnan(value))
             return js_nan();
             return js_nan();
         return Value(value);
         return Value(value);
     }
     }
-    if constexpr (!IsIntegral<T>)
+    if constexpr (!IsIntegral<UnderlyingBufferDataType>)
         VERIFY_NOT_REACHED();
         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));
             return js_bigint(global_object.heap(), Crypto::SignedBigInteger::create_from(int_value));
         else
         else
             return js_bigint(global_object.heap(), Crypto::SignedBigInteger { Crypto::UnsignedBigInteger::create_from(int_value) });
             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>
 template<typename T>
 static ByteBuffer numeric_to_raw_bytes(GlobalObject& global_object, Value value, bool is_little_endian)
 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 = [&]() {
     auto flip_if_needed = [&]() {
         if (is_little_endian)
         if (is_little_endian)
             return;
             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);
         float raw_value = value.to_double(global_object);
         ReadonlyBytes { &raw_value, sizeof(float) }.copy_to(raw_bytes);
         ReadonlyBytes { &raw_value, sizeof(float) }.copy_to(raw_bytes);
         flip_if_needed();
         flip_if_needed();
         return raw_bytes;
         return raw_bytes;
     }
     }
-    if constexpr (IsSame<T, double>) {
+    if constexpr (IsSame<UnderlyingBufferDataType, double>) {
         double raw_value = value.to_double(global_object);
         double raw_value = value.to_double(global_object);
         ReadonlyBytes { &raw_value, sizeof(double) }.copy_to(raw_bytes);
         ReadonlyBytes { &raw_value, sizeof(double) }.copy_to(raw_bytes);
         flip_if_needed();
         flip_if_needed();
         return raw_bytes;
         return raw_bytes;
     }
     }
-    if constexpr (!IsIntegral<T>)
+    if constexpr (!IsIntegral<UnderlyingBufferDataType>)
         VERIFY_NOT_REACHED();
         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();
         flip_if_needed();
         return raw_bytes;
         return raw_bytes;
     } else {
     } 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;
         return raw_bytes;
     }
     }
 }
 }

+ 0 - 3
Userland/Libraries/LibJS/Runtime/TypedArray.h

@@ -44,9 +44,6 @@ private:
     virtual void visit_edges(Visitor&) override;
     virtual void visit_edges(Visitor&) override;
 };
 };
 
 
-struct ClampedU8 {
-};
-
 template<typename T>
 template<typename T>
 class TypedArray : public TypedArrayBase {
 class TypedArray : public TypedArrayBase {
     JS_OBJECT(TypedArray, TypedArrayBase);
     JS_OBJECT(TypedArray, TypedArrayBase);