History

Initial V8 support, not working yet

ksuprynowicz committed 4 years ago

Commit 7e9ad391 parent df507a740 files · +4040 −3087Browse files

Showing the changes to libraries/script-engine/src/v8/ArrayBufferClass.cpp (1 of 40 files). Show all

Unified · Split

libraries/script-engine/src/v8/ArrayBufferClass.cpp+179−0
@@ -0,0 +1,179 @@
1+//
2+// ArrayBufferClass.cpp
3+//
4+//
5+// Created by Clement on 7/3/14.
6+// Copyright 2014 High Fidelity, Inc.
7+//
8+// Distributed under the Apache License, Version 2.0.
9+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10+//
11+
12+#include "ArrayBufferClass.h"
13+
14+#include <QDebug>
15+
16+#include "ArrayBufferPrototype.h"
17+#include "DataViewClass.h"
18+#include "ScriptEngineV8.h"
19+#include "TypedArrays.h"
20+
21+
22+// V8TODO
23+/*static const QString CLASS_NAME = "ArrayBuffer";
24+
25+// FIXME: Q_DECLARE_METATYPE is global and really belongs in a shared header file, not per .cpp like this
26+// (see DataViewClass.cpp, etc. which would also have to be updated to resolve)
27+Q_DECLARE_METATYPE(QByteArray*)
28+
29+ArrayBufferClass::ArrayBufferClass(ScriptEngineV8* scriptEngine) :
30+QObject(scriptEngine),
31+QScriptClass(scriptEngine) {
32+ qScriptRegisterMetaType<QByteArray>(engine(), toScriptValue, fromScriptValue);
33+ V8ScriptValue global = engine()->globalObject();
34+
35+ // Save string handles for quick lookup
36+ _name = engine()->toStringHandle(CLASS_NAME.toLatin1());
37+ _byteLength = engine()->toStringHandle(BYTE_LENGTH_PROPERTY_NAME.toLatin1());
38+
39+ // build prototype
40+ _proto = engine()->newQObject(new ArrayBufferPrototype(this),
41+ QScriptEngine::QtOwnership,
42+ QScriptEngine::SkipMethodsInEnumeration |
43+ QScriptEngine::ExcludeSuperClassMethods |
44+ QScriptEngine::ExcludeSuperClassProperties);
45+ _proto.setPrototype(global.property("Object").property("prototype"));
46+
47+ // Register constructor
48+ _ctor = engine()->newFunction(construct, _proto);
49+ _ctor.setData(engine()->toScriptValue(this));
50+
51+ engine()->globalObject().setProperty(name(), _ctor);
52+
53+ // Registering other array types
54+ // The script engine is there parent so it'll delete them with itself
55+ new DataViewClass(scriptEngine);
56+ new Int8ArrayClass(scriptEngine);
57+ new Uint8ArrayClass(scriptEngine);
58+ new Uint8ClampedArrayClass(scriptEngine);
59+ new Int16ArrayClass(scriptEngine);
60+ new Uint16ArrayClass(scriptEngine);
61+ new Int32ArrayClass(scriptEngine);
62+ new Uint32ArrayClass(scriptEngine);
63+ new Float32ArrayClass(scriptEngine);
64+ new Float64ArrayClass(scriptEngine);
65+}
66+
67+V8ScriptValue ArrayBufferClass::newInstance(qint32 size) {
68+ const qint32 MAX_LENGTH = 100000000;
69+ if (size < 0) {
70+ engine()->evaluate("throw \"ArgumentError: negative length\"");
71+ return V8ScriptValue();
72+ }
73+ if (size > MAX_LENGTH) {
74+ engine()->evaluate("throw \"ArgumentError: absurd length\"");
75+ return V8ScriptValue();
76+ }
77+ // We've patched qt to fix https://highfidelity.atlassian.net/browse/BUGZ-46 on mac and windows only.
78+#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
79+ engine()->reportAdditionalMemoryCost(size);
80+#endif
81+ QScriptEngine* eng = engine();
82+ QVariant variant = QVariant::fromValue(QByteArray(size, 0));
83+ V8ScriptValue data = eng->newVariant(variant);
84+ return engine()->newObject(this, data);
85+}
86+
87+V8ScriptValue ArrayBufferClass::newInstance(const QByteArray& ba) {
88+ QScriptEngine* eng = engine();
89+ V8ScriptValue data = eng->newVariant(QVariant::fromValue(ba));
90+ return eng->newObject(this, data);
91+}
92+
93+V8ScriptValue ArrayBufferClass::construct(V8ScriptContext* context, QScriptEngine* engine) {
94+ ArrayBufferClass* cls = qscriptvalue_cast<ArrayBufferClass*>(context->callee().data());
95+ if (!cls) {
96+ // return if callee (function called) is not of type ArrayBuffer
97+ return V8ScriptValue();
98+ }
99+ V8ScriptValue arg = context->argument(0);
100+ if (!arg.isValid() || !arg.isNumber()) {
101+ return V8ScriptValue();
102+ }
103+
104+ quint32 size = arg.toInt32();
105+ V8ScriptValue newObject = cls->newInstance(size);
106+
107+ if (context->isCalledAsConstructor()) {
108+ // if called with keyword new, replace this object.
109+ context->setThisObject(newObject);
110+ return engine->undefinedValue();
111+ }
112+
113+ return newObject;
114+}
115+
116+ScriptObjectV8Proxy::QueryFlags ArrayBufferClass::queryProperty(const V8ScriptValue& object,
117+ const V8ScriptString& name,
118+ QueryFlags flags, uint* id) {
119+ QByteArray* ba = qscriptvalue_cast<QByteArray*>(object.data());
120+ if (ba && name == _byteLength) {
121+ // if the property queried is byteLength, only handle read access
122+ return flags &= HandlesReadAccess;
123+ }
124+ return ScriptObjectV8Proxy::QueryFlags(); // No access
125+}
126+
127+V8ScriptValue ArrayBufferClass::property(const V8ScriptValue& object,
128+ const V8ScriptString& name, uint id) {
129+ QByteArray* ba = qscriptvalue_cast<QByteArray*>(object.data());
130+ if (ba && name == _byteLength) {
131+ return ba->length();
132+ }
133+ return V8ScriptValue();
134+}
135+
136+V8ScriptValue::PropertyFlags ArrayBufferClass::propertyFlags(const V8ScriptValue& object,
137+ const V8ScriptString& name, uint id) {
138+ return V8ScriptValue::Undeletable;
139+}
140+
141+QString ArrayBufferClass::name() const {
142+ return _name.toString();
143+}
144+
145+V8ScriptValue ArrayBufferClass::prototype() const {
146+ return _proto;
147+}
148+
149+V8ScriptValue ArrayBufferClass::toScriptValue(QScriptEngine* engine, const QByteArray& ba) {
150+ V8ScriptValue ctor = engine->globalObject().property(CLASS_NAME);
151+ ArrayBufferClass* cls = qscriptvalue_cast<ArrayBufferClass*>(ctor.data());
152+ if (!cls) {
153+ if (engine->currentContext()) {
154+ engine->currentContext()->throwError("arrayBufferClass::toScriptValue -- could not get " + CLASS_NAME + " class constructor");
155+ }
156+ return V8ScriptValue::NullValue;
157+ }
158+ return cls->newInstance(ba);
159+}
160+
161+void ArrayBufferClass::fromScriptValue(const V8ScriptValue& object, QByteArray& byteArray) {
162+ if (object.isString()) {
163+ // UTF-8 encoded String
164+ byteArray = object.toString().toUtf8();
165+ } else if (object.isArray()) {
166+ // Array of uint8s eg: [ 128, 3, 25, 234 ]
167+ auto Uint8Array = object.engine()->globalObject().property("Uint8Array");
168+ auto typedArray = Uint8Array.construct(V8ScriptValueList{object});
169+ if (QByteArray* buffer = qscriptvalue_cast<QByteArray*>(typedArray.property("buffer"))) {
170+ byteArray = *buffer;
171+ }
172+ } else if (object.isObject()) {
173+ // ArrayBuffer instance (or any JS class that supports coercion into QByteArray*)
174+ if (QByteArray* buffer = qscriptvalue_cast<QByteArray*>(object.data())) {
175+ byteArray = *buffer;
176+ }
177+ }
178+}
179+*/