--- Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h +++ Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h @@ -28,6 +28,7 @@ #include "JSArrayBufferView.h" #include "ThrowScope.h" #include "ToNativeFromValue.h" +#include namespace JSC { @@ -146,7 +147,18 @@ public: JSValue getIndexQuickly(unsigned i) const { +#if CPU(BIG_ENDIAN) + switch (Adaptor::typeValue) { + case TypeFloat32: + case TypeFloat64: + return Adaptor::toJSValue(nullptr, getIndexQuicklyAsNativeValue(i)); + default: + // typed array views are commonly expected to be little endian views of the underlying data + return Adaptor::toJSValue(nullptr, flipBytes(getIndexQuicklyAsNativeValue(i))); + } +#else return Adaptor::toJSValue(nullptr, getIndexQuicklyAsNativeValue(i)); +#endif } void setIndexQuicklyToNativeValue(unsigned i, typename Adaptor::Type value) @@ -158,7 +170,20 @@ public: void setIndexQuickly(unsigned i, JSValue value) { ASSERT(!value.isObject()); +#if CPU(BIG_ENDIAN) + switch (Adaptor::typeValue) { + case TypeFloat32: + case TypeFloat64: + setIndexQuicklyToNativeValue(i, toNativeFromValue(value)); + break; + default: + // typed array views are commonly expected to be little endian views of the underlying data + setIndexQuicklyToNativeValue(i, flipBytes(toNativeFromValue(value))); + break; + } +#else setIndexQuicklyToNativeValue(i, toNativeFromValue(value)); +#endif } bool setIndex(JSGlobalObject* globalObject, unsigned i, JSValue jsValue) @@ -172,13 +197,54 @@ public: if (isDetached() || i >= m_length) return false; +#if CPU(BIG_ENDIAN) + switch (Adaptor::typeValue) { + case TypeFloat32: + case TypeFloat64: + setIndexQuicklyToNativeValue(i, value); + break; + default: + // typed array views are commonly expected to be little endian views of the underlying data + setIndexQuicklyToNativeValue(i, flipBytes(value)); + break; + } +#else setIndexQuicklyToNativeValue(i, value); +#endif return true; } - static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue) { return toNativeFromValue(globalObject, jsValue); } + static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue) + { +#if CPU(BIG_ENDIAN) + switch (Adaptor::typeValue) { + case TypeFloat32: + case TypeFloat64: + return toNativeFromValue(globalObject, jsValue); + default: + // typed array views are commonly expected to be little endian views of the underlying data + return flipBytes(toNativeFromValue(globalObject, jsValue)); + } +#else + return toNativeFromValue(globalObject, jsValue); +#endif + } - static Optional toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue) { return toNativeFromValueWithoutCoercion(jsValue); } + static Optional toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue) + { +#if CPU(BIG_ENDIAN) + switch (Adaptor::typeValue) { + case TypeFloat32: + case TypeFloat64: + return toNativeFromValueWithoutCoercion(jsValue); + default: + // typed array views are commonly expected to be little endian views of the underlying data + return flipBytes(toNativeFromValueWithoutCoercion(jsValue)); + } +#else + return toNativeFromValueWithoutCoercion(jsValue); +#endif + } void sort() { --- Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h +++ Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h @@ -208,9 +208,36 @@ ALWAYS_INLINE EncodedJSValue genericTypedArrayViewProtoFuncIncludes(VM& vm, JSGl scope.assertNoException(); RELEASE_ASSERT(!thisObject->isDetached()); - if (std::isnan(static_cast(*targetOption))) { + double targetOptionLittleEndianAsDouble; +#if CPU(BIG_ENDIAN) + switch (ViewClass::TypedArrayStorageType) { + case TypeFloat32: + case TypeFloat64: + targetOptionLittleEndianAsDouble = static_cast(*targetOption); + default: + // typed array views are commonly expected to be little endian views of the underlying data + targetOptionLittleEndianAsDouble = static_cast(flipBytes(*targetOption)); + } +#else + targetOptionLittleEndianAsDouble = static_cast(*targetOption); +#endif + + if (std::isnan(targetOptionLittleEndianAsDouble)) { for (; index < length; ++index) { - if (std::isnan(static_cast(array[index]))) + double arrayElementLittleEndianAsDouble; +#if CPU(BIG_ENDIAN) + switch (ViewClass::TypedArrayStorageType) { + case TypeFloat32: + case TypeFloat64: + arrayElementLittleEndianAsDouble = static_cast(array[index]); + default: + // typed array views are commonly expected to be little endian views of the underlying data + arrayElementLittleEndianAsDouble = static_cast(flipBytes(array[index])); + } +#else + arrayElementLittleEndianAsDouble = static_cast(array[index]); +#endif + if (std::isnan(arrayElementLittleEndianAsDouble)) return JSValue::encode(jsBoolean(true)); } } else { --- Source/WTF/wtf/FlipBytes.h +++ Source/WTF/wtf/FlipBytes.h @@ -24,6 +24,7 @@ */ #pragma once +#include "Optional.h" namespace WTF { @@ -98,6 +99,42 @@ inline T flipBytes(T value) return T(); } +template +inline T flipBytes(WTF::Optional value) +{ + if (sizeof(*value) == 1) + return *value; + if (sizeof(*value) == 2) { + union { + T original; + uint16_t word; + } u; + u.original = *value; + u.word = flipBytes(u.word); + return u.original; + } + if (sizeof(*value) == 4) { + union { + T original; + uint32_t word; + } u; + u.original = *value; + u.word = flipBytes(u.word); + return u.original; + } + if (sizeof(*value) == 8) { + union { + T original; + uint64_t word; + } u; + u.original = *value; + u.word = flipBytes(u.word); + return u.original; + } + RELEASE_ASSERT_NOT_REACHED(); + return T(); +} + template inline T flipBytesIfLittleEndian(T value, bool littleEndian) {