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 | |