From 30fd4e27d05d08a0a71a1a2bc515ba4868c9ed93 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 14 Jul 2014 10:43:01 -0700 Subject: [PATCH] pre-CR cleanup --- .../script-engine/src/ArrayBufferClass.cpp | 16 +- .../script-engine/src/ArrayBufferClass.h | 8 +- .../src/ArrayBufferPrototype.cpp | 1 - .../src/ArrayBufferViewClass.cpp | 60 +----- .../script-engine/src/ArrayBufferViewClass.h | 10 +- libraries/script-engine/src/DataViewClass.cpp | 5 +- .../script-engine/src/DataViewPrototype.cpp | 22 +- libraries/script-engine/src/ScriptEngine.cpp | 1 - libraries/script-engine/src/ScriptEngine.h | 2 +- .../script-engine/src/TypedArrayPrototype.cpp | 106 ++++++++++ .../script-engine/src/TypedArrayPrototype.h | 33 +++ libraries/script-engine/src/TypedArrays.cpp | 191 +++++------------- libraries/script-engine/src/TypedArrays.h | 54 ++--- 13 files changed, 241 insertions(+), 268 deletions(-) create mode 100644 libraries/script-engine/src/TypedArrayPrototype.cpp create mode 100644 libraries/script-engine/src/TypedArrayPrototype.h diff --git a/libraries/script-engine/src/ArrayBufferClass.cpp b/libraries/script-engine/src/ArrayBufferClass.cpp index f8299266fd..ab33b5ffe7 100644 --- a/libraries/script-engine/src/ArrayBufferClass.cpp +++ b/libraries/script-engine/src/ArrayBufferClass.cpp @@ -23,10 +23,9 @@ static const QString CLASS_NAME = "ArrayBuffer"; Q_DECLARE_METATYPE(QByteArray*) ArrayBufferClass::ArrayBufferClass(ScriptEngine* scriptEngine) : -QObject(scriptEngine->getScriptEngine()), -QScriptClass(scriptEngine->getScriptEngine()), +QObject(scriptEngine->getEngine()), +QScriptClass(scriptEngine->getEngine()), _scriptEngine(scriptEngine) { - qDebug() << "Created with engine: " << engine(); qScriptRegisterMetaType(engine(), toScriptValue, fromScriptValue); QScriptValue global = engine()->globalObject(); @@ -40,15 +39,16 @@ _scriptEngine(scriptEngine) { QScriptEngine::SkipMethodsInEnumeration | QScriptEngine::ExcludeSuperClassMethods | QScriptEngine::ExcludeSuperClassProperties); - _proto.setPrototype(global.property("Object").property("prototype")); + // Register constructor _ctor = engine()->newFunction(construct, _proto); _ctor.setData(engine()->toScriptValue(this)); engine()->globalObject().setProperty(name(), _ctor); // Registering other array types + // The script engine is there parent so it'll delete them with itself new DataViewClass(scriptEngine); new Int8ArrayClass(scriptEngine); new Uint8ArrayClass(scriptEngine); @@ -87,11 +87,10 @@ QScriptValue ArrayBufferClass::newInstance(const QByteArray& ba) { QScriptValue ArrayBufferClass::construct(QScriptContext* context, QScriptEngine* engine) { ArrayBufferClass* cls = qscriptvalue_cast(context->callee().data()); if (!cls) { + // return if callee (function called) is not of type ArrayBuffer return QScriptValue(); } - QScriptValue arg = context->argument(0); - if (!arg.isValid() || !arg.isNumber()) { return QScriptValue(); } @@ -100,6 +99,7 @@ QScriptValue ArrayBufferClass::construct(QScriptContext* context, QScriptEngine* QScriptValue newObject = cls->newInstance(size); if (context->isCalledAsConstructor()) { + // if called with keyword new, replace this object. context->setThisObject(newObject); return engine->undefinedValue(); } @@ -118,8 +118,8 @@ QScriptClass::QueryFlags ArrayBufferClass::queryProperty(const QScriptValue& obj return 0; // No access } -QScriptValue ArrayBufferClass::property(const QScriptValue &object, - const QScriptString &name, uint id) { +QScriptValue ArrayBufferClass::property(const QScriptValue& object, + const QScriptString& name, uint id) { QByteArray* ba = qscriptvalue_cast(object.data()); if (ba && name == _byteLength) { return ba->length(); diff --git a/libraries/script-engine/src/ArrayBufferClass.h b/libraries/script-engine/src/ArrayBufferClass.h index c7b4d447dd..f7ad8ad4bd 100644 --- a/libraries/script-engine/src/ArrayBufferClass.h +++ b/libraries/script-engine/src/ArrayBufferClass.h @@ -29,19 +29,19 @@ public: QScriptValue newInstance(qint32 size); QScriptValue newInstance(const QByteArray& ba); - ScriptEngine* getScriptEngine() { return _scriptEngine; } - QueryFlags queryProperty(const QScriptValue& object, const QScriptString& name, QueryFlags flags, uint* id); - QScriptValue property(const QScriptValue &object, - const QScriptString &name, uint id); + QScriptValue property(const QScriptValue& object, + const QScriptString& name, uint id); QScriptValue::PropertyFlags propertyFlags(const QScriptValue& object, const QScriptString& name, uint id); QString name() const; QScriptValue prototype() const; + ScriptEngine* getEngine() { return _scriptEngine; } + private: static QScriptValue construct(QScriptContext* context, QScriptEngine* engine); diff --git a/libraries/script-engine/src/ArrayBufferPrototype.cpp b/libraries/script-engine/src/ArrayBufferPrototype.cpp index 37db5f3eec..53ebebc740 100644 --- a/libraries/script-engine/src/ArrayBufferPrototype.cpp +++ b/libraries/script-engine/src/ArrayBufferPrototype.cpp @@ -12,7 +12,6 @@ #include #include "ArrayBufferClass.h" - #include "ArrayBufferPrototype.h" Q_DECLARE_METATYPE(QByteArray*) diff --git a/libraries/script-engine/src/ArrayBufferViewClass.cpp b/libraries/script-engine/src/ArrayBufferViewClass.cpp index a01f239512..aad2e6add7 100644 --- a/libraries/script-engine/src/ArrayBufferViewClass.cpp +++ b/libraries/script-engine/src/ArrayBufferViewClass.cpp @@ -14,8 +14,8 @@ Q_DECLARE_METATYPE(QByteArray*) ArrayBufferViewClass::ArrayBufferViewClass(ScriptEngine* scriptEngine) : -QObject(scriptEngine->getScriptEngine()), -QScriptClass(scriptEngine->getScriptEngine()), +QObject(scriptEngine->getEngine()), +QScriptClass(scriptEngine->getEngine()), _scriptEngine(scriptEngine) { // Save string handles for quick lookup _bufferName = engine()->toStringHandle(BUFFER_PROPERTY_NAME.toLatin1()); @@ -32,8 +32,8 @@ QScriptClass::QueryFlags ArrayBufferViewClass::queryProperty(const QScriptValue& return 0; // No access } -QScriptValue ArrayBufferViewClass::property(const QScriptValue &object, - const QScriptString &name, uint id) { +QScriptValue ArrayBufferViewClass::property(const QScriptValue& object, + const QScriptString& name, uint id) { if (name == _bufferName) { return object.data().property(_bufferName); } @@ -50,55 +50,3 @@ QScriptValue::PropertyFlags ArrayBufferViewClass::propertyFlags(const QScriptVal const QScriptString& name, uint id) { return QScriptValue::Undeletable; } - -//QScriptClass::QueryFlags DataViewClass::queryProperty(const QScriptValue& object, -// const QScriptString& name, -// QueryFlags flags, uint* id) { -// QByteArray* arrayBuffer = qscriptvalue_cast(object.property(_bufferName).data()); -// bool ok = false; -// int pos = name.toArrayIndex(&ok); -// -// // Check that name is a valid index and arrayBuffer exists -// if (ok && arrayBuffer && pos > 0 && pos < arrayBuffer->size()) { -// *id = pos; // save pos to avoid recomputation -// return HandlesReadAccess | HandlesWriteAccess; // Read/Write access -// } -// -// return ArrayBufferViewClass::queryProperty(object, name, flags, id); -//} -// -//QScriptValue DataViewClass::property(const QScriptValue &object, -// const QScriptString &name, uint id) { -// QByteArray* arrayBuffer = qscriptvalue_cast(object.property(_bufferName).data()); -// bool ok = false; -// name.toArrayIndex(&ok); -// -// if (ok && arrayBuffer) { -// return (*arrayBuffer)[id]; -// } -// -// return ArrayBufferViewClass::queryProperty(object, name, flags, id); -//} -// -//void DataViewClass::setProperty(QScriptValue &object, -// const QScriptString &name, -// uint id, const QScriptValue &value) { -// QByteArray *ba = qscriptvalue_cast(object.data()); -// if (!ba) -// return; -// if (name == length) { -// resize(*ba, value.toInt32()); -// } else { -// qint32 pos = id; -// if (pos < 0) -// return; -// if (ba->size() <= pos) -// resize(*ba, pos + 1); -// (*ba)[pos] = char(value.toInt32()); -// } -//} -// -//QScriptValue::PropertyFlags DataViewClass::propertyFlags(const QScriptValue& object, -// const QScriptString& name, uint id) { -// return QScriptValue::Undeletable; -//} diff --git a/libraries/script-engine/src/ArrayBufferViewClass.h b/libraries/script-engine/src/ArrayBufferViewClass.h index acc061c8a3..b673ebf280 100644 --- a/libraries/script-engine/src/ArrayBufferViewClass.h +++ b/libraries/script-engine/src/ArrayBufferViewClass.h @@ -34,12 +34,12 @@ public: ScriptEngine* getScriptEngine() { return _scriptEngine; } virtual QueryFlags queryProperty(const QScriptValue& object, - const QScriptString& name, - QueryFlags flags, uint* id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, uint id); + const QScriptString& name, + QueryFlags flags, uint* id); + virtual QScriptValue property(const QScriptValue& object, + const QScriptString& name, uint id); virtual QScriptValue::PropertyFlags propertyFlags(const QScriptValue& object, - const QScriptString& name, uint id); + const QScriptString& name, uint id); protected: // JS Object attributes QScriptString _bufferName; diff --git a/libraries/script-engine/src/DataViewClass.cpp b/libraries/script-engine/src/DataViewClass.cpp index efb45daf3f..a65bdff617 100644 --- a/libraries/script-engine/src/DataViewClass.cpp +++ b/libraries/script-engine/src/DataViewClass.cpp @@ -29,12 +29,11 @@ DataViewClass::DataViewClass(ScriptEngine* scriptEngine) : ArrayBufferViewClass( QScriptEngine::SkipMethodsInEnumeration | QScriptEngine::ExcludeSuperClassMethods | QScriptEngine::ExcludeSuperClassProperties); - _proto.setPrototype(global.property("Object").property("prototype")); + // Register constructor _ctor = engine()->newFunction(construct, _proto); _ctor.setData(engine()->toScriptValue(this)); - engine()->globalObject().setProperty(name(), _ctor); } @@ -47,7 +46,7 @@ QScriptValue DataViewClass::newInstance(QScriptValue buffer, quint32 byteOffset, return engine()->newObject(this, data); } -QScriptValue DataViewClass::construct(QScriptContext *context, QScriptEngine *engine) { +QScriptValue DataViewClass::construct(QScriptContext* context, QScriptEngine* engine) { DataViewClass* cls = qscriptvalue_cast(context->callee().data()); if (!cls || context->argumentCount() < 1) { return QScriptValue(); diff --git a/libraries/script-engine/src/DataViewPrototype.cpp b/libraries/script-engine/src/DataViewPrototype.cpp index 29264e9bc5..91f7e01b50 100644 --- a/libraries/script-engine/src/DataViewPrototype.cpp +++ b/libraries/script-engine/src/DataViewPrototype.cpp @@ -36,8 +36,6 @@ bool DataViewPrototype::realOffset(qint32& offset, size_t size) const { return (offset + size) <= viewOffset + viewLength; } -///////////////// GETTERS //////////////////////////// - qint32 DataViewPrototype::getInt8(qint32 byteOffset) { if (realOffset(byteOffset, sizeof(qint8))) { QDataStream stream(*thisArrayBuffer()); @@ -149,7 +147,7 @@ QScriptValue DataViewPrototype::getFloat64(qint32 byteOffset, bool littleEndian) double result; stream >> result; if (isNaN(result)) { - return QScriptValue(); + return QScriptValue(NAN); } return result; @@ -158,8 +156,6 @@ QScriptValue DataViewPrototype::getFloat64(qint32 byteOffset, bool littleEndian) return QScriptValue(); } -///////////////// SETTERS //////////////////////////// - void DataViewPrototype::setInt8(qint32 byteOffset, qint32 value) { if (realOffset(byteOffset, sizeof(qint8))) { QDataStream stream(thisArrayBuffer(), QIODevice::ReadWrite); @@ -167,7 +163,7 @@ void DataViewPrototype::setInt8(qint32 byteOffset, qint32 value) { stream << (qint8)value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } @@ -178,7 +174,7 @@ void DataViewPrototype::setUint8(qint32 byteOffset, quint32 value) { stream << (quint8)value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } @@ -190,7 +186,7 @@ void DataViewPrototype::setInt16(qint32 byteOffset, qint32 value, bool littleEnd stream << (qint16)value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } @@ -202,7 +198,7 @@ void DataViewPrototype::setUint16(qint32 byteOffset, quint32 value, bool littleE stream << (quint16)value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } @@ -214,7 +210,7 @@ void DataViewPrototype::setInt32(qint32 byteOffset, qint32 value, bool littleEnd stream << (qint32)value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } @@ -226,7 +222,7 @@ void DataViewPrototype::setUint32(qint32 byteOffset, quint32 value, bool littleE stream << (quint32)value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } @@ -239,7 +235,7 @@ void DataViewPrototype::setFloat32(qint32 byteOffset, float value, bool littleEn stream << value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } @@ -252,7 +248,7 @@ void DataViewPrototype::setFloat64(qint32 byteOffset, double value, bool littleE stream << value; } else { - thisObject().engine()->evaluate("throw \"1RangeError: byteOffset out of range\""); + thisObject().engine()->evaluate("throw \"RangeError: byteOffset out of range\""); } } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a224b9fa33..cd7c2670ec 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -143,7 +143,6 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL, QTextStream in(&scriptFile); _scriptContents = in.readAll(); } else { - qDebug() << "ERROR Loading file:" << fileName; emit errorMessage("ERROR Loading file:" + fileName); } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 3dda172044..0eda74914f 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -57,7 +57,7 @@ public: /// Access the ModelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener static ModelsScriptingInterface* getModelsScriptingInterface() { return &_modelsScriptingInterface; } - QScriptEngine* getScriptEngine() { return &_engine; } + QScriptEngine* getEngine() { return &_engine; } ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } /// sets the script contents, will return false if failed, will fail if script is already running diff --git a/libraries/script-engine/src/TypedArrayPrototype.cpp b/libraries/script-engine/src/TypedArrayPrototype.cpp new file mode 100644 index 0000000000..37274dd080 --- /dev/null +++ b/libraries/script-engine/src/TypedArrayPrototype.cpp @@ -0,0 +1,106 @@ +// +// TypedArrayPrototype.cpp +// +// +// Created by Clement on 7/14/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TypedArrays.h" + +#include "TypedArrayPrototype.h" + +Q_DECLARE_METATYPE(QByteArray*) + +TypedArrayPrototype::TypedArrayPrototype(QObject* parent) : QObject(parent) { +} + +QByteArray* TypedArrayPrototype::thisArrayBuffer() const { + QScriptValue bufferObject = thisObject().data().property(BUFFER_PROPERTY_NAME); + return qscriptvalue_cast(bufferObject.data()); +} + +void TypedArrayPrototype::set(QScriptValue array, qint32 offset) { + TypedArray* typedArray = static_cast(parent()); + 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()) { + 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\""); + } +} + +QScriptValue TypedArrayPrototype::subarray(qint32 begin) { + TypedArray* typedArray = static_cast(parent()); + QScriptValue arrayBuffer = thisObject().data().property(typedArray->_bufferName); + qint32 byteOffset = thisObject().data().property(typedArray->_byteOffsetName).toInt32(); + qint32 length = thisObject().data().property(typedArray->_lengthName).toInt32(); + qint32 bytesPerElement = typedArray->_bytesPerElement; + + // if indices < 0 then they start from the end of the array + begin = (begin < 0) ? length + begin : begin; + + // here we clamp the indices to fit the array + begin = glm::clamp(begin, 0, (length - 1)); + + byteOffset += begin * bytesPerElement; + return typedArray->newInstance(arrayBuffer, byteOffset, length - begin); +} + +QScriptValue TypedArrayPrototype::subarray(qint32 begin, qint32 end) { + TypedArray* typedArray = static_cast(parent()); + QScriptValue arrayBuffer = thisObject().data().property(typedArray->_bufferName); + qint32 byteOffset = thisObject().data().property(typedArray->_byteOffsetName).toInt32(); + qint32 length = thisObject().data().property(typedArray->_lengthName).toInt32(); + qint32 bytesPerElement = typedArray->_bytesPerElement; + + // if indices < 0 then they start from the end of the array + begin = (begin < 0) ? length + begin : begin; + end = (end < 0) ? length + end : end; + + // here we clamp the indices to fit the array + begin = glm::clamp(begin, 0, (length - 1)); + end = glm::clamp(end, 0, (length - 1)); + + byteOffset += begin * bytesPerElement; + length = (end - begin > 0) ? end - begin : 0; + return typedArray->newInstance(arrayBuffer, byteOffset, length); +} + +QScriptValue TypedArrayPrototype::get(quint32 index) { + TypedArray* typedArray = static_cast(parent()); + QScriptString name = engine()->toStringHandle(QString::number(index)); + uint id; + QScriptClass::QueryFlags flags = typedArray->queryProperty(thisObject(), + name, + QScriptClass::HandlesReadAccess, &id); + if (QScriptClass::HandlesReadAccess & flags) { + return typedArray->property(thisObject(), name, id); + } + return QScriptValue(); +} + +void TypedArrayPrototype::set(quint32 index, QScriptValue& value) { + TypedArray* typedArray = static_cast(parent()); + QScriptValue object = thisObject(); + QScriptString name = engine()->toStringHandle(QString::number(index)); + uint id; + QScriptClass::QueryFlags flags = typedArray->queryProperty(object, + name, + QScriptClass::HandlesWriteAccess, &id); + if (QScriptClass::HandlesWriteAccess & flags) { + typedArray->setProperty(object, name, id, value); + } +} diff --git a/libraries/script-engine/src/TypedArrayPrototype.h b/libraries/script-engine/src/TypedArrayPrototype.h new file mode 100644 index 0000000000..86d578ace0 --- /dev/null +++ b/libraries/script-engine/src/TypedArrayPrototype.h @@ -0,0 +1,33 @@ +// +// TypedArrayPrototype.h +// +// +// Created by Clement on 7/14/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_TypedArrayPrototype_h +#define hifi_TypedArrayPrototype_h + +#include "ArrayBufferViewClass.h" + +class TypedArrayPrototype : public QObject, public QScriptable { + Q_OBJECT +public: + TypedArrayPrototype(QObject* parent = NULL); + +public slots: + void set(QScriptValue array, qint32 offset = 0); + QScriptValue subarray(qint32 begin); + QScriptValue subarray(qint32 begin, qint32 end); + + QScriptValue get(quint32 index); + void set(quint32 index, QScriptValue& value); +private: + QByteArray* thisArrayBuffer() const; +}; + +#endif // hifi_TypedArrayPrototype_h \ No newline at end of file diff --git a/libraries/script-engine/src/TypedArrays.cpp b/libraries/script-engine/src/TypedArrays.cpp index 6b461fc6fb..72e84859c4 100644 --- a/libraries/script-engine/src/TypedArrays.cpp +++ b/libraries/script-engine/src/TypedArrays.cpp @@ -12,6 +12,7 @@ #include #include "ScriptEngine.h" +#include "TypedArrayPrototype.h" #include "TypedArrays.h" @@ -30,12 +31,11 @@ TypedArray::TypedArray(ScriptEngine* scriptEngine, QString name) : ArrayBufferVi QScriptEngine::SkipMethodsInEnumeration | QScriptEngine::ExcludeSuperClassMethods | QScriptEngine::ExcludeSuperClassProperties); - _proto.setPrototype(global.property("Object").property("prototype")); + // Register constructor _ctor = engine()->newFunction(construct, _proto); _ctor.setData(engine()->toScriptValue(this)); - engine()->globalObject().setProperty(_name, _ctor); } @@ -46,8 +46,9 @@ QScriptValue TypedArray::newInstance(quint32 length) { } QScriptValue TypedArray::newInstance(QScriptValue array) { - if (array.property("length").isValid()) { - quint32 length = array.property("length").toInt32(); + const QString ARRAY_LENGTH_HANDLE = "length"; + if (array.property(ARRAY_LENGTH_HANDLE).isValid()) { + quint32 length = array.property(ARRAY_LENGTH_HANDLE).toInt32(); QScriptValue newArray = newInstance(length); for (int i = 0; i < length; ++i) { QScriptValue value = array.property(QString::number(i)); @@ -70,12 +71,11 @@ QScriptValue TypedArray::newInstance(QScriptValue buffer, quint32 byteOffset, qu return engine()->newObject(this, data); } -QScriptValue TypedArray::construct(QScriptContext *context, QScriptEngine *engine) { +QScriptValue TypedArray::construct(QScriptContext* context, QScriptEngine* engine) { TypedArray* cls = qscriptvalue_cast(context->callee().data()); if (!cls) { return QScriptValue(); } - if (context->argumentCount() == 0) { return cls->newInstance(0); } @@ -84,6 +84,7 @@ QScriptValue TypedArray::construct(QScriptContext *context, QScriptEngine *engin QScriptValue bufferArg = context->argument(0); QByteArray* arrayBuffer = qscriptvalue_cast(bufferArg.data()); + // parse arguments if (arrayBuffer) { if (context->argumentCount() == 1) { // Case for entire ArrayBuffer @@ -136,6 +137,7 @@ QScriptValue TypedArray::construct(QScriptContext *context, QScriptEngine *engin } if (context->isCalledAsConstructor()) { + // if called with the new keyword, replace this object context->setThisObject(newObject); return engine->undefinedValue(); } @@ -164,8 +166,8 @@ QScriptClass::QueryFlags TypedArray::queryProperty(const QScriptValue& object, return ArrayBufferViewClass::queryProperty(object, name, flags, id); } -QScriptValue TypedArray::property(const QScriptValue &object, - const QScriptString &name, uint id) { +QScriptValue TypedArray::property(const QScriptValue& object, + const QScriptString& name, uint id) { if (name == _bytesPerElementName) { return QScriptValue(_bytesPerElement); } @@ -193,98 +195,10 @@ void TypedArray::setBytesPerElement(quint32 bytesPerElement) { _ctor.setProperty(_bytesPerElementName, _bytesPerElement); } -TypedArrayPrototype::TypedArrayPrototype(QObject* parent) : QObject(parent) { -} - -QByteArray* TypedArrayPrototype::thisArrayBuffer() const { - QScriptValue bufferObject = thisObject().data().property(BUFFER_PROPERTY_NAME); - return qscriptvalue_cast(bufferObject.data()); -} - -void TypedArrayPrototype::set(QScriptValue array, qint32 offset) { - TypedArray* typedArray = static_cast(parent()); - 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()) { - 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\""); - } -} - -QScriptValue TypedArrayPrototype::subarray(qint32 begin) { - TypedArray* typedArray = static_cast(parent()); - QScriptValue arrayBuffer = thisObject().data().property(typedArray->_bufferName); - qint32 byteOffset = thisObject().data().property(typedArray->_byteOffsetName).toInt32(); - qint32 length = thisObject().data().property(typedArray->_lengthName).toInt32(); - qint32 bytesPerElement = typedArray->_bytesPerElement; - - // if indices < 0 then they start from the end of the array - begin = (begin < 0) ? length + begin : begin; - - // here we clamp the indices to fit the array - begin = glm::clamp(begin, 0, (length - 1)); - - byteOffset += begin * bytesPerElement; - return typedArray->newInstance(arrayBuffer, byteOffset, length - begin); -} - -QScriptValue TypedArrayPrototype::subarray(qint32 begin, qint32 end) { - TypedArray* typedArray = static_cast(parent()); - QScriptValue arrayBuffer = thisObject().data().property(typedArray->_bufferName); - qint32 byteOffset = thisObject().data().property(typedArray->_byteOffsetName).toInt32(); - qint32 length = thisObject().data().property(typedArray->_lengthName).toInt32(); - qint32 bytesPerElement = typedArray->_bytesPerElement; - - // if indices < 0 then they start from the end of the array - begin = (begin < 0) ? length + begin : begin; - end = (end < 0) ? length + end : end; - - // here we clamp the indices to fit the array - begin = glm::clamp(begin, 0, (length - 1)); - end = glm::clamp(end, 0, (length - 1)); - - byteOffset += begin * bytesPerElement; - length = (end - begin > 0) ? end - begin : 0; - return typedArray->newInstance(arrayBuffer, byteOffset, length); -} - -QScriptValue TypedArrayPrototype::get(quint32 index) { - TypedArray* typedArray = static_cast(parent()); - QScriptString name = engine()->toStringHandle(QString::number(index)); - uint id; - QScriptClass::QueryFlags flags = typedArray->queryProperty(thisObject(), - name, - QScriptClass::HandlesReadAccess, &id); - if (QScriptClass::HandlesReadAccess & flags) { - return typedArray->property(thisObject(), name, id); - } - return QScriptValue(); -} - -void TypedArrayPrototype::set(quint32 index, QScriptValue& value) { - TypedArray* typedArray = static_cast(parent()); - QScriptValue object = thisObject(); - QScriptString name = engine()->toStringHandle(QString::number(index)); - uint id; - QScriptClass::QueryFlags flags = typedArray->queryProperty(object, - name, - QScriptClass::HandlesWriteAccess, &id); - if (QScriptClass::HandlesWriteAccess & flags) { - typedArray->setProperty(object, name, id, value); - } -} - +// templated helper functions +// don't work for floats as they require single precision settings template -QScriptValue propertyHelper(const QByteArray* arrayBuffer, const QScriptString &name, uint id) { +QScriptValue propertyHelper(const QByteArray* arrayBuffer, const QScriptString& name, uint id) { bool ok = false; name.toArrayIndex(&ok); @@ -300,7 +214,7 @@ QScriptValue propertyHelper(const QByteArray* arrayBuffer, const QScriptString & } template -void setPropertyHelper(QByteArray* arrayBuffer, const QScriptString &name, uint id, const QScriptValue &value) { +void setPropertyHelper(QByteArray* arrayBuffer, const QScriptString& name, uint id, const QScriptValue& value) { if (arrayBuffer && value.isNumber()) { QDataStream stream(arrayBuffer, QIODevice::ReadWrite); stream.skipRawData(id); @@ -313,15 +227,15 @@ Int8ArrayClass::Int8ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEn setBytesPerElement(sizeof(qint8)); } -QScriptValue Int8ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { +QScriptValue Int8ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); QScriptValue result = propertyHelper(arrayBuffer, name, id); return (result.isValid()) ? result : TypedArray::property(object, name, id); } void Int8ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); setPropertyHelper(ba, name, id, value); } @@ -329,16 +243,15 @@ Uint8ArrayClass::Uint8ArrayClass(ScriptEngine* scriptEngine) : TypedArray(script setBytesPerElement(sizeof(quint8)); } -QScriptValue Uint8ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { - +QScriptValue Uint8ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); QScriptValue result = propertyHelper(arrayBuffer, name, id); return (result.isValid()) ? result : TypedArray::property(object, name, id); } -void Uint8ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Uint8ArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); setPropertyHelper(ba, name, id, value); } @@ -346,16 +259,15 @@ Uint8ClampedArrayClass::Uint8ClampedArrayClass(ScriptEngine* scriptEngine) : Typ setBytesPerElement(sizeof(quint8)); } -QScriptValue Uint8ClampedArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { - +QScriptValue Uint8ClampedArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); QScriptValue result = propertyHelper(arrayBuffer, name, id); return (result.isValid()) ? result : TypedArray::property(object, name, id); } -void Uint8ClampedArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Uint8ClampedArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); if (ba && value.isNumber()) { QDataStream stream(ba, QIODevice::ReadWrite); stream.skipRawData(id); @@ -373,16 +285,15 @@ Int16ArrayClass::Int16ArrayClass(ScriptEngine* scriptEngine) : TypedArray(script setBytesPerElement(sizeof(qint16)); } -QScriptValue Int16ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { - +QScriptValue Int16ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); QScriptValue result = propertyHelper(arrayBuffer, name, id); return (result.isValid()) ? result : TypedArray::property(object, name, id); } -void Int16ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Int16ArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); setPropertyHelper(ba, name, id, value); } @@ -390,16 +301,15 @@ Uint16ArrayClass::Uint16ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scri setBytesPerElement(sizeof(quint16)); } -QScriptValue Uint16ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { - +QScriptValue Uint16ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); QScriptValue result = propertyHelper(arrayBuffer, name, id); return (result.isValid()) ? result : TypedArray::property(object, name, id); } -void Uint16ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Uint16ArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); setPropertyHelper(ba, name, id, value); } @@ -407,16 +317,15 @@ Int32ArrayClass::Int32ArrayClass(ScriptEngine* scriptEngine) : TypedArray(script setBytesPerElement(sizeof(qint32)); } -QScriptValue Int32ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { - +QScriptValue Int32ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); QScriptValue result = propertyHelper(arrayBuffer, name, id); return (result.isValid()) ? result : TypedArray::property(object, name, id); } -void Int32ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Int32ArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); setPropertyHelper(ba, name, id, value); } @@ -424,16 +333,16 @@ Uint32ArrayClass::Uint32ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scri setBytesPerElement(sizeof(quint32)); } -QScriptValue Uint32ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { +QScriptValue Uint32ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); QScriptValue result = propertyHelper(arrayBuffer, name, id); return (result.isValid()) ? result : TypedArray::property(object, name, id); } -void Uint32ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Uint32ArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); setPropertyHelper(ba, name, id, value); } @@ -441,8 +350,7 @@ Float32ArrayClass::Float32ArrayClass(ScriptEngine* scriptEngine) : TypedArray(sc setBytesPerElement(sizeof(float)); } -QScriptValue Float32ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { - +QScriptValue Float32ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data());bool ok = false; name.toArrayIndex(&ok); @@ -461,9 +369,9 @@ QScriptValue Float32ArrayClass::property(const QScriptValue &object, const QScri return TypedArray::property(object, name, id); } -void Float32ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Float32ArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); if (ba && value.isNumber()) { QDataStream stream(ba, QIODevice::ReadWrite); stream.skipRawData(id); @@ -477,8 +385,7 @@ Float64ArrayClass::Float64ArrayClass(ScriptEngine* scriptEngine) : TypedArray(sc setBytesPerElement(sizeof(double)); } -QScriptValue Float64ArrayClass::property(const QScriptValue &object, const QScriptString &name, uint id) { - +QScriptValue Float64ArrayClass::property(const QScriptValue& object, const QScriptString& name, uint id) { QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data());bool ok = false; name.toArrayIndex(&ok); @@ -497,9 +404,9 @@ QScriptValue Float64ArrayClass::property(const QScriptValue &object, const QScri return TypedArray::property(object, name, id); } -void Float64ArrayClass::setProperty(QScriptValue &object, const QScriptString &name, - uint id, const QScriptValue &value) { - QByteArray *ba = qscriptvalue_cast(object.data().property(_bufferName).data()); +void Float64ArrayClass::setProperty(QScriptValue& object, const QScriptString& name, + uint id, const QScriptValue& value) { + QByteArray* ba = qscriptvalue_cast(object.data().property(_bufferName).data()); if (ba && value.isNumber()) { QDataStream stream(ba, QIODevice::ReadWrite); stream.skipRawData(id); diff --git a/libraries/script-engine/src/TypedArrays.h b/libraries/script-engine/src/TypedArrays.h index bacb067add..a1a288c3c9 100644 --- a/libraries/script-engine/src/TypedArrays.h +++ b/libraries/script-engine/src/TypedArrays.h @@ -64,29 +64,13 @@ protected: friend class TypedArrayPrototype; }; -class TypedArrayPrototype : public QObject, public QScriptable { - Q_OBJECT -public: - TypedArrayPrototype(QObject* parent = NULL); - -public slots: - void set(QScriptValue array, qint32 offset = 0); - QScriptValue subarray(qint32 begin); - QScriptValue subarray(qint32 begin, qint32 end); - - QScriptValue get(quint32 index); - void set(quint32 index, QScriptValue& value); -private: - QByteArray* thisArrayBuffer() const; -}; - class Int8ArrayClass : public TypedArray { Q_OBJECT public: Int8ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); }; class Uint8ArrayClass : public TypedArray { @@ -94,8 +78,8 @@ class Uint8ArrayClass : public TypedArray { public: Uint8ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); }; class Uint8ClampedArrayClass : public TypedArray { @@ -103,8 +87,8 @@ class Uint8ClampedArrayClass : public TypedArray { public: Uint8ClampedArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); }; class Int16ArrayClass : public TypedArray { @@ -112,8 +96,8 @@ class Int16ArrayClass : public TypedArray { public: Int16ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); }; class Uint16ArrayClass : public TypedArray { @@ -121,16 +105,17 @@ class Uint16ArrayClass : public TypedArray { public: Uint16ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value);}; + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); +}; class Int32ArrayClass : public TypedArray { Q_OBJECT public: Int32ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); }; class Uint32ArrayClass : public TypedArray { @@ -138,8 +123,8 @@ class Uint32ArrayClass : public TypedArray { public: Uint32ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); }; class Float32ArrayClass : public TypedArray { @@ -147,16 +132,17 @@ class Float32ArrayClass : public TypedArray { public: Float32ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value);}; + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); +}; class Float64ArrayClass : public TypedArray { Q_OBJECT public: Float64ArrayClass(ScriptEngine* scriptEngine); - QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); - void setProperty(QScriptValue &object, const QScriptString &name, uint id, const QScriptValue &value); + QScriptValue property(const QScriptValue& object, const QScriptString& name, uint id); + void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value); }; #endif // hifi_TypedArrays_h \ No newline at end of file