aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp106
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h2
-rw-r--r--src/qml/jsruntime/qv4value_p.h10
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations2
4 files changed, 75 insertions, 45 deletions
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index c52526d686..54c3b9cfc1 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -57,16 +57,31 @@ DEFINE_OBJECT_VTABLE(TypedArray);
Q_STATIC_ASSERT((int)ExecutionEngine::NTypedArrayTypes == (int)Heap::TypedArray::NTypes);
+static inline int toInt32(Value v)
+{
+ Q_ASSERT(v.isNumber());
+ if (v.isInteger())
+ return v.integerValue();
+ return Double::toInt32(v.doubleValue());
+}
+
+static inline double toDouble(Value v)
+{
+ Q_ASSERT(v.isNumber());
+ if (v.isInteger())
+ return v.integerValue();
+ return v.doubleValue();
+}
+
ReturnedValue Int8ArrayRead(const char *data, int index)
{
return Encode((int)(signed char)data[index]);
}
-void Int8ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void Int8ArrayWrite(char *data, int index, const Value &value)
{
- signed char v = (signed char)value.toUInt32();
- if (e->hasException)
- return;
+ int n = toInt32(value);
+ signed char v = static_cast<signed char>(n);
data[index] = v;
}
@@ -75,23 +90,22 @@ ReturnedValue UInt8ArrayRead(const char *data, int index)
return Encode((int)(unsigned char)data[index]);
}
-void UInt8ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void UInt8ArrayWrite(char *data, int index, const Value &value)
{
- unsigned char v = (unsigned char)value.toUInt32();
- if (e->hasException)
- return;
+ int n = toInt32(value);
+ unsigned char v = static_cast<unsigned char>(uint(n));
data[index] = v;
}
-void UInt8ClampedArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void UInt8ClampedArrayWrite(char *data, int index, const Value &value)
{
+ Q_ASSERT(value.isNumber());
if (value.isInteger()) {
data[index] = (char)(unsigned char)qBound(0, value.integerValue(), 255);
return;
}
- double d = value.toNumber();
- if (e->hasException)
- return;
+ Q_ASSERT(value.isDouble());
+ double d = value.doubleValue();
// ### is there a way to optimise this?
if (d <= 0 || std::isnan(d)) {
data[index] = 0;
@@ -123,11 +137,10 @@ ReturnedValue Int16ArrayRead(const char *data, int index)
return Encode((int)*(const short *)(data + index));
}
-void Int16ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void Int16ArrayWrite(char *data, int index, const Value &value)
{
- short v = (short)value.toInt32();
- if (e->hasException)
- return;
+ int n = toInt32(value);
+ short v = static_cast<short>(n);
*(short *)(data + index) = v;
}
@@ -136,11 +149,10 @@ ReturnedValue UInt16ArrayRead(const char *data, int index)
return Encode((int)*(const unsigned short *)(data + index));
}
-void UInt16ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void UInt16ArrayWrite(char *data, int index, const Value &value)
{
- unsigned short v = (unsigned short)value.toInt32();
- if (e->hasException)
- return;
+ int n = toInt32(value);
+ unsigned short v = static_cast<unsigned short>(n);
*(unsigned short *)(data + index) = v;
}
@@ -149,11 +161,9 @@ ReturnedValue Int32ArrayRead(const char *data, int index)
return Encode(*(const int *)(data + index));
}
-void Int32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void Int32ArrayWrite(char *data, int index, const Value &value)
{
- int v = (int)value.toInt32();
- if (e->hasException)
- return;
+ int v = toInt32(value);
*(int *)(data + index) = v;
}
@@ -162,11 +172,10 @@ ReturnedValue UInt32ArrayRead(const char *data, int index)
return Encode(*(const unsigned int *)(data + index));
}
-void UInt32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void UInt32ArrayWrite(char *data, int index, const Value &value)
{
- unsigned int v = (unsigned int)value.toUInt32();
- if (e->hasException)
- return;
+ int n = toInt32(value);
+ unsigned v = static_cast<unsigned>(n);
*(unsigned int *)(data + index) = v;
}
@@ -175,11 +184,9 @@ ReturnedValue Float32ArrayRead(const char *data, int index)
return Encode(*(const float *)(data + index));
}
-void Float32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void Float32ArrayWrite(char *data, int index, const Value &value)
{
- float v = value.toNumber();
- if (e->hasException)
- return;
+ float v = toDouble(value);
*(float *)(data + index) = v;
}
@@ -188,11 +195,9 @@ ReturnedValue Float64ArrayRead(const char *data, int index)
return Encode(*(const double *)(data + index));
}
-void Float64ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value)
+void Float64ArrayWrite(char *data, int index, const Value &value)
{
- double v = value.toNumber();
- if (e->hasException)
- return;
+ double v = toDouble(value);
*(double *)(data + index) = v;
}
@@ -277,7 +282,7 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
for (uint i = 0; i < l; ++i) {
Primitive val;
val.setRawValue(read(src, i*srcElementSize));
- write(scope.engine, dest, i*destElementSize, val);
+ write(dest, i*destElementSize, val);
}
}
@@ -346,7 +351,10 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
ScopedValue val(scope);
while (idx < l) {
val = o->get(idx);
- array->d()->type->write(scope.engine, b, 0, val);
+ val = val->convertedToNumber();
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ array->d()->type->write(b, 0, val);
if (scope.engine->hasException)
return Encode::undefined();
++idx;
@@ -384,6 +392,8 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val
uint index = id.asArrayIndex();
Scope scope(static_cast<const Object *>(m)->engine());
Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
+ if (a->d()->buffer->isDetachedBuffer())
+ return scope.engine->throwTypeError();
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
@@ -409,13 +419,18 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
Scope scope(v4);
Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
+ if (a->d()->buffer->isDetachedBuffer())
+ return scope.engine->throwTypeError();
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
if (byteOffset + bytesPerElement > (uint)a->d()->buffer->byteLength())
return false;
- a->d()->type->write(scope.engine, a->d()->buffer->data->data(), byteOffset, value);
+ Value v = Primitive::fromReturnedValue(value.convertedToNumber());
+ if (scope.hasException() || a->d()->buffer->isDetachedBuffer())
+ return scope.engine->throwTypeError();
+ a->d()->type->write(a->d()->buffer->data->data(), byteOffset, v);
return true;
}
@@ -612,13 +627,15 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_fill(const FunctionObject *b,
double val = argc ? argv[0].toNumber() : std::numeric_limits<double>::quiet_NaN();
Value value = Primitive::fromDouble(val);
+ if (scope.hasException() || v->d()->buffer->isDetachedBuffer())
+ return scope.engine->throwTypeError();
char *data = v->d()->buffer->data->data();
uint bytesPerElement = v->d()->type->bytesPerElement;
uint byteOffset = v->d()->byteOffset;
while (k < fin) {
- v->d()->type->write(scope.engine, data, byteOffset + k * bytesPerElement, value);
+ v->d()->type->write(data, byteOffset + k * bytesPerElement, value);
k++;
}
@@ -1237,7 +1254,12 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
ScopedValue val(scope);
while (idx < l) {
val = o->get(idx);
- a->d()->type->write(scope.engine, b, 0, val);
+ if (scope.hasException())
+ return Encode::undefined();
+ val = val->convertedToNumber();
+ if (scope.hasException() || buffer->isDetachedBuffer())
+ return scope.engine->throwTypeError();
+ a->d()->type->write(b, 0, val);
if (scope.engine->hasException)
RETURN_UNDEFINED();
++idx;
@@ -1278,7 +1300,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
for (uint i = 0; i < l; ++i) {
Primitive val;
val.setRawValue(read(src, i*srcElementSize));
- write(scope.engine, dest, i*elementSize, val);
+ write(dest, i*elementSize, val);
}
if (srcCopy)
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 31698fa6d0..775ba61ddc 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -61,7 +61,7 @@ namespace QV4 {
struct ArrayBuffer;
typedef ReturnedValue (*TypedArrayRead)(const char *data, int index);
-typedef void (*TypedArrayWrite)(ExecutionEngine *engine, char *data, int index, const Value &value);
+typedef void (*TypedArrayWrite)(char *data, int index, const Value &value);
struct TypedArrayOperations {
int bytesPerElement;
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 6a6df3eb6d..e4be6b99dd 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -408,6 +408,7 @@ public:
}
static bool toBooleanImpl(Value val);
double toInteger() const;
+ inline ReturnedValue convertedToNumber() const;
inline double toNumber() const;
static double toNumberImpl(Value v);
double toNumberImpl() const { return toNumberImpl(*this); }
@@ -554,6 +555,15 @@ inline double Value::toNumber() const
return toNumberImpl();
}
+inline ReturnedValue Value::convertedToNumber() const
+{
+ if (isInteger() || isDouble())
+ return asReturnedValue();
+ Value v;
+ v.setDouble(toNumberImpl());
+ return v.asReturnedValue();
+}
+
inline
ReturnedValue Heap::Base::asReturnedValue() const
{
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index de21ad7fad..3d79b87652 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -683,7 +683,6 @@ built-ins/TypedArray/from/name.js fails
built-ins/TypedArray/from/prop-desc.js fails
built-ins/TypedArray/prototype/constructor.js fails
built-ins/TypedArray/prototype/fill/fill-values-conversion-operations-consistent-nan.js fails
-built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js fails
built-ins/TypedArray/prototype/slice/bit-precision.js fails
built-ins/TypedArray/prototype/sort/arraylength-internal.js fails
built-ins/TypedArray/prototype/sort/comparefn-call-throws.js fails
@@ -790,7 +789,6 @@ built-ins/TypedArrays/internals/Set/detached-buffer.js fails
built-ins/TypedArrays/internals/Set/key-is-minus-zero.js fails
built-ins/TypedArrays/internals/Set/key-is-not-integer.js fails
built-ins/TypedArrays/internals/Set/key-is-out-of-bounds.js fails
-built-ins/TypedArrays/internals/Set/tonumber-value-detached-buffer.js fails
built-ins/TypedArrays/internals/Set/tonumber-value-throws.js strictFails
built-ins/WeakMap/constructor.js fails
built-ins/WeakMap/empty-iterable.js fails