Added JS exceptions + fixed up floating precision mess up

This commit is contained in:
Atlante45 2014-07-11 16:23:19 -07:00
parent d456adff1d
commit b9fe5b2ef1
7 changed files with 105 additions and 52 deletions

View file

@ -48,7 +48,17 @@ _scriptEngine(scriptEngine) {
engine()->globalObject().setProperty(name(), _ctor);
}
QScriptValue ArrayBufferClass::newInstance(quint32 size) {
QScriptValue ArrayBufferClass::newInstance(qint32 size) {
const qint32 MAX_LENGTH = 100000000;
if (size < 0) {
engine()->evaluate("throw \"ArgumentError: negative length\"");
return QScriptValue();
}
if (size > MAX_LENGTH) {
engine()->evaluate("throw \"ArgumentError: absurd length\"");
return QScriptValue();
}
engine()->reportAdditionalMemoryCost(size);
QScriptEngine* eng = engine();
QVariant variant = QVariant::fromValue(QByteArray(size, 0));

View file

@ -26,7 +26,7 @@ class ArrayBufferClass : public QObject, public QScriptClass {
Q_OBJECT
public:
ArrayBufferClass(ScriptEngine* scriptEngine);
QScriptValue newInstance(quint32 size);
QScriptValue newInstance(qint32 size);
QScriptValue newInstance(const QByteArray& ba);
ScriptEngine* getScriptEngine() { return _scriptEngine; }

View file

@ -64,7 +64,7 @@ QScriptValue DataViewClass::construct(QScriptContext *context, QScriptEngine *en
}
if (byteOffsetArg.isNumber() &&
(byteOffsetArg.toInt32() < 0 ||
byteOffsetArg.toInt32() >= arrayBuffer->size())) {
byteOffsetArg.toInt32() > arrayBuffer->size())) {
engine->evaluate("throw \"RangeError: byteOffset out of range\"");
return QScriptValue();
}

View file

@ -26,7 +26,10 @@ QByteArray* DataViewPrototype::thisArrayBuffer() const {
return qscriptvalue_cast<QByteArray*>(bufferObject.data());
}
bool DataViewPrototype::realOffset(quint32& offset, size_t size) const {
bool DataViewPrototype::realOffset(qint32& offset, size_t size) const {
if (offset < 0) {
return false;
}
quint32 viewOffset = thisObject().data().property(BYTE_OFFSET_PROPERTY_NAME).toInt32();
quint32 viewLength = thisObject().data().property(BYTE_LENGTH_PROPERTY_NAME).toInt32();
//qDebug() << "View Offset: " << viewOffset << ", View Lenght: " << viewLength;
@ -38,7 +41,7 @@ bool DataViewPrototype::realOffset(quint32& offset, size_t size) const {
///////////////// GETTERS ////////////////////////////
qint32 DataViewPrototype::getInt8(quint32 byteOffset) {
qint32 DataViewPrototype::getInt8(qint32 byteOffset) {
if (realOffset(byteOffset, sizeof(qint8))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
@ -51,7 +54,7 @@ qint32 DataViewPrototype::getInt8(quint32 byteOffset) {
return 0;
}
quint32 DataViewPrototype::getUint8(quint32 byteOffset) {
quint32 DataViewPrototype::getUint8(qint32 byteOffset) {
if (realOffset(byteOffset, sizeof(quint8))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
@ -64,7 +67,7 @@ quint32 DataViewPrototype::getUint8(quint32 byteOffset) {
return 0;
}
qint32 DataViewPrototype::getInt16(quint32 byteOffset, bool littleEndian) {
qint32 DataViewPrototype::getInt16(qint32 byteOffset, bool littleEndian) {
if (realOffset(byteOffset, sizeof(qint16))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
@ -78,7 +81,7 @@ qint32 DataViewPrototype::getInt16(quint32 byteOffset, bool littleEndian) {
return 0;
}
quint32 DataViewPrototype::getUint16(quint32 byteOffset, bool littleEndian) {
quint32 DataViewPrototype::getUint16(qint32 byteOffset, bool littleEndian) {
if (realOffset(byteOffset, sizeof(quint16))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
@ -92,7 +95,7 @@ quint32 DataViewPrototype::getUint16(quint32 byteOffset, bool littleEndian) {
return 0;
}
qint32 DataViewPrototype::getInt32(quint32 byteOffset, bool littleEndian) {
qint32 DataViewPrototype::getInt32(qint32 byteOffset, bool littleEndian) {
if (realOffset(byteOffset, sizeof(qint32))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
@ -106,7 +109,7 @@ qint32 DataViewPrototype::getInt32(quint32 byteOffset, bool littleEndian) {
return 0;
}
quint32 DataViewPrototype::getUint32(quint32 byteOffset, bool littleEndian) {
quint32 DataViewPrototype::getUint32(qint32 byteOffset, bool littleEndian) {
if (realOffset(byteOffset, sizeof(quint32))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
@ -120,25 +123,28 @@ quint32 DataViewPrototype::getUint32(quint32 byteOffset, bool littleEndian) {
return 0;
}
float DataViewPrototype::getFloat32(quint32 byteOffset, bool littleEndian) {
float DataViewPrototype::getFloat32(qint32 byteOffset, bool littleEndian) {
if (realOffset(byteOffset, sizeof(float))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
float result;
stream >> result;
qDebug() << "Get: " << result;
return result;
}
thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\"");
return 0;
}
double DataViewPrototype::getFloat64(quint32 byteOffset, bool littleEndian) {
double DataViewPrototype::getFloat64(qint32 byteOffset, bool littleEndian) {
if (realOffset(byteOffset, sizeof(double))) {
QDataStream stream(*thisArrayBuffer());
stream.skipRawData(byteOffset);
stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian);
stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
double result;
stream >> result;
@ -150,7 +156,7 @@ double DataViewPrototype::getFloat64(quint32 byteOffset, bool littleEndian) {
///////////////// SETTERS ////////////////////////////
void DataViewPrototype::setInt8(quint32 byteOffset, qint32 value) {
void DataViewPrototype::setInt8(qint32 byteOffset, qint32 value) {
if (realOffset(byteOffset, sizeof(qint8))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
@ -161,7 +167,7 @@ void DataViewPrototype::setInt8(quint32 byteOffset, qint32 value) {
}
}
void DataViewPrototype::setUint8(quint32 byteOffset, quint32 value) {
void DataViewPrototype::setUint8(qint32 byteOffset, quint32 value) {
if (realOffset(byteOffset, sizeof(quint8))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
@ -172,7 +178,7 @@ void DataViewPrototype::setUint8(quint32 byteOffset, quint32 value) {
}
}
void DataViewPrototype::setInt16(quint32 byteOffset, qint32 value, bool littleEndian) {
void DataViewPrototype::setInt16(qint32 byteOffset, qint32 value, bool littleEndian) {
if (realOffset(byteOffset, sizeof(qint16))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
@ -184,7 +190,7 @@ void DataViewPrototype::setInt16(quint32 byteOffset, qint32 value, bool littleEn
}
}
void DataViewPrototype::setUint16(quint32 byteOffset, quint32 value, bool littleEndian) {
void DataViewPrototype::setUint16(qint32 byteOffset, quint32 value, bool littleEndian) {
if (realOffset(byteOffset, sizeof(quint16))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
@ -196,7 +202,7 @@ void DataViewPrototype::setUint16(quint32 byteOffset, quint32 value, bool little
}
}
void DataViewPrototype::setInt32(quint32 byteOffset, qint32 value, bool littleEndian) {
void DataViewPrototype::setInt32(qint32 byteOffset, qint32 value, bool littleEndian) {
if (realOffset(byteOffset, sizeof(qint32))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
@ -208,7 +214,7 @@ void DataViewPrototype::setInt32(quint32 byteOffset, qint32 value, bool littleEn
}
}
void DataViewPrototype::setUint32(quint32 byteOffset, quint32 value, bool littleEndian) {
void DataViewPrototype::setUint32(qint32 byteOffset, quint32 value, bool littleEndian) {
if (realOffset(byteOffset, sizeof(quint32))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
@ -220,11 +226,12 @@ void DataViewPrototype::setUint32(quint32 byteOffset, quint32 value, bool little
}
}
void DataViewPrototype::setFloat32(quint32 byteOffset, float value, bool littleEndian) {
void DataViewPrototype::setFloat32(qint32 byteOffset, float value, bool littleEndian) {
if (realOffset(byteOffset, sizeof(float))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
stream << value;
} else {
@ -232,11 +239,12 @@ void DataViewPrototype::setFloat32(quint32 byteOffset, float value, bool littleE
}
}
void DataViewPrototype::setFloat64(quint32 byteOffset, double value, bool littleEndian) {
void DataViewPrototype::setFloat64(qint32 byteOffset, double value, bool littleEndian) {
if (realOffset(byteOffset, sizeof(double))) {
QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite);
stream.skipRawData(byteOffset);
stream.setByteOrder((littleEndian) ? QDataStream::LittleEndian : QDataStream::BigEndian);
stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
stream << value;
} else {

View file

@ -31,14 +31,14 @@ public slots:
//
// These methods raise an exception if they would read
// beyond the end of the view.
qint32 getInt8(quint32 byteOffset);
quint32 getUint8(quint32 byteOffset);
qint32 getInt16(quint32 byteOffset, bool littleEndian = false);
quint32 getUint16(quint32 byteOffset, bool littleEndian = false);
qint32 getInt32(quint32 byteOffset, bool littleEndian = false);
quint32 getUint32(quint32 byteOffset, bool littleEndian = false);
float getFloat32(quint32 byteOffset, bool littleEndian = false);
double getFloat64(quint32 byteOffset, bool littleEndian = false);
qint32 getInt8(qint32 byteOffset);
quint32 getUint8(qint32 byteOffset);
qint32 getInt16(qint32 byteOffset, bool littleEndian = false);
quint32 getUint16(qint32 byteOffset, bool littleEndian = false);
qint32 getInt32(qint32 byteOffset, bool littleEndian = false);
quint32 getUint32(qint32 byteOffset, bool littleEndian = false);
float getFloat32(qint32 byteOffset, bool littleEndian = false);
double getFloat64(qint32 byteOffset, bool littleEndian = false);
// Stores a value of the given type at the specified byte offset
// from the start of the view. There is no alignment constraint;
@ -51,18 +51,18 @@ public slots:
//
// These methods raise an exception if they would write
// beyond the end of the view.
void setInt8(quint32 byteOffset, qint32 value);
void setUint8(quint32 byteOffset, quint32 value);
void setInt16(quint32 byteOffset, qint32 value, bool littleEndian = false);
void setUint16(quint32 byteOffset, quint32 value, bool littleEndian = false);
void setInt32(quint32 byteOffset, qint32 value, bool littleEndian = false);
void setUint32(quint32 byteOffset, quint32 value, bool littleEndian = false);
void setFloat32(quint32 byteOffset, float value, bool littleEndian = false);
void setFloat64(quint32 byteOffset, double value, bool littleEndian = false);
void setInt8(qint32 byteOffset, qint32 value);
void setUint8(qint32 byteOffset, quint32 value);
void setInt16(qint32 byteOffset, qint32 value, bool littleEndian = false);
void setUint16(qint32 byteOffset, quint32 value, bool littleEndian = false);
void setInt32(qint32 byteOffset, qint32 value, bool littleEndian = false);
void setUint32(qint32 byteOffset, quint32 value, bool littleEndian = false);
void setFloat32(qint32 byteOffset, float value, bool littleEndian = false);
void setFloat64(qint32 byteOffset, double value, bool littleEndian = false);
private:
QByteArray* thisArrayBuffer() const;
bool realOffset(quint32& offset, size_t size) const;
bool realOffset(qint32& offset, size_t size) const;
};
#endif // hifi_DataViewPrototype_h

View file

@ -56,6 +56,7 @@ QScriptValue TypedArray::newInstance(QScriptValue array) {
}
return newArray;
}
engine()->evaluate("throw \"ArgumentError: not an array\"");
return QScriptValue();
}
@ -200,19 +201,23 @@ QByteArray* TypedArrayPrototype::thisArrayBuffer() const {
return qscriptvalue_cast<QByteArray*>(bufferObject.data());
}
void TypedArrayPrototype::set(QScriptValue array, quint32 offset) {
void TypedArrayPrototype::set(QScriptValue array, qint32 offset) {
TypedArray* typedArray = static_cast<TypedArray*>(parent());
if (array.isArray()) {
if (array.isArray() || typedArray) {
if (offset < 0) {
engine()->evaluate("throw \"ArgumentError: negative offset\"");
}
quint32 length = array.property("length").toInt32();
if (offset + length > thisObject().data().property(typedArray->_lengthName).toInt32()) {
// TODO throw an error maybe?
engine()->evaluate("throw \"ArgumentError: array does not fit\"");
return;
}
for (int i = 0; i < length; ++i) {
thisObject().setProperty(QString::number(offset + i), array.property(QString::number(i)));
}
} else {
engine()->evaluate("throw \"ArgumentError: not an array\"");
}
// TODO handle typed arrays
}
QScriptValue TypedArrayPrototype::subarray(qint32 begin) {
@ -411,15 +416,31 @@ Float32ArrayClass::Float32ArrayClass(ScriptEngine* scriptEngine) : TypedArray(sc
QScriptValue Float32ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) {
QByteArray* arrayBuffer = qscriptvalue_cast<QByteArray*>(object.data().property(_bufferName).data());
QScriptValue result = propertyHelper<float>(arrayBuffer, name, id);
return (result.isValid()) ? result : TypedArray::property(object, name, id);
QByteArray* arrayBuffer = qscriptvalue_cast<QByteArray*>(object.data().property(_bufferName).data());bool ok = false;
name.toArrayIndex(&ok);
if (ok && arrayBuffer) {
QDataStream stream(*arrayBuffer);
stream.skipRawData(id);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
float result;
stream >> result;
return result;
}
return TypedArray::property(object, name, id);
}
void Float32ArrayClass::setProperty(QScriptValue &object, const QScriptString &name,
uint id, const QScriptValue &value) {
QByteArray *ba = qscriptvalue_cast<QByteArray*>(object.data().property(_bufferName).data());
setPropertyHelper<float>(ba, name, id, value);
if (ba && value.isNumber()) {
QDataStream stream(ba, QIODevice::ReadWrite);
stream.skipRawData(id);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
stream << (float)value.toNumber();
}
}
Float64ArrayClass::Float64ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, FLOAT_64_ARRAY_CLASS_NAME) {
@ -428,16 +449,30 @@ Float64ArrayClass::Float64ArrayClass(ScriptEngine* scriptEngine) : TypedArray(sc
QScriptValue Float64ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) {
QByteArray* arrayBuffer = qscriptvalue_cast<QByteArray*>(object.data().property(_bufferName).data());
QScriptValue result = propertyHelper<double>(arrayBuffer, name, id);
return (result.isValid()) ? result : TypedArray::property(object, name, id);
QByteArray* arrayBuffer = qscriptvalue_cast<QByteArray*>(object.data().property(_bufferName).data());bool ok = false;
name.toArrayIndex(&ok);
if (ok && arrayBuffer) {
QDataStream stream(*arrayBuffer);
stream.skipRawData(id);
stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
double result;
stream >> result;
return result;
}
return TypedArray::property(object, name, id);
}
void Float64ArrayClass::setProperty(QScriptValue &object, const QScriptString &name,
uint id, const QScriptValue &value) {
QByteArray *ba = qscriptvalue_cast<QByteArray*>(object.data().property(_bufferName).data());
setPropertyHelper<double>(ba, name, id, value);
if (ba && value.isNumber()) {
QDataStream stream(ba, QIODevice::ReadWrite);
stream.skipRawData(id);
stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
stream << (double)value.toNumber();
}
}

View file

@ -69,7 +69,7 @@ public:
TypedArrayPrototype(QObject* parent = NULL);
public slots:
void set(QScriptValue array, quint32 offset = 0);
void set(QScriptValue array, qint32 offset = 0);
QScriptValue subarray(qint32 begin);
QScriptValue subarray(qint32 begin, qint32 end);