| 1 | // Copyright (C) 2024 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 3 | |
| 4 | #include "qv4qmetaobjectwrapper_p.h" |
| 5 | |
| 6 | #include <private/qqmlobjectorgadget_p.h> |
| 7 | #include <private/qv4jscall_p.h> |
| 8 | #include <private/qv4qobjectwrapper_p.h> |
| 9 | |
| 10 | QT_BEGIN_NAMESPACE |
| 11 | |
| 12 | using namespace Qt::StringLiterals; |
| 13 | |
| 14 | namespace QV4 { |
| 15 | |
| 16 | void Heap::QMetaObjectWrapper::init(const QMetaObject *metaObject) |
| 17 | { |
| 18 | FunctionObject::init(); |
| 19 | m_metaObject = metaObject; |
| 20 | } |
| 21 | |
| 22 | void Heap::QMetaObjectWrapper::destroy() |
| 23 | { |
| 24 | delete[] m_constructors; |
| 25 | FunctionObject::destroy(); |
| 26 | } |
| 27 | |
| 28 | ReturnedValue QMetaObjectWrapper::create(ExecutionEngine *engine, const QMetaObject* metaObject) { |
| 29 | |
| 30 | Scope scope(engine); |
| 31 | Scoped<QMetaObjectWrapper> mo(scope, engine->memoryManager->allocate<QMetaObjectWrapper>(args&: metaObject)->asReturnedValue()); |
| 32 | mo->init(engine); |
| 33 | return mo->asReturnedValue(); |
| 34 | } |
| 35 | |
| 36 | void QMetaObjectWrapper::init(ExecutionEngine *) { |
| 37 | const QMetaObject &mo = *d()->metaObject(); |
| 38 | |
| 39 | for (int i = 0; i < mo.enumeratorCount(); i++) { |
| 40 | QMetaEnum Enum = mo.enumerator(index: i); |
| 41 | for (int k = 0; k < Enum.keyCount(); k++) { |
| 42 | const char* key = Enum.key(index: k); |
| 43 | const int value = Enum.value(index: k); |
| 44 | defineReadonlyProperty(name: QLatin1String(key), value: Value::fromInt32(i: value)); |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | ReturnedValue QMetaObjectWrapper::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *) |
| 50 | { |
| 51 | Q_ASSERT(f->as<QMetaObjectWrapper>()); |
| 52 | return construct(d: static_cast<const QMetaObjectWrapper*>(f)->d(), argv, argc); |
| 53 | } |
| 54 | |
| 55 | ReturnedValue QMetaObjectWrapper::constructInternal( |
| 56 | const QMetaObject *mo, const QQmlPropertyData *constructors, Heap::FunctionObject *d, |
| 57 | const Value *argv, int argc) |
| 58 | { |
| 59 | ExecutionEngine *v4 = d->internalClass->engine; |
| 60 | |
| 61 | if (!constructors) { |
| 62 | return v4->throwTypeError(message: QLatin1String(mo->className()) |
| 63 | + QLatin1String(" has no invokable constructor" )); |
| 64 | } |
| 65 | |
| 66 | Scope scope(v4); |
| 67 | ScopedObject object(scope); |
| 68 | JSCallData cData(nullptr, argv, argc); |
| 69 | CallData *callData = cData.callData(scope); |
| 70 | |
| 71 | const QQmlObjectOrGadget objectOrGadget(mo); |
| 72 | |
| 73 | const auto callType = [](QMetaType metaType) { |
| 74 | return metaType.flags() & QMetaType::PointerToQObject |
| 75 | ? QMetaObject::CreateInstance |
| 76 | : QMetaObject::ConstructInPlace; |
| 77 | }; |
| 78 | |
| 79 | const int constructorCount = mo->constructorCount(); |
| 80 | if (constructorCount == 1) { |
| 81 | object = QObjectMethod::callPrecise( |
| 82 | object: objectOrGadget, data: constructors[0], engine: v4, callArgs: callData, |
| 83 | callType: callType(constructors[0].propType())); |
| 84 | } else if (const QQmlPropertyData *ctor = QObjectMethod::resolveOverloaded( |
| 85 | object: objectOrGadget, methods: constructors, methodCount: constructorCount, engine: v4, callArgs: callData)) { |
| 86 | object = QObjectMethod::callPrecise( |
| 87 | object: objectOrGadget, data: *ctor, engine: v4, callArgs: callData, callType: callType(ctor->propType())); |
| 88 | } |
| 89 | |
| 90 | if (object) { |
| 91 | Scoped<FunctionObject> functionObject(scope, d); |
| 92 | object->defineDefaultProperty(name: v4->id_constructor(), value: functionObject); |
| 93 | object->setPrototypeOf(functionObject); |
| 94 | } |
| 95 | |
| 96 | return object.asReturnedValue(); |
| 97 | } |
| 98 | |
| 99 | bool QMetaObjectWrapper::virtualIsEqualTo(Managed *a, Managed *b) |
| 100 | { |
| 101 | const QMetaObjectWrapper *aMetaObject = a->as<QMetaObjectWrapper>(); |
| 102 | Q_ASSERT(aMetaObject); |
| 103 | const QMetaObjectWrapper *bMetaObject = b->as<QMetaObjectWrapper>(); |
| 104 | return bMetaObject && aMetaObject->metaObject() == bMetaObject->metaObject(); |
| 105 | } |
| 106 | |
| 107 | DEFINE_OBJECT_VTABLE(QMetaObjectWrapper); |
| 108 | |
| 109 | } // namespace QV4 |
| 110 | |
| 111 | QT_END_NAMESPACE |
| 112 | |