diff --git a/libraries/script-engine/src/TypedArrays.cpp b/libraries/script-engine/src/TypedArrays.cpp index 121870443f..d6ffc8f5a6 100644 --- a/libraries/script-engine/src/TypedArrays.cpp +++ b/libraries/script-engine/src/TypedArrays.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "ScriptEngine.h" #include "TypedArrays.h" @@ -22,12 +24,12 @@ TypedArray::TypedArray(ScriptEngine* scriptEngine, QString name) : ArrayBufferVi QScriptValue global = engine()->globalObject(); - // build prototype TODO - // _proto = engine->newQObject(new DataViewPrototype(this), - // QScriptEngine::QtOwnership, - // QScriptEngine::SkipMethodsInEnumeration | - // QScriptEngine::ExcludeSuperClassMethods | - // QScriptEngine::ExcludeSuperClassProperties); + // build prototype + _proto = engine()->newQObject(new TypedArrayPrototype(this), + QScriptEngine::QtOwnership, + QScriptEngine::SkipMethodsInEnumeration | + QScriptEngine::ExcludeSuperClassMethods | + QScriptEngine::ExcludeSuperClassProperties); _proto.setPrototype(global.property("Object").property("prototype")); @@ -37,16 +39,49 @@ TypedArray::TypedArray(ScriptEngine* scriptEngine, QString name) : ArrayBufferVi engine()->globalObject().setProperty(_name, _ctor); } +QScriptValue TypedArray::newInstance(quint32 length) { + ArrayBufferClass* array = getScriptEngine()->getArrayBufferClass(); + QScriptValue buffer = array->newInstance(length * _bytesPerElement); + return newInstance(buffer, 0, length); +} + +QScriptValue TypedArray::newInstance(QScriptValue array) { + if (array.property("length").isValid()) { + quint32 length = array.property("length").toInt32(); + QScriptValue newArray = newInstance(length); + for (int i = 0; i < length; ++i) { + QScriptValue value = array.property(QString::number(i)); + setProperty(newArray, engine()->toStringHandle(QString::number(i)), + i * _bytesPerElement, (value.isNumber()) ? value : QScriptValue(0)); + } + return newArray; + } + return QScriptValue(); +} + +QScriptValue TypedArray::newInstance(QScriptValue buffer, quint32 byteOffset, quint32 length) { + QScriptValue data = engine()->newObject(); + data.setProperty(_bufferName, buffer); + data.setProperty(_byteOffsetName, byteOffset); + data.setProperty(_byteLengthName, length * _bytesPerElement); + data.setProperty(_lengthName, length); + + return engine()->newObject(this, data); +} + QScriptValue TypedArray::construct(QScriptContext *context, QScriptEngine *engine) { TypedArray* cls = qscriptvalue_cast(context->callee().data()); - if (!cls || context->argumentCount() < 1) { + if (!cls) { return QScriptValue(); } + if (context->argumentCount() == 0) { + return cls->newInstance(0); + } + QScriptValue newObject; QScriptValue bufferArg = context->argument(0); QByteArray* arrayBuffer = qscriptvalue_cast(bufferArg.data()); - TypedArray* typedArray = qscriptvalue_cast(bufferArg); if (arrayBuffer) { if (context->argumentCount() == 1) { @@ -58,15 +93,22 @@ QScriptValue TypedArray::construct(QScriptContext *context, QScriptEngine *engin engine->evaluate("throw \"ArgumentError: 2nd arg is not a number\""); return QScriptValue(); } - if (byteOffsetArg.toInt32() < 0 || byteOffsetArg.toInt32() >= arrayBuffer->size()) { + if (byteOffsetArg.toInt32() < 0 || byteOffsetArg.toInt32() > arrayBuffer->size()) { engine->evaluate("throw \"RangeError: byteOffset out of range\""); return QScriptValue(); } + if (byteOffsetArg.toInt32() % cls->_bytesPerElement != 0) { + engine->evaluate("throw \"RangeError: byteOffset not a multiple of BYTES_PER_ELEMENT\""); + } quint32 byteOffset = byteOffsetArg.toInt32(); if (context->argumentCount() == 2) { // case for end of ArrayBuffer - newObject = cls->newInstance(bufferArg, byteOffset, arrayBuffer->size() - byteOffset); + if ((arrayBuffer->size() - byteOffset) % cls->_bytesPerElement != 0) { + engine->evaluate("throw \"RangeError: byteLength - byteOffset not a multiple of BYTES_PER_ELEMENT\""); + } + quint32 length = (arrayBuffer->size() - byteOffset) / cls->_bytesPerElement; + newObject = cls->newInstance(bufferArg, byteOffset, length); } else { QScriptValue lengthArg = (context->argumentCount() > 2) ? context->argument(2) : QScriptValue(); @@ -79,20 +121,17 @@ QScriptValue TypedArray::construct(QScriptContext *context, QScriptEngine *engin engine->evaluate("throw \"RangeError: byteLength out of range\""); return QScriptValue(); } - quint32 length = lengthArg.toInt32() * cls->_bytesPerElement; + quint32 length = lengthArg.toInt32(); // case for well-defined range newObject = cls->newInstance(bufferArg, byteOffset, length); } } - } else if (typedArray) { - // case for another reference to another TypedArray - newObject = cls->newInstance(bufferArg, true); } else if (context->argument(0).isNumber()) { // case for new ArrayBuffer newObject = cls->newInstance(context->argument(0).toInt32()); } else { - // TODO: Standard array case + newObject = cls->newInstance(bufferArg); } if (context->isCalledAsConstructor()) { @@ -148,79 +187,257 @@ QScriptValue TypedArray::prototype() const { return _proto; } -Int8ArrayClass::Int8ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, INT_8_ARRAY_CLASS_NAME) { - _bytesPerElement = sizeof(qint8); +void TypedArray::setBytesPerElement(quint32 bytesPerElement) { + _bytesPerElement = bytesPerElement; + _ctor.setProperty(_bytesPerElementName, _bytesPerElement); } -QScriptValue Int8ArrayClass::newInstance(quint32 length) { - ArrayBufferClass* array = getScriptEngine()->getArrayBufferClass(); - QScriptValue buffer = array->newInstance(length * _bytesPerElement); - return newInstance(buffer, 0, length); +TypedArrayPrototype::TypedArrayPrototype(QObject* parent) : QObject(parent) { } -QScriptValue Int8ArrayClass::newInstance(QScriptValue array, bool isTypedArray) { - // TODO - assert(false); - if (isTypedArray) { - QByteArray* originalArray = qscriptvalue_cast(array.data().property(_bufferName).data()); - ArrayBufferClass* arrayBufferClass = reinterpret_cast(engine())->getArrayBufferClass(); - quint32 byteOffset = array.data().property(_byteOffsetName).toInt32(); - quint32 byteLength = array.data().property(_byteLengthName).toInt32(); - quint32 length = byteLength / _bytesPerElement; - QByteArray newArray = originalArray->mid(byteOffset, byteLength); - - if (byteLength % _bytesPerElement != 0) { - length += 1; - byteLength = length * _bytesPerElement; +QByteArray* TypedArrayPrototype::thisArrayBuffer() const { + QScriptValue bufferObject = thisObject().data().property(BUFFER_PROPERTY_NAME); + return qscriptvalue_cast(bufferObject.data()); +} + +void TypedArrayPrototype::set(QScriptValue array, quint32 offset) { + TypedArray* typedArray = static_cast(parent()); + if (array.isArray()) { + quint32 length = array.property("length").toInt32(); + if (offset + length > thisObject().data().property(typedArray->_lengthName).toInt32()) { + // TODO throw an error maybe? + return; } - - - return newInstance(arrayBufferClass->newInstance(newArray), - array.data().property(_byteOffsetName).toInt32(), - array.data().property(_lengthName).toInt32()); + for (int i = 0; i < length; ++i) { + thisObject().setProperty(QString::number(offset + i), array.property(QString::number(i))); + } + } + // TODO handle typed arrays +} + +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(); } -QScriptValue Int8ArrayClass::newInstance(QScriptValue buffer, quint32 byteOffset, quint32 length) { - QScriptValue data = engine()->newObject(); - data.setProperty(_bufferName, buffer); - data.setProperty(_byteOffsetName, byteOffset); - data.setProperty(_byteLengthName, length * _bytesPerElement); - data.setProperty(_lengthName, length); - - return engine()->newObject(this, data); +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); + } } -QScriptValue Int8ArrayClass::property(const QScriptValue &object, - const QScriptString &name, uint id) { - QByteArray* arrayBuffer = qscriptvalue_cast(object.data().property(_bufferName).data()); +template +QScriptValue propertyHelper(const QByteArray* arrayBuffer, const QScriptString &name, uint id) { bool ok = false; name.toArrayIndex(&ok); - + if (ok && arrayBuffer) { QDataStream stream(*arrayBuffer); stream.skipRawData(id); - qint8 result; + T result; stream >> result; return result; } - - return TypedArray::property(object, name, id); + return QScriptValue(); } -void Int8ArrayClass::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); +template +void setPropertyHelper(QByteArray* arrayBuffer, const QScriptString &name, uint id, const QScriptValue &value) { + if (arrayBuffer && value.isNumber()) { + QDataStream stream(arrayBuffer, QIODevice::ReadWrite); stream.skipRawData(id); - stream << (qint8)value.toInt32(); + stream << (T)value.toNumber(); } } +Int8ArrayClass::Int8ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, INT_8_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(qint8)); +} + +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()); + setPropertyHelper(ba, name, id, value); +} + +Uint8ArrayClass::Uint8ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, UINT_8_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(quint8)); +} + +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()); + setPropertyHelper(ba, name, id, value); +} + +Int16ArrayClass::Int16ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, INT_16_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(qint16)); +} + +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()); + setPropertyHelper(ba, name, id, value); +} + +Uint16ArrayClass::Uint16ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, UINT_16_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(quint16)); +} + +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()); + setPropertyHelper(ba, name, id, value); +} + +Int32ArrayClass::Int32ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, INT_32_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(qint32)); +} + +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()); + setPropertyHelper(ba, name, id, value); +} + +Uint32ArrayClass::Uint32ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, UINT_32_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(quint32)); +} + +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()); + setPropertyHelper(ba, name, id, value); +} + +Float32ArrayClass::Float32ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, FLOAT_32_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(float)); +} + +QScriptValue Float32ArrayClass::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 Float32ArrayClass::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); +} + +Float64ArrayClass::Float64ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, FLOAT_64_ARRAY_CLASS_NAME) { + setBytesPerElement(sizeof(double)); +} + +QScriptValue Float64ArrayClass::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 Float64ArrayClass::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); +} + diff --git a/libraries/script-engine/src/TypedArrays.h b/libraries/script-engine/src/TypedArrays.h index 2c63d83f93..37d341b2ad 100644 --- a/libraries/script-engine/src/TypedArrays.h +++ b/libraries/script-engine/src/TypedArrays.h @@ -18,20 +18,28 @@ static const QString BYTES_PER_ELEMENT_PROPERTY_NAME = "BYTES_PER_ELEMENT"; static const QString LENGTH_PROPERTY_NAME = "length"; static const QString INT_8_ARRAY_CLASS_NAME = "Int8Array"; +static const QString UINT_8_ARRAY_CLASS_NAME = "Uint8Array"; +static const QString INT_16_ARRAY_CLASS_NAME = "Int16Array"; +static const QString UINT_16_ARRAY_CLASS_NAME = "Uint16Array"; +static const QString INT_32_ARRAY_CLASS_NAME = "Int32Array"; +static const QString UINT_32_ARRAY_CLASS_NAME = "Uint32Array"; +static const QString FLOAT_32_ARRAY_CLASS_NAME = "Float32Array"; +static const QString FLOAT_64_ARRAY_CLASS_NAME = "Float64Array"; class TypedArray : public ArrayBufferViewClass { Q_OBJECT public: TypedArray(ScriptEngine* scriptEngine, QString name); - virtual QScriptValue newInstance(quint32 length) = 0; - virtual QScriptValue newInstance(QScriptValue array, bool isTypedArray) = 0; - virtual QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset, quint32 length) = 0; + virtual QScriptValue newInstance(quint32 length); + virtual QScriptValue newInstance(QScriptValue array); + virtual QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset, quint32 length); virtual QueryFlags queryProperty(const QScriptValue& object, const QScriptString& name, QueryFlags flags, uint* id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, uint id); + virtual QScriptValue property(const QScriptValue& object, + const QScriptString& name, uint id); + virtual void setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value) = 0; virtual QScriptValue::PropertyFlags propertyFlags(const QScriptValue& object, const QScriptString& name, uint id); @@ -41,6 +49,8 @@ public: protected: static QScriptValue construct(QScriptContext* context, QScriptEngine* engine); + void setBytesPerElement(quint32 bytesPerElement); + QScriptValue _proto; QScriptValue _ctor; @@ -49,53 +59,98 @@ protected: QScriptString _lengthName; quint32 _bytesPerElement; + + friend class TypedArrayPrototype; +}; + +class TypedArrayPrototype : public QObject, public QScriptable { + Q_OBJECT +public: + TypedArrayPrototype(QObject* parent = NULL); + +public slots: + void set(QScriptValue array, quint32 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 newInstance(quint32 length); - QScriptValue newInstance(QScriptValue array, bool isTypedArray); - QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset, quint32 length); - - 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 { + Q_OBJECT +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); }; class Uint8ClampedArrayClass : public TypedArray { - + // TODO }; class Int16ArrayClass : public TypedArray { + Q_OBJECT +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); }; class Uint16ArrayClass : public TypedArray { + Q_OBJECT +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);}; 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); }; class Uint32ArrayClass : public TypedArray { + Q_OBJECT +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); }; class Float32ArrayClass : public TypedArray { + Q_OBJECT +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);}; 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); }; #endif // hifi_TypedArrays_h \ No newline at end of file