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);
508 const QV4::QQmlTypeWrapper *typeWrapper, QObject *wrapperObject)
510 QV4::ExecutionEngine *engine = typeWrapper->internalClass()->engine;
513 return engine->throwTypeError();
515 const QQmlType type = typeWrapper->d()->type();
516 const QMetaType myTypeId = type.typeId();
517 QQmlMetaObject myQmlType;
518 if (!myTypeId.isValid()) {
522 QQmlData *theirDData = QQmlData::get(wrapperObject);
523 Q_ASSERT(theirDData);
524 if (!theirDData->compilationUnit)
525 return Encode(
false);
527 QQmlRefPointer<QQmlTypeData> td
528 = engine->typeLoader()->getType(typeWrapper->d()->type().sourceUrl());
529 if (CompiledData::CompilationUnit *cu = td->compilationUnit())
530 myQmlType = QQmlMetaType::metaObjectForType(cu->metaType());
532 return Encode(
false);
534 myQmlType = QQmlMetaType::metaObjectForType(myTypeId);
535 if (myQmlType.isNull())
536 return Encode(
false);
539 const QMetaObject *theirType = wrapperObject->metaObject();
541 if (QQmlMetaObject::canConvert(theirType, myQmlType))
543 else if (type.isValueType())
544 return Encode::undefined();
546 return Encode(
false);
549ReturnedValue QQmlTypeWrapper::virtualInstanceOf(
const Object *typeObject,
const Value &var)
551 Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>());
552 const QV4::QQmlTypeWrapper *typeWrapper =
static_cast<
const QV4::QQmlTypeWrapper *>(typeObject);
554 if (
const QObjectWrapper *objectWrapper = var.as<QObjectWrapper>())
555 return instanceOfQObject(typeWrapper, objectWrapper->object());
557 if (
const QQmlTypeWrapper *varTypeWrapper = var.as<QQmlTypeWrapper>()) {
559 if (QObject *varObject = varTypeWrapper->object())
560 return instanceOfQObject(typeWrapper, varObject);
563 const QQmlType type = typeWrapper->d()->type();
566 if (!type.isValueType())
567 return Encode(
false);
569 const auto canCastValueType = [&]() ->
bool {
570 if (
const QQmlValueTypeWrapper *valueWrapper = var.as<QQmlValueTypeWrapper>()) {
571 return QQmlMetaObject::canConvert(
572 valueWrapper->metaObject(), type.metaObjectForValueType());
575 const QMetaType typeId = type.typeId();
576 if (
const VariantObject *variantObject = var.as<VariantObject>()) {
577 if (variantObject->d()->data().metaType() == typeId)
581 switch (typeId.id()) {
582 case QMetaType::Void:
583 return var.isUndefined();
584 case QMetaType::QVariant:
587 return var.isInteger();
588 case QMetaType::Double:
589 return var.isDouble();
590 case QMetaType::QString:
591 return var.isString();
592 case QMetaType::Bool:
593 return var.isBoolean();
594 case QMetaType::QUrl:
595 if (var.as<UrlObject>())
598 case QMetaType::QDate:
599 case QMetaType::QTime:
600 case QMetaType::QDateTime:
601 if (var.as<DateObject>())
612 return canCastValueType() ? Encode(
true) : Encode::undefined();
615ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(
const Object *object, ExecutionEngine *engine, Lookup *lookup)
618 PropertyKey id = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
620 return Object::virtualResolveLookupGetter(object, engine, lookup);
623 const QQmlTypeWrapper *This =
static_cast<
const QQmlTypeWrapper *>(object);
624 ScopedString name(scope, id.asStringOrSymbol());
625 QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
627 Scoped<QQmlTypeWrapper> w(scope,
static_cast<
const QQmlTypeWrapper *>(This));
628 QQmlType type = w->d()->type();
630 if (type.isValid()) {
632 if (type.isSingleton()) {
633 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
634 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
635 if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type)) {
636 const bool includeEnums
637 = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums;
638 if (!includeEnums || !name->startsWithUpper()) {
639 QQmlData *ddata = QQmlData::get(qobjectSingleton,
false);
640 if (ddata && ddata->propertyCache) {
641 const QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
643 ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
644 if (qualifiesForMethodLookup(property)) {
645 QV4::Heap::QObjectMethod *method =
nullptr;
646 setupQObjectMethodLookup(
647 lookup, ddata->propertyCache, property,
648 val->objectValue(), method);
649 lookup->call = QV4::Lookup::Call::GetterSingletonMethod;
652 lookup, ddata, property, val->objectValue(), This);
653 lookup->call = QV4::Lookup::Call::GetterSingletonProperty;
655 return lookup->getter(engine, *object);
668 if (name->startsWithUpper()) {
670 QQmlTypeLoader *typeLoader = engine->typeLoader();
671 int value = type.enumValue(typeLoader, name, &ok);
673 lookup->qmlEnumValueLookup.ic.set(engine, This->internalClass());
674 lookup->qmlEnumValueLookup.encodedEnumValue
675 = QV4::Value::fromInt32(value).asReturnedValue();
676 lookup->call = QV4::Lookup::Call::GetterEnumValue;
677 return lookup->getter(engine, *object);
680 value = type.scopedEnumIndex(typeLoader, name, &ok);
682 Scoped<QQmlEnumWrapper> enumWrapper(
683 scope, createEnumWrapper(engine, scope, type, value,
true));
684 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
685 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
686 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
687 lookup->call = QV4::Lookup::Call::GetterEnum;
688 return enumWrapper.asReturnedValue();
691 value = type.unscopedEnumIndex(typeLoader, name, &ok);
693 Scoped<QQmlEnumWrapper> enumWrapper(
694 scope, createEnumWrapper(engine, scope, type, value,
false));
695 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
696 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
697 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
698 lookup->call = QV4::Lookup::Call::GetterEnum;
699 return enumWrapper.asReturnedValue();
703 }
else if (w->d()->object) {
704 QObject *ao = qmlAttachedPropertiesObject(
705 w->d()->object, type.attachedPropertiesFunction(engine->typeLoader()));
708 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
709 return lookup->getter(engine, *object);
715
716 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
717 return lookup->getter(engine, *object);
749ReturnedValue QQmlTypeWrapper::lookupSingletonProperty(Lookup *l, ExecutionEngine *engine,
const Value &object)
751 const auto revertLookup = [l, engine, &object]() {
752 l->qobjectLookup.propertyCache->release();
753 l->qobjectLookup.propertyCache =
nullptr;
754 l->call = QV4::Lookup::Call::GetterGeneric;
755 return Lookup::getterGeneric(l, engine, object);
760 Heap::Object *o =
static_cast<Heap::Object *>(object.heapObject());
771 if (!o || o->internalClass != l->qobjectLookup.qmlTypeIc)
772 return revertLookup();
774 Heap::QQmlTypeWrapper *This =
static_cast<Heap::QQmlTypeWrapper *>(o);
776 QQmlType type = This->type();
778 return revertLookup();
780 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
781 return revertLookup();
783 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
784 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
785 Q_ASSERT(qobjectSingleton);
788 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
789 const QObjectWrapper::Flags flags = l->forCall
790 ? QObjectWrapper::AllowOverride
791 : (QObjectWrapper::AttachMethods | QObjectWrapper::AllowOverride);
792 return QObjectWrapper::lookupPropertyGetterImpl(l, engine, obj, flags, revertLookup);
795ReturnedValue QQmlTypeWrapper::lookupSingletonMethod(Lookup *l, ExecutionEngine *engine,
const Value &object)
797 const auto revertLookup = [l, engine, &object]() {
798 l->qobjectMethodLookup.propertyCache->release();
799 l->qobjectMethodLookup.propertyCache =
nullptr;
800 l->call = QV4::Lookup::Call::GetterGeneric;
801 return Lookup::getterGeneric(l, engine, object);
805 const QQmlTypeWrapper *This = object.as<QQmlTypeWrapper>();
807 return revertLookup();
809 QQmlType type = This->d()->type();
811 return revertLookup();
813 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
814 return revertLookup();
816 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
817 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
818 Q_ASSERT(qobjectSingleton);
821 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
822 return QObjectWrapper::lookupMethodGetterImpl(
823 l, engine, obj, l->forCall ? QObjectWrapper::NoFlag : QObjectWrapper::AttachMethods,
866ReturnedValue QQmlEnumWrapper::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
869 Q_ASSERT(m->as<QQmlEnumWrapper>());
871 return Object::virtualGet(m, id, receiver, hasProperty);
873 const QQmlEnumWrapper *resource =
static_cast<
const QQmlEnumWrapper *>(m);
874 QV4::ExecutionEngine *v4 = resource->engine();
875 QV4::Scope scope(v4);
876 ScopedString name(scope, id.asStringOrSymbol());
878 QQmlType type = resource->d()->type();
879 int index = resource->d()->enumIndex;
882 auto *typeLoader = v4->typeLoader();
883 int value = resource->d()->scoped ? type.scopedEnumValue(typeLoader, index, name, &ok)
884 : type.unscopedEnumValue(typeLoader, index, name, &ok);
888 return QV4::Value::fromInt32(value).asReturnedValue();
890 return Object::virtualGet(m, id, receiver, hasProperty);