mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 22:47:07 +02:00
- Bunch of fixes to typed arrays
- First working prototype for Int8Array - Base classes for all other typed arrays
This commit is contained in:
parent
a76ebae771
commit
b2b1701965
10 changed files with 412 additions and 37 deletions
|
@ -9,8 +9,10 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "ArrayBufferPrototype.h"
|
#include "ArrayBufferPrototype.h"
|
||||||
|
#include "ScriptEngine.h"
|
||||||
|
|
||||||
#include "ArrayBufferClass.h"
|
#include "ArrayBufferClass.h"
|
||||||
|
|
||||||
|
@ -19,16 +21,20 @@ static const QString BYTE_LENGTH_PROPERTY_NAME = "byteLength";
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QByteArray*)
|
Q_DECLARE_METATYPE(QByteArray*)
|
||||||
|
|
||||||
ArrayBufferClass::ArrayBufferClass(QScriptEngine* engine) : QObject(engine), QScriptClass(engine) {
|
ArrayBufferClass::ArrayBufferClass(ScriptEngine* scriptEngine) :
|
||||||
qScriptRegisterMetaType<QByteArray>(engine, toScriptValue, fromScriptValue);
|
QObject(scriptEngine->getScriptEngine()),
|
||||||
QScriptValue global = engine->globalObject();
|
QScriptClass(scriptEngine->getScriptEngine()),
|
||||||
|
_scriptEngine(scriptEngine) {
|
||||||
|
qDebug() << "Created with engine: " << engine();
|
||||||
|
qScriptRegisterMetaType<QByteArray>(engine(), toScriptValue, fromScriptValue);
|
||||||
|
QScriptValue global = engine()->globalObject();
|
||||||
|
|
||||||
// Save string handles for quick lookup
|
// Save string handles for quick lookup
|
||||||
_name = engine->toStringHandle(CLASS_NAME.toLatin1());
|
_name = engine()->toStringHandle(CLASS_NAME.toLatin1());
|
||||||
_byteLength = engine->toStringHandle(BYTE_LENGTH_PROPERTY_NAME.toLatin1());
|
_byteLength = engine()->toStringHandle(BYTE_LENGTH_PROPERTY_NAME.toLatin1());
|
||||||
|
|
||||||
// build prototype
|
// build prototype
|
||||||
_proto = engine->newQObject(new ArrayBufferPrototype(this),
|
_proto = engine()->newQObject(new ArrayBufferPrototype(this),
|
||||||
QScriptEngine::QtOwnership,
|
QScriptEngine::QtOwnership,
|
||||||
QScriptEngine::SkipMethodsInEnumeration |
|
QScriptEngine::SkipMethodsInEnumeration |
|
||||||
QScriptEngine::ExcludeSuperClassMethods |
|
QScriptEngine::ExcludeSuperClassMethods |
|
||||||
|
@ -36,15 +42,17 @@ ArrayBufferClass::ArrayBufferClass(QScriptEngine* engine) : QObject(engine), QSc
|
||||||
|
|
||||||
_proto.setPrototype(global.property("Object").property("prototype"));
|
_proto.setPrototype(global.property("Object").property("prototype"));
|
||||||
|
|
||||||
_ctor = engine->newFunction(construct, _proto);
|
_ctor = engine()->newFunction(construct, _proto);
|
||||||
_ctor.setData(engine->toScriptValue(this));
|
_ctor.setData(engine()->toScriptValue(this));
|
||||||
|
|
||||||
engine->globalObject().setProperty(name(), _ctor);
|
engine()->globalObject().setProperty(name(), _ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue ArrayBufferClass::newInstance(quint32 size) {
|
QScriptValue ArrayBufferClass::newInstance(quint32 size) {
|
||||||
engine()->reportAdditionalMemoryCost(size);
|
engine()->reportAdditionalMemoryCost(size);
|
||||||
QScriptValue data = engine()->newVariant(QVariant::fromValue(QByteArray(size, 0)));
|
QScriptEngine* eng = engine();
|
||||||
|
QVariant variant = QVariant::fromValue(QByteArray(size, 0));
|
||||||
|
QScriptValue data = eng->newVariant(variant);
|
||||||
return engine()->newObject(this, data);
|
return engine()->newObject(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,17 @@
|
||||||
#include <QtScript/QScriptString>
|
#include <QtScript/QScriptString>
|
||||||
#include <QtScript/QScriptValue>
|
#include <QtScript/QScriptValue>
|
||||||
|
|
||||||
|
class ScriptEngine;
|
||||||
|
|
||||||
class ArrayBufferClass : public QObject, public QScriptClass {
|
class ArrayBufferClass : public QObject, public QScriptClass {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ArrayBufferClass(QScriptEngine* engine);
|
ArrayBufferClass(ScriptEngine* scriptEngine);
|
||||||
QScriptValue newInstance(quint32 size);
|
QScriptValue newInstance(quint32 size);
|
||||||
QScriptValue newInstance(const QByteArray& ba);
|
QScriptValue newInstance(const QByteArray& ba);
|
||||||
|
|
||||||
|
ScriptEngine* getScriptEngine() { return _scriptEngine; }
|
||||||
|
|
||||||
QueryFlags queryProperty(const QScriptValue& object,
|
QueryFlags queryProperty(const QScriptValue& object,
|
||||||
const QScriptString& name,
|
const QScriptString& name,
|
||||||
QueryFlags flags, uint* id);
|
QueryFlags flags, uint* id);
|
||||||
|
@ -50,6 +54,8 @@ private:
|
||||||
// JS Object attributes
|
// JS Object attributes
|
||||||
QScriptString _name;
|
QScriptString _name;
|
||||||
QScriptString _byteLength;
|
QScriptString _byteLength;
|
||||||
|
|
||||||
|
ScriptEngine* _scriptEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ArrayBufferClass_h
|
#endif // hifi_ArrayBufferClass_h
|
|
@ -13,13 +13,14 @@
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QByteArray*)
|
Q_DECLARE_METATYPE(QByteArray*)
|
||||||
|
|
||||||
ArrayBufferViewClass::ArrayBufferViewClass(QScriptEngine* engine) :
|
ArrayBufferViewClass::ArrayBufferViewClass(ScriptEngine* scriptEngine) :
|
||||||
QObject(engine),
|
QObject(scriptEngine->getScriptEngine()),
|
||||||
QScriptClass(engine) {
|
QScriptClass(scriptEngine->getScriptEngine()),
|
||||||
|
_scriptEngine(scriptEngine) {
|
||||||
// Save string handles for quick lookup
|
// Save string handles for quick lookup
|
||||||
_bufferName = engine->toStringHandle(BUFFER_PROPERTY_NAME.toLatin1());
|
_bufferName = engine()->toStringHandle(BUFFER_PROPERTY_NAME.toLatin1());
|
||||||
_byteOffsetName = engine->toStringHandle(BYTE_OFFSET_PROPERTY_NAME.toLatin1());
|
_byteOffsetName = engine()->toStringHandle(BYTE_OFFSET_PROPERTY_NAME.toLatin1());
|
||||||
_byteLengthName = engine->toStringHandle(BYTE_LENGTH_PROPERTY_NAME.toLatin1());
|
_byteLengthName = engine()->toStringHandle(BYTE_LENGTH_PROPERTY_NAME.toLatin1());
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptClass::QueryFlags ArrayBufferViewClass::queryProperty(const QScriptValue& object,
|
QScriptClass::QueryFlags ArrayBufferViewClass::queryProperty(const QScriptValue& object,
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include <QtScript/QScriptString>
|
#include <QtScript/QScriptString>
|
||||||
#include <QtScript/QScriptValue>
|
#include <QtScript/QScriptValue>
|
||||||
|
|
||||||
|
#include "ScriptEngine.h"
|
||||||
|
|
||||||
static const QString BUFFER_PROPERTY_NAME = "buffer";
|
static const QString BUFFER_PROPERTY_NAME = "buffer";
|
||||||
static const QString BYTE_OFFSET_PROPERTY_NAME = "byteOffset";
|
static const QString BYTE_OFFSET_PROPERTY_NAME = "byteOffset";
|
||||||
static const QString BYTE_LENGTH_PROPERTY_NAME = "byteLength";
|
static const QString BYTE_LENGTH_PROPERTY_NAME = "byteLength";
|
||||||
|
@ -27,21 +29,24 @@ static const QString BYTE_LENGTH_PROPERTY_NAME = "byteLength";
|
||||||
class ArrayBufferViewClass : public QObject, public QScriptClass {
|
class ArrayBufferViewClass : public QObject, public QScriptClass {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ArrayBufferViewClass(QScriptEngine* engine);
|
ArrayBufferViewClass(ScriptEngine* scriptEngine);
|
||||||
|
|
||||||
|
ScriptEngine* getScriptEngine() { return _scriptEngine; }
|
||||||
|
|
||||||
QueryFlags queryProperty(const QScriptValue& object,
|
virtual QueryFlags queryProperty(const QScriptValue& object,
|
||||||
const QScriptString& name,
|
const QScriptString& name,
|
||||||
QueryFlags flags, uint* id);
|
QueryFlags flags, uint* id);
|
||||||
QScriptValue property(const QScriptValue &object,
|
virtual QScriptValue property(const QScriptValue &object,
|
||||||
const QScriptString &name, uint id);
|
const QScriptString &name, uint id);
|
||||||
QScriptValue::PropertyFlags propertyFlags(const QScriptValue& object,
|
virtual QScriptValue::PropertyFlags propertyFlags(const QScriptValue& object,
|
||||||
const QScriptString& name, uint id);
|
const QScriptString& name, uint id);
|
||||||
protected:
|
protected:
|
||||||
// JS Object attributes
|
// JS Object attributes
|
||||||
QScriptString _bufferName;
|
QScriptString _bufferName;
|
||||||
QScriptString _byteOffsetName;
|
QScriptString _byteOffsetName;
|
||||||
QScriptString _byteLengthName;
|
QScriptString _byteLengthName;
|
||||||
|
|
||||||
|
ScriptEngine* _scriptEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ArrayBufferViewClass_h
|
#endif // hifi_ArrayBufferViewClass_h
|
|
@ -17,14 +17,14 @@ Q_DECLARE_METATYPE(QByteArray*)
|
||||||
|
|
||||||
static const QString DATA_VIEW_NAME = "DataView";
|
static const QString DATA_VIEW_NAME = "DataView";
|
||||||
|
|
||||||
DataViewClass::DataViewClass(QScriptEngine* engine) : ArrayBufferViewClass(engine) {
|
DataViewClass::DataViewClass(ScriptEngine* scriptEngine) : ArrayBufferViewClass(scriptEngine) {
|
||||||
QScriptValue global = engine->globalObject();
|
QScriptValue global = engine()->globalObject();
|
||||||
|
|
||||||
// Save string handles for quick lookup
|
// Save string handles for quick lookup
|
||||||
_name = engine->toStringHandle(DATA_VIEW_NAME.toLatin1());
|
_name = engine()->toStringHandle(DATA_VIEW_NAME.toLatin1());
|
||||||
|
|
||||||
// build prototype
|
// build prototype
|
||||||
_proto = engine->newQObject(new DataViewPrototype(this),
|
_proto = engine()->newQObject(new DataViewPrototype(this),
|
||||||
QScriptEngine::QtOwnership,
|
QScriptEngine::QtOwnership,
|
||||||
QScriptEngine::SkipMethodsInEnumeration |
|
QScriptEngine::SkipMethodsInEnumeration |
|
||||||
QScriptEngine::ExcludeSuperClassMethods |
|
QScriptEngine::ExcludeSuperClassMethods |
|
||||||
|
@ -32,10 +32,10 @@ DataViewClass::DataViewClass(QScriptEngine* engine) : ArrayBufferViewClass(engin
|
||||||
|
|
||||||
_proto.setPrototype(global.property("Object").property("prototype"));
|
_proto.setPrototype(global.property("Object").property("prototype"));
|
||||||
|
|
||||||
_ctor = engine->newFunction(construct, _proto);
|
_ctor = engine()->newFunction(construct, _proto);
|
||||||
_ctor.setData(engine->toScriptValue(this));
|
_ctor.setData(engine()->toScriptValue(this));
|
||||||
|
|
||||||
engine->globalObject().setProperty(name(), _ctor);
|
engine()->globalObject().setProperty(name(), _ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue DataViewClass::newInstance(QScriptValue buffer, quint32 byteOffset, quint32 byteLentgh) {
|
QScriptValue DataViewClass::newInstance(QScriptValue buffer, quint32 byteOffset, quint32 byteLentgh) {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
class DataViewClass : public ArrayBufferViewClass {
|
class DataViewClass : public ArrayBufferViewClass {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DataViewClass(QScriptEngine* engine);
|
DataViewClass(ScriptEngine* scriptEngine);
|
||||||
QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset, quint32 byteLength);
|
QScriptValue newInstance(QScriptValue buffer, quint32 byteOffset, quint32 byteLength);
|
||||||
|
|
||||||
QString name() const;
|
QString name() const;
|
||||||
|
|
|
@ -32,13 +32,13 @@
|
||||||
#include <VoxelDetail.h>
|
#include <VoxelDetail.h>
|
||||||
|
|
||||||
#include "AnimationObject.h"
|
#include "AnimationObject.h"
|
||||||
#include "ArrayBufferClass.h"
|
|
||||||
#include "ArrayBufferViewClass.h"
|
#include "ArrayBufferViewClass.h"
|
||||||
#include "DataViewClass.h"
|
#include "DataViewClass.h"
|
||||||
#include "MenuItemProperties.h"
|
#include "MenuItemProperties.h"
|
||||||
#include "MIDIEvent.h"
|
#include "MIDIEvent.h"
|
||||||
#include "LocalVoxels.h"
|
#include "LocalVoxels.h"
|
||||||
#include "ScriptEngine.h"
|
#include "ScriptEngine.h"
|
||||||
|
#include "TypedArrays.h"
|
||||||
#include "XMLHttpRequestClass.h"
|
#include "XMLHttpRequestClass.h"
|
||||||
|
|
||||||
VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface;
|
VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface;
|
||||||
|
@ -93,8 +93,15 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
|
||||||
_quatLibrary(),
|
_quatLibrary(),
|
||||||
_vec3Library(),
|
_vec3Library(),
|
||||||
_uuidLibrary(),
|
_uuidLibrary(),
|
||||||
_animationCache(this)
|
_animationCache(this),
|
||||||
|
_arrayBufferClass(NULL)
|
||||||
{
|
{
|
||||||
|
_arrayBufferClass = new ArrayBufferClass(this);
|
||||||
|
qDebug() << "Engine: " << this;
|
||||||
|
qDebug() << "ArrayBuffer: " <<_arrayBufferClass;
|
||||||
|
qDebug() << "DataView: " << new DataViewClass(this);
|
||||||
|
qDebug() << "Int8Array: " << new Int8ArrayClass(this);
|
||||||
|
qDebug() << "Initial thread: " << QThread::currentThread() << " " << thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngine::ScriptEngine(const QUrl& scriptURL,
|
ScriptEngine::ScriptEngine(const QUrl& scriptURL,
|
||||||
|
@ -118,13 +125,21 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL,
|
||||||
_quatLibrary(),
|
_quatLibrary(),
|
||||||
_vec3Library(),
|
_vec3Library(),
|
||||||
_uuidLibrary(),
|
_uuidLibrary(),
|
||||||
_animationCache(this)
|
_animationCache(this),
|
||||||
|
_arrayBufferClass(NULL)
|
||||||
{
|
{
|
||||||
QString scriptURLString = scriptURL.toString();
|
QString scriptURLString = scriptURL.toString();
|
||||||
_fileNameString = scriptURLString;
|
_fileNameString = scriptURLString;
|
||||||
|
|
||||||
QUrl url(scriptURL);
|
QUrl url(scriptURL);
|
||||||
|
|
||||||
|
_arrayBufferClass = new ArrayBufferClass(this);
|
||||||
|
qDebug() << "Engine: " << this;
|
||||||
|
qDebug() << "ArrayBuffer: " <<_arrayBufferClass;
|
||||||
|
qDebug() << "DataView: " << new DataViewClass(this);
|
||||||
|
qDebug() << "Int8Array: " << new Int8ArrayClass(this);
|
||||||
|
qDebug() << "Initial thread: " << QThread::currentThread() << " " << thread();
|
||||||
|
|
||||||
// if the scheme length is one or lower, maybe they typed in a file, let's try
|
// if the scheme length is one or lower, maybe they typed in a file, let's try
|
||||||
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
|
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
|
||||||
if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
||||||
|
@ -141,6 +156,7 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL,
|
||||||
QTextStream in(&scriptFile);
|
QTextStream in(&scriptFile);
|
||||||
_scriptContents = in.readAll();
|
_scriptContents = in.readAll();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
qDebug() << "ERROR Loading file:" << fileName;
|
qDebug() << "ERROR Loading file:" << fileName;
|
||||||
emit errorMessage("ERROR Loading file:" + fileName);
|
emit errorMessage("ERROR Loading file:" + fileName);
|
||||||
}
|
}
|
||||||
|
@ -213,10 +229,6 @@ void ScriptEngine::init() {
|
||||||
if (_isInitialized) {
|
if (_isInitialized) {
|
||||||
return; // only initialize once
|
return; // only initialize once
|
||||||
}
|
}
|
||||||
|
|
||||||
new ArrayBufferClass(&_engine);
|
|
||||||
new ArrayBufferViewClass(&_engine);
|
|
||||||
new DataViewClass(&_engine);
|
|
||||||
|
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <VoxelsScriptingInterface.h>
|
#include <VoxelsScriptingInterface.h>
|
||||||
|
|
||||||
#include "AbstractControllerScriptingInterface.h"
|
#include "AbstractControllerScriptingInterface.h"
|
||||||
|
#include "ArrayBufferClass.h"
|
||||||
#include "Quat.h"
|
#include "Quat.h"
|
||||||
#include "ScriptUUID.h"
|
#include "ScriptUUID.h"
|
||||||
#include "Vec3.h"
|
#include "Vec3.h"
|
||||||
|
@ -56,6 +57,9 @@ public:
|
||||||
/// Access the ModelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
/// Access the ModelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||||
static ModelsScriptingInterface* getModelsScriptingInterface() { return &_modelsScriptingInterface; }
|
static ModelsScriptingInterface* getModelsScriptingInterface() { return &_modelsScriptingInterface; }
|
||||||
|
|
||||||
|
QScriptEngine* getScriptEngine() { return &_engine; }
|
||||||
|
ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; }
|
||||||
|
|
||||||
/// sets the script contents, will return false if failed, will fail if script is already running
|
/// sets the script contents, will return false if failed, will fail if script is already running
|
||||||
bool setScriptContents(const QString& scriptContents, const QString& fileNameString = QString(""));
|
bool setScriptContents(const QString& scriptContents, const QString& fileNameString = QString(""));
|
||||||
|
|
||||||
|
@ -147,6 +151,8 @@ private:
|
||||||
Vec3 _vec3Library;
|
Vec3 _vec3Library;
|
||||||
ScriptUUID _uuidLibrary;
|
ScriptUUID _uuidLibrary;
|
||||||
AnimationCache _animationCache;
|
AnimationCache _animationCache;
|
||||||
|
|
||||||
|
ArrayBufferClass* _arrayBufferClass;
|
||||||
|
|
||||||
QHash<QUuid, quint16> _outgoingScriptAudioSequenceNumbers;
|
QHash<QUuid, quint16> _outgoingScriptAudioSequenceNumbers;
|
||||||
};
|
};
|
||||||
|
|
233
libraries/script-engine/src/TypedArrays.cpp
Normal file
233
libraries/script-engine/src/TypedArrays.cpp
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
//
|
||||||
|
// TypedArrays.cpp
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Clement on 7/9/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 "ScriptEngine.h"
|
||||||
|
|
||||||
|
#include "TypedArrays.h"
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QByteArray*)
|
||||||
|
|
||||||
|
TypedArray::TypedArray(ScriptEngine* scriptEngine, QString name) : ArrayBufferViewClass(scriptEngine) {
|
||||||
|
_bytesPerElementName = engine()->toStringHandle(BYTES_PER_ELEMENT_PROPERTY_NAME.toLatin1());
|
||||||
|
_lengthName = engine()->toStringHandle(LENGTH_PROPERTY_NAME.toLatin1());
|
||||||
|
_name = engine()->toStringHandle(name.toLatin1());
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue TypedArray::construct(QScriptContext *context, QScriptEngine *engine) {
|
||||||
|
TypedArray* cls = qscriptvalue_cast<TypedArray*>(context->callee().data());
|
||||||
|
if (!cls || context->argumentCount() < 1) {
|
||||||
|
return QScriptValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue newObject;
|
||||||
|
QScriptValue bufferArg = context->argument(0);
|
||||||
|
QByteArray* arrayBuffer = qscriptvalue_cast<QByteArray*>(bufferArg.data());
|
||||||
|
TypedArray* typedArray = qscriptvalue_cast<TypedArray*>(bufferArg);
|
||||||
|
|
||||||
|
if (arrayBuffer) {
|
||||||
|
if (context->argumentCount() == 1) {
|
||||||
|
// Case for entire ArrayBuffer
|
||||||
|
newObject = cls->newInstance(bufferArg, 0, arrayBuffer->size());
|
||||||
|
} else {
|
||||||
|
QScriptValue byteOffsetArg = context->argument(1);
|
||||||
|
if (!byteOffsetArg.isNumber()) {
|
||||||
|
engine->evaluate("throw \"ArgumentError: 2nd arg is not a number\"");
|
||||||
|
return QScriptValue();
|
||||||
|
}
|
||||||
|
if (byteOffsetArg.toInt32() < 0 || byteOffsetArg.toInt32() >= arrayBuffer->size()) {
|
||||||
|
engine->evaluate("throw \"RangeError: byteOffset out of range\"");
|
||||||
|
return QScriptValue();
|
||||||
|
}
|
||||||
|
quint32 byteOffset = byteOffsetArg.toInt32();
|
||||||
|
|
||||||
|
if (context->argumentCount() == 2) {
|
||||||
|
// case for end of ArrayBuffer
|
||||||
|
newObject = cls->newInstance(bufferArg, byteOffset, arrayBuffer->size() - byteOffset);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
QScriptValue lengthArg = (context->argumentCount() > 2) ? context->argument(2) : QScriptValue();
|
||||||
|
if (!lengthArg.isNumber()) {
|
||||||
|
engine->evaluate("throw \"ArgumentError: 3nd arg is not a number\"");
|
||||||
|
return QScriptValue();
|
||||||
|
}
|
||||||
|
if (lengthArg.toInt32() < 0 ||
|
||||||
|
byteOffsetArg.toInt32() + lengthArg.toInt32() * cls->_bytesPerElement > arrayBuffer->size()) {
|
||||||
|
engine->evaluate("throw \"RangeError: byteLength out of range\"");
|
||||||
|
return QScriptValue();
|
||||||
|
}
|
||||||
|
quint32 length = lengthArg.toInt32() * cls->_bytesPerElement;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->isCalledAsConstructor()) {
|
||||||
|
context->setThisObject(newObject);
|
||||||
|
return engine->undefinedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptClass::QueryFlags TypedArray::queryProperty(const QScriptValue& object,
|
||||||
|
const QScriptString& name,
|
||||||
|
QueryFlags flags, uint* id) {
|
||||||
|
if (name == _bytesPerElementName || name == _lengthName) {
|
||||||
|
return flags &= HandlesReadAccess; // Only keep read access flags
|
||||||
|
}
|
||||||
|
return ArrayBufferViewClass::queryProperty(object, name, flags, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue TypedArray::property(const QScriptValue &object,
|
||||||
|
const QScriptString &name, uint id) {
|
||||||
|
if (name == _bytesPerElementName) {
|
||||||
|
return QScriptValue(_bytesPerElement);
|
||||||
|
}
|
||||||
|
if (name == _lengthName) {
|
||||||
|
return object.data().property(_lengthName);
|
||||||
|
}
|
||||||
|
return ArrayBufferViewClass::property(object, name, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue::PropertyFlags TypedArray::propertyFlags(const QScriptValue& object,
|
||||||
|
const QScriptString& name, uint id) {
|
||||||
|
return QScriptValue::Undeletable;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TypedArray::name() const {
|
||||||
|
return _name.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue TypedArray::prototype() const {
|
||||||
|
return _proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
Int8ArrayClass::Int8ArrayClass(ScriptEngine* scriptEngine) : TypedArray(scriptEngine, INT_8_ARRAY_CLASS_NAME) {
|
||||||
|
QScriptValue global = engine()->globalObject();
|
||||||
|
|
||||||
|
_bytesPerElement = sizeof(qint8);
|
||||||
|
|
||||||
|
// build prototype
|
||||||
|
// _proto = engine->newQObject(new DataViewPrototype(this),
|
||||||
|
// QScriptEngine::QtOwnership,
|
||||||
|
// QScriptEngine::SkipMethodsInEnumeration |
|
||||||
|
// QScriptEngine::ExcludeSuperClassMethods |
|
||||||
|
// QScriptEngine::ExcludeSuperClassProperties);
|
||||||
|
|
||||||
|
_proto.setPrototype(global.property("Object").property("prototype"));
|
||||||
|
|
||||||
|
_ctor = engine()->newFunction(construct, _proto);
|
||||||
|
_ctor.setData(engine()->toScriptValue(this));
|
||||||
|
|
||||||
|
engine()->globalObject().setProperty(name(), _ctor);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue Int8ArrayClass::newInstance(quint32 length) {
|
||||||
|
ArrayBufferClass* array = getScriptEngine()->getArrayBufferClass();
|
||||||
|
QScriptValue buffer = array->newInstance(length * _bytesPerElement);
|
||||||
|
return newInstance(buffer, 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue Int8ArrayClass::newInstance(QScriptValue array, bool isTypedArray) {
|
||||||
|
// TODO
|
||||||
|
assert(false);
|
||||||
|
if (isTypedArray) {
|
||||||
|
QByteArray* originalArray = qscriptvalue_cast<QByteArray*>(array.data().property(_bufferName).data());
|
||||||
|
ArrayBufferClass* arrayBufferClass = reinterpret_cast<ScriptEngine*>(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return newInstance(arrayBufferClass->newInstance(newArray),
|
||||||
|
array.data().property(_byteOffsetName).toInt32(),
|
||||||
|
array.data().property(_lengthName).toInt32());
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptClass::QueryFlags Int8ArrayClass::queryProperty(const QScriptValue& object,
|
||||||
|
const QScriptString& name,
|
||||||
|
QueryFlags flags, uint* id) {
|
||||||
|
quint32 byteOffset = object.data().property(_byteOffsetName).toInt32();
|
||||||
|
quint32 length = object.data().property(_lengthName).toInt32();
|
||||||
|
bool ok = false;
|
||||||
|
int pos = name.toArrayIndex(&ok);
|
||||||
|
|
||||||
|
// Check that name is a valid index and arrayBuffer exists
|
||||||
|
if (ok && pos >= 0 && pos < length) {
|
||||||
|
*id = byteOffset + pos * _bytesPerElement; // save pos to avoid recomputation
|
||||||
|
return HandlesReadAccess | HandlesWriteAccess; // Read/Write access
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypedArray::queryProperty(object, name, flags, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue Int8ArrayClass::property(const QScriptValue &object,
|
||||||
|
const QScriptString &name, uint 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);
|
||||||
|
|
||||||
|
qint8 result;
|
||||||
|
stream >> result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypedArray::property(object, name, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Int8ArrayClass::setProperty(QScriptValue &object,
|
||||||
|
const QScriptString &name,
|
||||||
|
uint id, const QScriptValue &value) {
|
||||||
|
qDebug() << "ID: " << id << ", Value: " << value.toInt32();
|
||||||
|
QByteArray *ba = qscriptvalue_cast<QByteArray*>(object.data().property(_bufferName).data());
|
||||||
|
if (ba && value.isNumber()) {
|
||||||
|
QDataStream stream(ba, QIODevice::ReadWrite);
|
||||||
|
stream.skipRawData(id);
|
||||||
|
|
||||||
|
qDebug() << "Adding: " << (qint8)value.toInt32();
|
||||||
|
stream << (qint8)value.toInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
104
libraries/script-engine/src/TypedArrays.h
Normal file
104
libraries/script-engine/src/TypedArrays.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// TypedArrays.h
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Clement on 7/9/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_TypedArrays_h
|
||||||
|
#define hifi_TypedArrays_h
|
||||||
|
|
||||||
|
#include "ArrayBufferViewClass.h"
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
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 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::PropertyFlags propertyFlags(const QScriptValue& object,
|
||||||
|
const QScriptString& name, uint id);
|
||||||
|
|
||||||
|
QString name() const;
|
||||||
|
QScriptValue prototype() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static QScriptValue construct(QScriptContext* context, QScriptEngine* engine);
|
||||||
|
|
||||||
|
QScriptValue _proto;
|
||||||
|
QScriptValue _ctor;
|
||||||
|
|
||||||
|
QScriptString _name;
|
||||||
|
QScriptString _bytesPerElementName;
|
||||||
|
QScriptString _lengthName;
|
||||||
|
|
||||||
|
quint32 _bytesPerElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
QueryFlags queryProperty(const QScriptValue& object,
|
||||||
|
const QScriptString& name,
|
||||||
|
QueryFlags flags, uint* id);
|
||||||
|
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 {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Uint8ClampedArrayClass : public TypedArray {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Int16ArrayClass : public TypedArray {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Uint16ArrayClass : public TypedArray {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Int32ArrayClass : public TypedArray {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Uint32ArrayClass : public TypedArray {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Float32ArrayClass : public TypedArray {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Float64ArrayClass : public TypedArray {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_TypedArrays_h
|
Loading…
Reference in a new issue