296ReturnedValue QQmlTypeWrapper::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
bool *hasProperty)
299 Q_ASSERT(m->as<QQmlTypeWrapper>());
302 return Object::virtualGet(m, id, receiver, hasProperty);
304 QV4::ExecutionEngine *v4 = m->engine();
305 QV4::Scope scope(v4);
306 ScopedString name(scope, id.asStringOrSymbol());
308 Scoped<QQmlTypeWrapper> w(scope,
static_cast<
const QQmlTypeWrapper *>(m));
313 QQmlRefPointer<QQmlContextData> context = v4->callingQmlContext();
315 QObject *object = w->d()->object;
316 QQmlType type = w->d()->type();
318 QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(v4->qmlEngine());
319 if (type.isValid()) {
322 if (type.isSingleton()) {
324 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
325 if (QObject *qobjectSingleton = enginePrivate->singletonInstance<QObject*>(type)) {
327 const bool includeEnums
328 = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums;
329 if (includeEnums && name->startsWithUpper()) {
331 int value = enumForSingleton(v4->typeLoader(), name, type, &ok);
333 return QV4::Value::fromInt32(value).asReturnedValue();
335 value = type.scopedEnumIndex(v4->typeLoader(), name, &ok);
337 return createEnumWrapper(v4, scope, type, value,
true);
339 value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok);
341 return createEnumWrapper(v4, scope, type, value,
false);
346 const ReturnedValue result = QV4::QObjectWrapper::getQmlProperty(
347 v4, context, w->d(), qobjectSingleton, name,
348 QV4::QObjectWrapper::AttachMethods, &ok);
354 }
else if (type.isQJSValueSingleton()) {
355 QJSValue scriptSingleton = enginePrivate->singletonInstance<QJSValue>(type);
356 if (!scriptSingleton.isUndefined()) {
358 QV4::ScopedObject o(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
368 if (name->startsWithUpper()) {
370 int value = type.enumValue(v4->typeLoader(), name, &ok);
372 return QV4::Value::fromInt32(value).asReturnedValue();
374 value = type.scopedEnumIndex(v4->typeLoader(), name, &ok);
376 return createEnumWrapper(v4, scope, type, value,
true);
378 value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok);
380 return createEnumWrapper(v4, scope, type, value,
false);
384 }
else if (w->d()->object) {
385 QObject *ao = qmlAttachedPropertiesObject(
386 object, type.attachedPropertiesFunction(v4->typeLoader()));
388 return QV4::QObjectWrapper::getQmlProperty(
389 v4, context, w->d(), ao, name, QV4::QObjectWrapper::AttachMethods,
400 }
else if (w->d()->kind() == Heap::QQmlTypeWrapper::Namespace) {
401 const QQmlTypeNameCache::Result r = w->d()->queryNamespace(name, v4);
403 if (r.type.isValid()) {
404 return create(scope.engine, object, r.type, w->d()->typeNameMode());
405 }
else if (r.scriptIndex != -1) {
406 QV4::ScopedObject scripts(scope, context->importedScripts());
407 return scripts->get(r.scriptIndex);
408 }
else if (r.importNamespace) {
409 return create(scope.engine, object, context->imports(), r.importNamespace);
412 return QV4::Encode::undefined();
419 Q_ASSERT(!
"Unreachable");
423 const ReturnedValue result = Object::virtualGet(m, id, receiver, &ok);
431bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id,
const Value &value, Value *receiver)
434 return Object::virtualPut(m, id, value, receiver);
437 Q_ASSERT(m->as<QQmlTypeWrapper>());
438 QQmlTypeWrapper *w =
static_cast<QQmlTypeWrapper *>(m);
440 if (scope.hasException())
443 ScopedString name(scope, id.asStringOrSymbol());
444 QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
446 QQmlType type = w->d()->type();
447 if (type.isValid() && !type.isSingleton() && w->d()->object) {
448 QObject *object = w->d()->object;
449 QObject *ao = qmlAttachedPropertiesObject(
450 object, type.attachedPropertiesFunction(scope.engine->typeLoader()));
452 return QV4::QObjectWrapper::setQmlProperty(
453 scope.engine, context, ao, name, QV4::QObjectWrapper::NoFlag, value);
455 }
else if (type.isSingleton()) {
456 QQmlEnginePrivate *e = QQmlEnginePrivate::get(scope.engine->qmlEngine());
457 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
458 if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type))
459 return QV4::QObjectWrapper::setQmlProperty(
460 scope.engine, context, qobjectSingleton, name,
461 QV4::QObjectWrapper::NoFlag, value);
464 QJSValue scriptSingleton = e->singletonInstance<QJSValue>(type);
465 if (!scriptSingleton.isUndefined()) {
466 QV4::ScopedObject apiprivate(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
468 QString error = QLatin1String(
"Cannot assign to read-only property \"") + name->toQString() + QLatin1Char(
'\"');
469 scope.engine->throwError(error);
472 return apiprivate->put(name, value);
519 const QV4::QQmlTypeWrapper *typeWrapper, QObject *wrapperObject)
521 QV4::ExecutionEngine *engine = typeWrapper->internalClass()->engine;
524 return engine->throwTypeError();
526 const QQmlType type = typeWrapper->d()->type();
527 QQmlMetaObject myQmlType;
528 if (type.isComposite()) {
529 if (!instanceHasCompilationUnit(wrapperObject))
530 return Encode(
false);
532 const CompiledData::CompilationUnit *cu
533 = engine->typeLoader()->getType(type.sourceUrl())->compilationUnit();
537 return Encode(
false);
539 myQmlType = QQmlMetaObject(cu->rootPropertyCache());
540 Q_ASSERT(!myQmlType.isNull());
541 }
else if (type.isInlineComponentType()) {
542 if (!instanceHasCompilationUnit(wrapperObject))
543 return Encode(
false);
545 auto baseUrl = type.sourceUrl();
546 baseUrl.setFragment(QString());
548 const CompiledData::CompilationUnit *cu
549 = engine->typeLoader()->getType(baseUrl)->compilationUnit();
552 return Encode(
false);
554 myQmlType = QQmlMetaObject(cu->propertyCaches.at(
555 cu->inlineComponentId(type.elementName())));
556 Q_ASSERT(!myQmlType.isNull());
558 myQmlType = QQmlMetaType::metaObjectForType(type.typeId());
559 if (myQmlType.isNull())
560 return Encode(
false);
563 const QMetaObject *theirType = wrapperObject->metaObject();
565 if (QQmlMetaObject::canConvert(theirType, myQmlType))
567 else if (type.isValueType())
568 return Encode::undefined();
570 return Encode(
false);
573ReturnedValue QQmlTypeWrapper::virtualInstanceOf(
const Object *typeObject,
const Value &var)
575 Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>());
576 const QV4::QQmlTypeWrapper *typeWrapper =
static_cast<
const QV4::QQmlTypeWrapper *>(typeObject);
578 if (
const QObjectWrapper *objectWrapper = var.as<QObjectWrapper>())
579 return instanceOfQObject(typeWrapper, objectWrapper->object());
581 if (
const QQmlTypeWrapper *varTypeWrapper = var.as<QQmlTypeWrapper>()) {
583 if (QObject *varObject = varTypeWrapper->object())
584 return instanceOfQObject(typeWrapper, varObject);
587 const QQmlType type = typeWrapper->d()->type();
590 if (!type.isValueType())
591 return Encode(
false);
593 const auto canCastValueType = [&]() ->
bool {
594 if (
const QQmlValueTypeWrapper *valueWrapper = var.as<QQmlValueTypeWrapper>()) {
595 return QQmlMetaObject::canConvert(
596 valueWrapper->metaObject(), type.metaObjectForValueType());
599 const QMetaType typeId = type.typeId();
600 if (
const VariantObject *variantObject = var.as<VariantObject>()) {
601 if (variantObject->d()->data().metaType() == typeId)
605 switch (typeId.id()) {
606 case QMetaType::Void:
607 return var.isUndefined();
608 case QMetaType::QVariant:
611 return var.isInteger();
612 case QMetaType::Double:
613 return var.isDouble();
614 case QMetaType::QString:
615 return var.isString();
616 case QMetaType::Bool:
617 return var.isBoolean();
618 case QMetaType::QUrl:
619 if (var.as<UrlObject>())
622 case QMetaType::QDate:
623 case QMetaType::QTime:
624 case QMetaType::QDateTime:
625 if (var.as<DateObject>())
636 return canCastValueType() ? Encode(
true) : Encode::undefined();
639ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(
const Object *object, ExecutionEngine *engine, Lookup *lookup)
642 PropertyKey id = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
644 return Object::virtualResolveLookupGetter(object, engine, lookup);
647 const QQmlTypeWrapper *This =
static_cast<
const QQmlTypeWrapper *>(object);
648 ScopedString name(scope, id.asStringOrSymbol());
649 QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
651 Scoped<QQmlTypeWrapper> w(scope,
static_cast<
const QQmlTypeWrapper *>(This));
652 QQmlType type = w->d()->type();
654 if (type.isValid()) {
656 if (type.isSingleton()) {
657 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
658 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
659 if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type)) {
660 const bool includeEnums
661 = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums;
662 if (!includeEnums || !name->startsWithUpper()) {
663 QQmlData *ddata = QQmlData::get(qobjectSingleton,
false);
664 if (ddata && ddata->propertyCache) {
665 const QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
667 ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
668 if (qualifiesForMethodLookup(property)) {
669 QV4::Heap::QObjectMethod *method =
nullptr;
670 setupQObjectMethodLookup(
671 lookup, ddata->propertyCache, property,
672 val->objectValue(), method);
673 lookup->call = QV4::Lookup::Call::GetterSingletonMethod;
676 lookup, ddata, property, val->objectValue(), This);
677 lookup->call = QV4::Lookup::Call::GetterSingletonProperty;
679 return lookup->getter(engine, *object);
692 if (name->startsWithUpper()) {
694 QQmlTypeLoader *typeLoader = engine->typeLoader();
695 int value = type.enumValue(typeLoader, name, &ok);
697 lookup->qmlEnumValueLookup.ic.set(engine, This->internalClass());
698 lookup->qmlEnumValueLookup.encodedEnumValue
699 = QV4::Value::fromInt32(value).asReturnedValue();
700 lookup->call = QV4::Lookup::Call::GetterEnumValue;
701 return lookup->getter(engine, *object);
704 value = type.scopedEnumIndex(typeLoader, name, &ok);
706 Scoped<QQmlEnumWrapper> enumWrapper(
707 scope, createEnumWrapper(engine, scope, type, value,
true));
708 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
709 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
710 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
711 lookup->call = QV4::Lookup::Call::GetterEnum;
712 return enumWrapper.asReturnedValue();
715 value = type.unscopedEnumIndex(typeLoader, name, &ok);
717 Scoped<QQmlEnumWrapper> enumWrapper(
718 scope, createEnumWrapper(engine, scope, type, value,
false));
719 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
720 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
721 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
722 lookup->call = QV4::Lookup::Call::GetterEnum;
723 return enumWrapper.asReturnedValue();
727 }
else if (w->d()->object) {
728 QObject *ao = qmlAttachedPropertiesObject(
729 w->d()->object, type.attachedPropertiesFunction(engine->typeLoader()));
732 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
733 return lookup->getter(engine, *object);
739
740 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
741 return lookup->getter(engine, *object);
773ReturnedValue QQmlTypeWrapper::lookupSingletonProperty(Lookup *l, ExecutionEngine *engine,
const Value &object)
775 const auto revertLookup = [l, engine, &object]() {
776 l->qobjectLookup.propertyCache->release();
777 l->qobjectLookup.propertyCache =
nullptr;
778 l->call = QV4::Lookup::Call::GetterGeneric;
779 return Lookup::getterGeneric(l, engine, object);
784 Heap::Object *o =
static_cast<Heap::Object *>(object.heapObject());
795 if (!o || o->internalClass != l->qobjectLookup.qmlTypeIc)
796 return revertLookup();
798 Heap::QQmlTypeWrapper *This =
static_cast<Heap::QQmlTypeWrapper *>(o);
800 QQmlType type = This->type();
802 return revertLookup();
804 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
805 return revertLookup();
807 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
808 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
809 Q_ASSERT(qobjectSingleton);
812 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
813 const QObjectWrapper::Flags flags = l->forCall
814 ? QObjectWrapper::AllowOverride
815 : (QObjectWrapper::AttachMethods | QObjectWrapper::AllowOverride);
816 return QObjectWrapper::lookupPropertyGetterImpl(l, engine, obj, flags, revertLookup);
819ReturnedValue QQmlTypeWrapper::lookupSingletonMethod(Lookup *l, ExecutionEngine *engine,
const Value &object)
821 const auto revertLookup = [l, engine, &object]() {
822 l->qobjectMethodLookup.propertyCache->release();
823 l->qobjectMethodLookup.propertyCache =
nullptr;
824 l->call = QV4::Lookup::Call::GetterGeneric;
825 return Lookup::getterGeneric(l, engine, object);
829 const QQmlTypeWrapper *This = object.as<QQmlTypeWrapper>();
831 return revertLookup();
833 QQmlType type = This->d()->type();
835 return revertLookup();
837 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
838 return revertLookup();
840 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
841 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
842 Q_ASSERT(qobjectSingleton);
845 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
846 return QObjectWrapper::lookupMethodGetterImpl(
847 l, engine, obj, l->forCall ? QObjectWrapper::NoFlag : QObjectWrapper::AttachMethods,
890ReturnedValue QQmlEnumWrapper::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
893 Q_ASSERT(m->as<QQmlEnumWrapper>());
895 return Object::virtualGet(m, id, receiver, hasProperty);
897 const QQmlEnumWrapper *resource =
static_cast<
const QQmlEnumWrapper *>(m);
898 QV4::ExecutionEngine *v4 = resource->engine();
899 QV4::Scope scope(v4);
900 ScopedString name(scope, id.asStringOrSymbol());
902 QQmlType type = resource->d()->type();
903 int index = resource->d()->enumIndex;
906 auto *typeLoader = v4->typeLoader();
907 int value = resource->d()->scoped ? type.scopedEnumValue(typeLoader, index, name, &ok)
908 : type.unscopedEnumValue(typeLoader, index, name, &ok);
912 return QV4::Value::fromInt32(value).asReturnedValue();
914 return Object::virtualGet(m, id, receiver, hasProperty);