290ReturnedValue QQmlTypeWrapper::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
bool *hasProperty)
293 Q_ASSERT(m->as<QQmlTypeWrapper>());
296 return Object::virtualGet(m, id, receiver, hasProperty);
298 QV4::ExecutionEngine *v4 = m->engine();
299 QV4::Scope scope(v4);
300 ScopedString name(scope, id.asStringOrSymbol());
302 Scoped<QQmlTypeWrapper> w(scope,
static_cast<
const QQmlTypeWrapper *>(m));
307 QQmlRefPointer<QQmlContextData> context = v4->callingQmlContext();
309 QObject *object = w->d()->object;
310 QQmlType type = w->d()->type();
312 QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(v4->qmlEngine());
313 if (type.isValid()) {
316 if (type.isSingleton()) {
318 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
319 if (QObject *qobjectSingleton = enginePrivate->singletonInstance<QObject*>(type)) {
321 const bool includeEnums
322 = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums;
323 if (includeEnums && name->startsWithUpper()) {
325 int value = enumForSingleton(v4->typeLoader(), name, type, &ok);
327 return QV4::Value::fromInt32(value).asReturnedValue();
329 value = type.scopedEnumIndex(v4->typeLoader(), name, &ok);
331 return createEnumWrapper(v4, scope, type, value,
true);
333 value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok);
335 return createEnumWrapper(v4, scope, type, value,
false);
340 const ReturnedValue result = QV4::QObjectWrapper::getQmlProperty(
341 v4, context, w->d(), qobjectSingleton, name,
342 QV4::QObjectWrapper::AttachMethods, &ok);
348 }
else if (type.isQJSValueSingleton()) {
349 QJSValue scriptSingleton = enginePrivate->singletonInstance<QJSValue>(type);
350 if (!scriptSingleton.isUndefined()) {
352 QV4::ScopedObject o(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
362 if (name->startsWithUpper()) {
364 int value = type.enumValue(v4->typeLoader(), name, &ok);
366 return QV4::Value::fromInt32(value).asReturnedValue();
368 value = type.scopedEnumIndex(v4->typeLoader(), name, &ok);
370 return createEnumWrapper(v4, scope, type, value,
true);
372 value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok);
374 return createEnumWrapper(v4, scope, type, value,
false);
378 }
else if (w->d()->object) {
379 QObject *ao = qmlAttachedPropertiesObject(
380 object, type.attachedPropertiesFunction(v4->typeLoader()));
382 return QV4::QObjectWrapper::getQmlProperty(
383 v4, context, w->d(), ao, name, QV4::QObjectWrapper::AttachMethods,
394 }
else if (w->d()->kind() == Heap::QQmlTypeWrapper::Namespace) {
395 const QQmlTypeNameCache::Result r = w->d()->queryNamespace(name, v4);
397 if (r.type.isValid()) {
398 return create(scope.engine, object, r.type, w->d()->typeNameMode());
399 }
else if (r.scriptIndex != -1) {
400 QV4::ScopedObject scripts(scope, context->importedScripts());
401 return scripts->get(r.scriptIndex);
402 }
else if (r.importNamespace) {
403 return create(scope.engine, object, context->imports(), r.importNamespace);
406 return QV4::Encode::undefined();
413 Q_ASSERT(!
"Unreachable");
417 const ReturnedValue result = Object::virtualGet(m, id, receiver, &ok);
425bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id,
const Value &value, Value *receiver)
428 return Object::virtualPut(m, id, value, receiver);
431 Q_ASSERT(m->as<QQmlTypeWrapper>());
432 QQmlTypeWrapper *w =
static_cast<QQmlTypeWrapper *>(m);
434 if (scope.hasException())
437 ScopedString name(scope, id.asStringOrSymbol());
438 QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
440 QQmlType type = w->d()->type();
441 if (type.isValid() && !type.isSingleton() && w->d()->object) {
442 QObject *object = w->d()->object;
443 QObject *ao = qmlAttachedPropertiesObject(
444 object, type.attachedPropertiesFunction(scope.engine->typeLoader()));
446 return QV4::QObjectWrapper::setQmlProperty(
447 scope.engine, context, ao, name, QV4::QObjectWrapper::NoFlag, value);
449 }
else if (type.isSingleton()) {
450 QQmlEnginePrivate *e = QQmlEnginePrivate::get(scope.engine->qmlEngine());
451 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
452 if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type))
453 return QV4::QObjectWrapper::setQmlProperty(
454 scope.engine, context, qobjectSingleton, name,
455 QV4::QObjectWrapper::NoFlag, value);
458 QJSValue scriptSingleton = e->singletonInstance<QJSValue>(type);
459 if (!scriptSingleton.isUndefined()) {
460 QV4::ScopedObject apiprivate(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
462 QString error = QLatin1String(
"Cannot assign to read-only property \"") + name->toQString() + QLatin1Char(
'\"');
463 scope.engine->throwError(error);
466 return apiprivate->put(name, value);
502 const QV4::QQmlTypeWrapper *typeWrapper, QObject *wrapperObject)
504 QV4::ExecutionEngine *engine = typeWrapper->internalClass()->engine;
507 return engine->throwTypeError();
509 const QQmlType type = typeWrapper->d()->type();
510 const QMetaType myTypeId = type.typeId();
511 QQmlMetaObject myQmlType;
512 if (!myTypeId.isValid()) {
516 QQmlData *theirDData = QQmlData::get(wrapperObject);
517 Q_ASSERT(theirDData);
518 if (!theirDData->compilationUnit)
519 return Encode(
false);
521 QQmlRefPointer<QQmlTypeData> td
522 = engine->typeLoader()->getType(typeWrapper->d()->type().sourceUrl());
523 if (CompiledData::CompilationUnit *cu = td->compilationUnit())
524 myQmlType = QQmlMetaType::metaObjectForType(cu->metaType());
526 return Encode(
false);
528 myQmlType = QQmlMetaType::metaObjectForType(myTypeId);
529 if (myQmlType.isNull())
530 return Encode(
false);
533 const QMetaObject *theirType = wrapperObject->metaObject();
535 if (QQmlMetaObject::canConvert(theirType, myQmlType))
537 else if (type.isValueType())
538 return Encode::undefined();
540 return Encode(
false);
543ReturnedValue QQmlTypeWrapper::virtualInstanceOf(
const Object *typeObject,
const Value &var)
545 Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>());
546 const QV4::QQmlTypeWrapper *typeWrapper =
static_cast<
const QV4::QQmlTypeWrapper *>(typeObject);
548 if (
const QObjectWrapper *objectWrapper = var.as<QObjectWrapper>())
549 return instanceOfQObject(typeWrapper, objectWrapper->object());
551 if (
const QQmlTypeWrapper *varTypeWrapper = var.as<QQmlTypeWrapper>()) {
553 if (QObject *varObject = varTypeWrapper->object())
554 return instanceOfQObject(typeWrapper, varObject);
557 const QQmlType type = typeWrapper->d()->type();
560 if (!type.isValueType())
561 return Encode(
false);
563 const auto canCastValueType = [&]() ->
bool {
564 if (
const QQmlValueTypeWrapper *valueWrapper = var.as<QQmlValueTypeWrapper>()) {
565 return QQmlMetaObject::canConvert(
566 valueWrapper->metaObject(), type.metaObjectForValueType());
569 const QMetaType typeId = type.typeId();
570 if (
const VariantObject *variantObject = var.as<VariantObject>()) {
571 if (variantObject->d()->data().metaType() == typeId)
575 switch (typeId.id()) {
576 case QMetaType::Void:
577 return var.isUndefined();
578 case QMetaType::QVariant:
581 return var.isInteger();
582 case QMetaType::Double:
583 return var.isDouble();
584 case QMetaType::QString:
585 return var.isString();
586 case QMetaType::Bool:
587 return var.isBoolean();
588 case QMetaType::QUrl:
589 if (var.as<UrlObject>())
592 case QMetaType::QDate:
593 case QMetaType::QTime:
594 case QMetaType::QDateTime:
595 if (var.as<DateObject>())
606 return canCastValueType() ? Encode(
true) : Encode::undefined();
609ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(
const Object *object, ExecutionEngine *engine, Lookup *lookup)
612 PropertyKey id = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
614 return Object::virtualResolveLookupGetter(object, engine, lookup);
617 const QQmlTypeWrapper *This =
static_cast<
const QQmlTypeWrapper *>(object);
618 ScopedString name(scope, id.asStringOrSymbol());
619 QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
621 Scoped<QQmlTypeWrapper> w(scope,
static_cast<
const QQmlTypeWrapper *>(This));
622 QQmlType type = w->d()->type();
624 if (type.isValid()) {
626 if (type.isSingleton()) {
627 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
628 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
629 if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type)) {
630 const bool includeEnums
631 = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums;
632 if (!includeEnums || !name->startsWithUpper()) {
633 QQmlData *ddata = QQmlData::get(qobjectSingleton,
false);
634 if (ddata && ddata->propertyCache) {
635 const QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
637 ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
638 if (qualifiesForMethodLookup(property)) {
639 QV4::Heap::QObjectMethod *method =
nullptr;
640 setupQObjectMethodLookup(
641 lookup, ddata, property, val->objectValue(), method);
642 lookup->call = QV4::Lookup::Call::GetterSingletonMethod;
645 lookup, ddata, property, val->objectValue(), This);
646 lookup->call = QV4::Lookup::Call::GetterSingletonProperty;
648 return lookup->getter(engine, *object);
661 if (name->startsWithUpper()) {
663 QQmlTypeLoader *typeLoader = engine->typeLoader();
664 int value = type.enumValue(typeLoader, name, &ok);
666 lookup->qmlEnumValueLookup.ic.set(engine, This->internalClass());
667 lookup->qmlEnumValueLookup.encodedEnumValue
668 = QV4::Value::fromInt32(value).asReturnedValue();
669 lookup->call = QV4::Lookup::Call::GetterEnumValue;
670 return lookup->getter(engine, *object);
673 value = type.scopedEnumIndex(typeLoader, name, &ok);
675 Scoped<QQmlEnumWrapper> enumWrapper(
676 scope, createEnumWrapper(engine, scope, type, value,
true));
677 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
678 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
679 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
680 lookup->call = QV4::Lookup::Call::GetterEnum;
681 return enumWrapper.asReturnedValue();
684 value = type.unscopedEnumIndex(typeLoader, name, &ok);
686 Scoped<QQmlEnumWrapper> enumWrapper(
687 scope, createEnumWrapper(engine, scope, type, value,
false));
688 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
689 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
690 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
691 lookup->call = QV4::Lookup::Call::GetterEnum;
692 return enumWrapper.asReturnedValue();
696 }
else if (w->d()->object) {
697 QObject *ao = qmlAttachedPropertiesObject(
698 w->d()->object, type.attachedPropertiesFunction(engine->typeLoader()));
701 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
702 return lookup->getter(engine, *object);
708
709 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
710 return lookup->getter(engine, *object);
742ReturnedValue QQmlTypeWrapper::lookupSingletonProperty(Lookup *l, ExecutionEngine *engine,
const Value &object)
744 const auto revertLookup = [l, engine, &object]() {
745 l->qobjectLookup.propertyCache->release();
746 l->qobjectLookup.propertyCache =
nullptr;
747 l->call = QV4::Lookup::Call::GetterGeneric;
748 return Lookup::getterGeneric(l, engine, object);
753 Heap::Object *o =
static_cast<Heap::Object *>(object.heapObject());
764 if (!o || o->internalClass != l->qobjectLookup.qmlTypeIc)
765 return revertLookup();
767 Heap::QQmlTypeWrapper *This =
static_cast<Heap::QQmlTypeWrapper *>(o);
769 QQmlType type = This->type();
771 return revertLookup();
773 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
774 return revertLookup();
776 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
777 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
778 Q_ASSERT(qobjectSingleton);
781 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
782 const QObjectWrapper::Flags flags = l->forCall
783 ? QObjectWrapper::AllowOverride
784 : (QObjectWrapper::AttachMethods | QObjectWrapper::AllowOverride);
785 return QObjectWrapper::lookupPropertyGetterImpl(l, engine, obj, flags, revertLookup);
788ReturnedValue QQmlTypeWrapper::lookupSingletonMethod(Lookup *l, ExecutionEngine *engine,
const Value &object)
790 const auto revertLookup = [l, engine, &object]() {
791 l->qobjectMethodLookup.propertyCache->release();
792 l->qobjectMethodLookup.propertyCache =
nullptr;
793 l->call = QV4::Lookup::Call::GetterGeneric;
794 return Lookup::getterGeneric(l, engine, object);
798 const QQmlTypeWrapper *This = object.as<QQmlTypeWrapper>();
800 return revertLookup();
802 QQmlType type = This->d()->type();
804 return revertLookup();
806 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
807 return revertLookup();
809 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
810 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
811 Q_ASSERT(qobjectSingleton);
814 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
815 return QObjectWrapper::lookupMethodGetterImpl(
816 l, engine, obj, l->forCall ? QObjectWrapper::NoFlag : QObjectWrapper::AttachMethods,
859ReturnedValue QQmlEnumWrapper::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
862 Q_ASSERT(m->as<QQmlEnumWrapper>());
864 return Object::virtualGet(m, id, receiver, hasProperty);
866 const QQmlEnumWrapper *resource =
static_cast<
const QQmlEnumWrapper *>(m);
867 QV4::ExecutionEngine *v4 = resource->engine();
868 QV4::Scope scope(v4);
869 ScopedString name(scope, id.asStringOrSymbol());
871 QQmlType type = resource->d()->type();
872 int index = resource->d()->enumIndex;
875 auto *typeLoader = v4->typeLoader();
876 int value = resource->d()->scoped ? type.scopedEnumValue(typeLoader, index, name, &ok)
877 : type.unscopedEnumValue(typeLoader, index, name, &ok);
881 return QV4::Value::fromInt32(value).asReturnedValue();
883 return Object::virtualGet(m, id, receiver, hasProperty);