121QJSManagedValue::QJSManagedValue(QJSValue value, QJSEngine *engine)
123 QV4::ExecutionEngine *v4 = engine->handle();
125 if (QV4::Value *m = QJSValuePrivate::takeManagedValue(&value)) {
126 if (Q_UNLIKELY(v4Engine(m) != v4)) {
127 qWarning(
"QJSManagedValue(QJSValue, QJSEngine *) failed: "
128 "Value was created in different engine.");
129 QV4::PersistentValueStorage::free(m);
137 d = v4->memoryManager->m_persistentValues->allocate();
139 if (
const QString *string = QJSValuePrivate::asQString(&value))
140 *d = v4->newString(*string);
142 *d = QJSValuePrivate::asReturnedValue(&value);
148QJSManagedValue::QJSManagedValue(
const QJSPrimitiveValue &value, QJSEngine *engine) :
149 QJSManagedValue(engine->handle())
151 switch (value.type()) {
152 case QJSPrimitiveValue::Undefined:
153 *d = QV4::Encode::undefined();
155 case QJSPrimitiveValue::Null:
156 *d = QV4::Encode::null();
158 case QJSPrimitiveValue::Boolean:
159 *d = QV4::Encode(value.asBoolean());
161 case QJSPrimitiveValue::Integer:
162 *d = QV4::Encode(value.asInteger());
164 case QJSPrimitiveValue::Double:
165 *d = QV4::Encode(value.asDouble());
167 case QJSPrimitiveValue::String:
168 *d = engine->handle()->newString(value.asString());
178QJSManagedValue::QJSManagedValue(
const QVariant &variant, QJSEngine *engine) :
179 QJSManagedValue(engine->handle())
181 *d = engine->handle()->fromVariant(variant);
187QJSManagedValue::QJSManagedValue(
const QString &string, QJSEngine *engine) :
188 QJSManagedValue(engine->handle())
190 *d = engine->handle()->newString(string);
285QJSManagedValue QJSManagedValue::prototype()
const
288 return QJSManagedValue();
290 QV4::ExecutionEngine *v4 = v4Engine(d);
291 QJSManagedValue result(v4);
293 if (
auto object = d->as<QV4::Object>())
294 *result.d = object->getPrototypeOf();
295 else if (
auto managed = d->as<QV4::Managed>())
296 *result.d = managed->internalClass()->prototype;
297 else if (d->isBoolean())
298 *result.d = v4->booleanPrototype();
299 else if (d->isNumber())
300 *result.d = v4->numberPrototype();
303 if (result.d->isUndefined())
304 *result.d = QV4::Encode::null();
315void QJSManagedValue::setPrototype(
const QJSManagedValue &prototype)
317 auto object = d ? d->as<QV4::Object>() :
nullptr;
319 qWarning(
"QJSManagedValue::setPrototype() failed: "
320 "Can only set a prototype on an object (excluding null).");
325 if (prototype.type() != QJSManagedValue::Object) {
326 qWarning(
"QJSManagedValue::setPrototype() failed: "
327 "Can only set objects (including null) as prototypes.");
331 if (Q_UNLIKELY(object->engine() != v4Engine(prototype.d))) {
332 qWarning(
"QJSManagedValue::setPrototype() failed: "
333 "Prototype was created in differen engine.");
338 if (!object->setPrototypeOf(prototype.d->as<QV4::Object>())) {
339 qWarning(
"QJSManagedValue::setPrototype() failed: "
340 "Prototype cycle detected.");
622QVariant QJSManagedValue::toVariant()
const
624 if (!d || d->isUndefined())
627 return QVariant(QMetaType::fromType<std::nullptr_t>(),
nullptr);
629 return QVariant(d->booleanValue());
631 return QVariant(d->integerValue());
633 return QVariant(d->doubleValue());
635 return QVariant(d->toQString());
636 if (d->as<QV4::Managed>())
637 return QV4::ExecutionEngine::toVariant(*d, QMetaType{},
true);
639 Q_UNREACHABLE_RETURN(QVariant());
701bool QJSManagedValue::hasProperty(
const QString &name)
const
703 if (!d || d->isNullOrUndefined())
706 if (d->isString() && name == QStringLiteral(
"length"))
709 if (QV4::Object *obj = d->as<QV4::Object>()) {
710 QV4::Scope scope(obj->engine());
711 QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
712 return obj->hasProperty(key);
715 return prototype().hasProperty(name);
722bool QJSManagedValue::hasOwnProperty(
const QString &name)
const
724 if (!d || d->isNullOrUndefined())
727 if (d->isString() && name == QStringLiteral(
"length"))
730 if (QV4::Object *obj = d->as<QV4::Object>()) {
731 QV4::Scope scope(obj->engine());
732 QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
733 return obj->getOwnProperty(key) != QV4::Attr_Invalid;
743QJSValue QJSManagedValue::property(
const QString &name)
const
748 if (d->isNullOrUndefined()) {
749 QV4::ExecutionEngine *e = v4Engine(d);
750 e->throwTypeError(QStringLiteral(
"Cannot read property '%1' of null").arg(name));
754 if (QV4::String *string = d->as<QV4::String>()) {
755 if (name == QStringLiteral(
"length"))
756 return QJSValue(string->d()->length());
759 if (QV4::Object *obj = d->as<QV4::Object>()) {
760 QV4::Scope scope(obj->engine());
761 QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
762 return QJSValuePrivate::fromReturnedValue(obj->get(key));
765 return prototype().property(name);
773void QJSManagedValue::setProperty(
const QString &name,
const QJSValue &value)
778 if (d->isNullOrUndefined()) {
779 v4Engine(d)->throwTypeError(
780 QStringLiteral(
"Value is null and could not be converted to an object"));
783 if (QV4::Object *obj = d->as<QV4::Object>()) {
784 QV4::Scope scope(obj->engine());
785 QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
786 if (Q_UNLIKELY(v4 && v4 != scope.engine)) {
787 qWarning(
"QJSManagedValue::setProperty() failed: "
788 "Value was created in different engine.");
791 QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
792 QV4::ScopedValue val(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, value));
801bool QJSManagedValue::deleteProperty(
const QString &name)
806 if (QV4::Object *obj = d->as<QV4::Object>()) {
807 QV4::Scope scope(obj->engine());
808 QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
809 return obj->deleteProperty(key);
820bool QJSManagedValue::hasProperty(quint32 arrayIndex)
const
822 if (!d || d->isNullOrUndefined())
825 if (QV4::String *string = d->as<QV4::String>())
826 return arrayIndex < quint32(string->d()->length());
828 if (QV4::Object *obj = d->as<QV4::Object>()) {
829 bool hasProperty =
false;
830 if (arrayIndex == std::numeric_limits<quint32>::max())
831 obj->get(obj->engine()->id_uintMax(), &hasProperty);
833 obj->get(arrayIndex, &hasProperty);
837 return prototype().hasProperty(arrayIndex);
845bool QJSManagedValue::hasOwnProperty(quint32 arrayIndex)
const
847 if (!d || d->isNullOrUndefined())
850 if (QV4::String *string = d->as<QV4::String>())
851 return arrayIndex < quint32(string->d()->length());
853 if (QV4::Object *obj = d->as<QV4::Object>()) {
854 if (arrayIndex == std::numeric_limits<quint32>::max()) {
855 return obj->getOwnProperty(obj->engine()->id_uintMax()->toPropertyKey())
856 != QV4::Attr_Invalid;
858 return obj->getOwnProperty(QV4::PropertyKey::fromArrayIndex(arrayIndex))
859 != QV4::Attr_Invalid;
871QJSValue QJSManagedValue::property(quint32 arrayIndex)
const
873 if (!d || d->isNullOrUndefined())
876 if (QV4::String *string = d->as<QV4::String>()) {
877 const QString qString = string->toQString();
878 if (arrayIndex < quint32(qString.size()))
879 return qString.sliced(arrayIndex, 1);
883 if (QV4::Object *obj = d->as<QV4::Object>()) {
884 if (arrayIndex == std::numeric_limits<quint32>::max())
885 return QJSValuePrivate::fromReturnedValue(obj->get(obj->engine()->id_uintMax()));
887 return QJSValuePrivate::fromReturnedValue(obj->get(arrayIndex));
890 return prototype().property(arrayIndex);
899void QJSManagedValue::setProperty(quint32 arrayIndex,
const QJSValue &value)
904 if (QV4::Object *obj = d->as<QV4::Object>()) {
905 QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
906 if (Q_UNLIKELY(v4 && v4 != obj->engine())) {
907 qWarning(
"QJSManagedValue::setProperty() failed: "
908 "Value was created in different engine.");
912 QV4::Scope scope(v4);
913 QV4::ScopedValue v(scope, QJSValuePrivate::convertToReturnedValue(v4, value));
914 obj->put(arrayIndex, v);
957QJSValue QJSManagedValue::call(
const QJSValueList &arguments)
const
959 const QV4::FunctionObject *f = functionObjectForCall(d);
963 QV4::ExecutionEngine *engine = f->engine();
965 QV4::Scope scope(engine);
966 QV4::JSCallArguments jsCallData(scope, arguments.size());
967 *jsCallData.thisObject = engine->globalObject;
969 for (
const QJSValue &arg : arguments) {
970 if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
971 qWarning(
"QJSManagedValue::call() failed: Argument was created in different engine.");
974 jsCallData.args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
977 return QJSValuePrivate::fromReturnedValue(f->call(jsCallData));
989QJSValue QJSManagedValue::callWithInstance(
const QJSValue &instance,
990 const QJSValueList &arguments)
const
992 const QV4::FunctionObject *f = functionObjectForCall(d);
996 QV4::ExecutionEngine *engine = f->engine();
998 if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, instance))) {
999 qWarning(
"QJSManagedValue::callWithInstance() failed: "
1000 "Instance was created in different engine.");
1004 QV4::Scope scope(engine);
1005 QV4::JSCallArguments jsCallData(scope, arguments.size());
1006 *jsCallData.thisObject = QJSValuePrivate::convertToReturnedValue(engine, instance);
1008 for (
const QJSValue &arg : arguments) {
1009 if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
1010 qWarning(
"QJSManagedValue::callWithInstance() failed: "
1011 "Argument was created in different engine.");
1014 jsCallData.args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
1017 return QJSValuePrivate::fromReturnedValue(f->call(jsCallData));
1029QJSValue QJSManagedValue::callAsConstructor(
const QJSValueList &arguments)
const
1031 const QV4::FunctionObject *f = functionObjectForCall(d);
1035 QV4::ExecutionEngine *engine = f->engine();
1037 QV4::Scope scope(engine);
1038 QV4::JSCallArguments jsCallData(scope, arguments.size());
1040 for (
const QJSValue &arg : arguments) {
1041 if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
1042 qWarning(
"QJSManagedValue::callAsConstructor() failed: "
1043 "Argument was created in different engine.");
1046 jsCallData.args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
1049 return QJSValuePrivate::fromReturnedValue(f->callAsConstructor(jsCallData));
1085QStringList QJSManagedValue::jsMetaMembers()
const
1090 if (QV4::InternalClass *c = d->as<QV4::InternalClass>()) {
1091 const auto heapClass = c->d();
1092 const int size = heapClass->size;
1094 result.reserve(size);
1095 QV4::Scope scope(c->engine());
1096 for (
int i = 0; i < size; ++i) {
1097 QV4::ScopedValue key(scope, heapClass->keyAt(i));
1098 result.append(key->toQString());
1118QJSManagedValue QJSManagedValue::jsMetaInstantiate(
const QJSValueList &values)
const
1123 if (QV4::InternalClass *c = d->as<QV4::InternalClass>()) {
1124 QV4::ExecutionEngine *engine = c->engine();
1125 QJSManagedValue result(engine);
1126 *result.d = c->engine()->newObject(c->d());
1127 QV4::Object *o = result.d->as<QV4::Object>();
1129 QV4::Scope scope(engine);
1130 QV4::ScopedValue val(scope);
1131 for (uint i = 0, end = qMin(qsizetype(c->d()->size), values.size()); i < end; ++i) {
1132 const QJSValue &arg = values[i];
1133 if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
1134 qWarning(
"QJSManagedValue::instantiate() failed: "
1135 "Argument was created in different engine.");
1136 return QJSManagedValue();
1138 val = QJSValuePrivate::convertToReturnedValue(engine, arg);
1139 o->setProperty(i, val);