20#include <private/qtqmlglobal_p.h>
21#include <private/qv4value_p.h>
22#include <private/qv4string_p.h>
23#include <private/qv4engine_p.h>
24#include <private/qv4mm_p.h>
25#include <private/qv4persistent_p.h>
27#include <QtCore/qthread.h>
33 static constexpr quint64 s_tagBits = 3;
34 static constexpr quint64 s_tagMask = (1 << s_tagBits) - 1;
36 static constexpr quint64 s_pointerBit = 0x1;
50 static_assert(quint64(
Kind::Null) <= s_tagMask);
57 static Kind tag(quint64 raw) {
return Kind(raw & s_tagMask); }
59#if QT_POINTER_SIZE == 4
63 return reinterpret_cast<
void *>(
raw >> 32);
73 static_assert(
alignof(
double) >= s_minAlignment);
79 Q_ASSERT(quint64(tag(raw)) & s_pointerBit);
80 return reinterpret_cast<
void *>(raw & ~s_tagMask);
85 Q_ASSERT(quint64(tag) & s_pointerBit);
86 return quintptr(pointer) | quint64(tag);
113 return (uintValue < uint(std::numeric_limits<
int>::max()))
114 ? encode(
int(uintValue))
115 : encode(
double(uintValue));
132 return static_cast<
double *>(pointer(v));
143 return static_cast<QV4::Value *>(pointer(v));
148 switch (qv4Value.type()) {
149 case QV4::StaticValue::Boolean_Type:
150 return encode(qv4Value.booleanValue());
151 case QV4::StaticValue::Integer_Type:
152 return encode(qv4Value.integerValue());
153 case QV4::StaticValue::Managed_Type: {
154 auto managed = qv4Value.as<QV4::Managed>();
155 auto engine = managed->engine();
156 auto mm = engine->memoryManager;
157 QV4::Value *m = mm->m_persistentValues->allocate();
161 QV4::WriteBarrier::markCustom(engine, [&](QV4::MarkStack *stack){
162 if constexpr (QV4::WriteBarrier::isInsertionBarrier)
163 managed->heapObject()->mark(stack);
168 case QV4::StaticValue::Double_Type:
169 return encode(qv4Value.doubleValue());
170 case QV4::StaticValue::Null_Type:
172 case QV4::StaticValue::Empty_Type:
175 case QV4::StaticValue::Undefined_Type:
179 return encodeUndefined();
185 return static_cast<QString *>(pointer(v));
190 return encodePointer(
new QString(std::move(stringValue)), Kind::QStringPtr);
195 return encodePointer(
new QString(std::move(stringValue)), Kind::QStringPtr);
201 setValue(&result, QV4::Value::fromReturnedValue(d));
209 if (
const QV4::Value *value = qv4ValuePtr(jsval->d))
210 return value->as<T>();
219 if (QV4::Value *value = qv4ValuePtr(jsval->d)) {
220 jsval->d = encodeUndefined();
229 switch (tag(jsval->d)) {
230 case Kind::BoolValue:
231 return QV4::Encode(boolValue(jsval->d));
233 return QV4::Encode(intValue(jsval->d));
234 case Kind::DoublePtr:
235 return QV4::Encode(*doublePtr(jsval->d));
237 return QV4::Encode::null();
244 return QV4::Encode::undefined();
252 if (
const QString *string = qStringPtr(jsval->d))
260 switch (tag(jsval->d)) {
261 case Kind::BoolValue:
262 return QV4::Encode(boolValue(jsval->d));
264 return QV4::Encode(intValue(jsval->d));
265 case Kind::DoublePtr:
266 return QV4::Encode(*doublePtr(jsval->d));
268 return QV4::Encode::null();
270 return qv4ValuePtr(jsval->d)->asReturnedValue();
276 return QV4::Encode::undefined();
281 jsval->d = encode(std::move(s));
291 static void setValue(QJSValue *jsval,
const QV4::Value &v)
293 jsval->d = encode(v);
300 jsval->d = encode(QV4::Value::fromHeapObject(e->newString(*string)));
308 const QJSValue &jsval)
311 return e->newString(*string)->asReturnedValue();
312 if (
const QV4::Value *val = asManagedType<QV4::Managed>(&jsval)) {
313 if (QV4::PersistentValueStorage::getEngine(val) == e)
314 return val->asReturnedValue();
316 qWarning(
"JSValue can't be reassigned to another engine.");
317 return QV4::Encode::undefined();
319 return asPrimitiveType(&jsval);
322 static QV4::ExecutionEngine *
engine(
const QJSValue *jsval)
325 if (
const QV4::Value *value = qv4ValuePtr(jsval->d))
326 return QV4::PersistentValueStorage::getEngine(value);
335 return !v4 || v4 == e;
338 static void free(QJSValue *jsval)
340 switch (tag(jsval->d)) {
347 delete doublePtr(jsval->d);
350 delete qStringPtr(jsval->d);
357 QV4::Value *m = qv4ValuePtr(jsval->d);
359 if (
QV4::ExecutionEngine *e = QV4::PersistentValueStorage::getEngine(m)) {
360 if (
QJSEngine *jsEngine = e->jsEngine()) {
361 if (jsEngine->thread() != QThread::currentThread()) {
362 QMetaObject::invokeMethod(
363 jsEngine, [m](){ QV4::PersistentValueStorage::free(m); });
368 QV4::PersistentValueStorage::free(m);
The QJSValueIterator class provides a Java-style iterator for QJSValue.
static quint64 encode(bool boolValue)
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
static void setString(QJSValue *jsval, QString s)
static bool boolValue(quint64 v)
static QV4::Value * qv4ValuePtr(quint64 v)
static int intValue(quint64 v)
static double * doublePtr(quint64 v)
static bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval)
static QV4::ExecutionEngine * engine(const QJSValue *jsval)
static quint64 encodePointer(void *pointer, Kind tag)
static QV4::Value * takeManagedValue(QJSValue *jsval)
static QV4::ReturnedValue asReturnedValue(const QJSValue *jsval)
static const QString * asQString(const QJSValue *jsval)
static quint64 encodeNull()
static constexpr quint64 s_minAlignment
static QString * qStringPtr(quint64 v)
static QV4::ReturnedValue convertToReturnedValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
static quint64 encode(const QV4::Value &qv4Value)
static void adoptPersistentValue(QJSValue *jsval, QV4::Value *v)
static QV4::ReturnedValue asPrimitiveType(const QJSValue *jsval)
static void setValue(QJSValue *jsval, const QV4::Value &v)
static void manageStringOnV4Heap(QV4::ExecutionEngine *e, QJSValue *jsval)
static quint64 encode(int intValue)
static const T * asManagedType(const QJSValue *jsval)
static quint64 encode(double doubleValue)
static void * pointer(quint64 raw)
static quint64 encode(QString stringValue)
static quint64 encodeUndefined()
static void free(QJSValue *jsval)
static Kind tag(quint64 raw)
Combined button and popup list for selecting options.