295ReturnedValue QQmlTypeWrapper::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
bool *hasProperty)
298 Q_ASSERT(m->as<QQmlTypeWrapper>());
301 return Object::virtualGet(m, id, receiver, hasProperty);
303 QV4::ExecutionEngine *v4 = m->engine();
304 QV4::Scope scope(v4);
305 ScopedString name(scope, id.asStringOrSymbol());
307 Scoped<QQmlTypeWrapper> w(scope,
static_cast<
const QQmlTypeWrapper *>(m));
312 QQmlRefPointer<QQmlContextData> context = v4->callingQmlContext();
314 QObject *object = w->d()->object;
315 QQmlType type = w->d()->type();
317 QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(v4->qmlEngine());
318 if (type.isValid()) {
321 if (type.isSingleton()) {
323 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
324 if (QObject *qobjectSingleton = enginePrivate->singletonInstance<QObject*>(type)) {
326 const bool includeEnums
327 = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums;
328 if (includeEnums && name->startsWithUpper()) {
330 int value = enumForSingleton(v4->typeLoader(), name, type, &ok);
332 return QV4::Value::fromInt32(value).asReturnedValue();
334 value = type.scopedEnumIndex(v4->typeLoader(), name, &ok);
336 return createEnumWrapper(v4, scope, type, value,
true);
338 value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok);
340 return createEnumWrapper(v4, scope, type, value,
false);
345 const ReturnedValue result = QV4::QObjectWrapper::getQmlProperty(
346 v4, context, w->d(), qobjectSingleton, name,
347 QV4::QObjectWrapper::AttachMethods, &ok);
353 }
else if (type.isQJSValueSingleton()) {
354 QJSValue scriptSingleton = enginePrivate->singletonInstance<QJSValue>(type);
355 if (!scriptSingleton.isUndefined()) {
357 QV4::ScopedObject o(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
367 if (name->startsWithUpper()) {
369 int value = type.enumValue(v4->typeLoader(), name, &ok);
371 return QV4::Value::fromInt32(value).asReturnedValue();
373 value = type.scopedEnumIndex(v4->typeLoader(), name, &ok);
375 return createEnumWrapper(v4, scope, type, value,
true);
377 value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok);
379 return createEnumWrapper(v4, scope, type, value,
false);
383 }
else if (w->d()->object) {
384 QObject *ao = qmlAttachedPropertiesObject(
385 object, type.attachedPropertiesFunction(v4->typeLoader()));
387 return QV4::QObjectWrapper::getQmlProperty(
388 v4, context, w->d(), ao, name, QV4::QObjectWrapper::AttachMethods,
399 }
else if (w->d()->kind() == Heap::QQmlTypeWrapper::Namespace) {
400 const QQmlTypeNameCache::Result r = w->d()->queryNamespace(name, v4);
402 if (r.type.isValid()) {
403 return create(scope.engine, object, r.type, w->d()->typeNameMode());
404 }
else if (r.scriptIndex != -1) {
405 QV4::ScopedObject scripts(scope, context->importedScripts());
406 return scripts->get(r.scriptIndex);
407 }
else if (r.importNamespace) {
408 return create(scope.engine, object, context->imports(), r.importNamespace);
411 return QV4::Encode::undefined();
418 Q_ASSERT(!
"Unreachable");
422 const ReturnedValue result = Object::virtualGet(m, id, receiver, &ok);
430bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id,
const Value &value, Value *receiver)
433 return Object::virtualPut(m, id, value, receiver);
436 Q_ASSERT(m->as<QQmlTypeWrapper>());
437 QQmlTypeWrapper *w =
static_cast<QQmlTypeWrapper *>(m);
439 if (scope.hasException())
442 ScopedString name(scope, id.asStringOrSymbol());
443 QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
445 QQmlType type = w->d()->type();
446 if (type.isValid() && !type.isSingleton() && w->d()->object) {
447 QObject *object = w->d()->object;
448 QObject *ao = qmlAttachedPropertiesObject(
449 object, type.attachedPropertiesFunction(scope.engine->typeLoader()));
451 return QV4::QObjectWrapper::setQmlProperty(
452 scope.engine, context, ao, name, QV4::QObjectWrapper::NoFlag, value);
454 }
else if (type.isSingleton()) {
455 QQmlEnginePrivate *e = QQmlEnginePrivate::get(scope.engine->qmlEngine());
456 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
457 if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type))
458 return QV4::QObjectWrapper::setQmlProperty(
459 scope.engine, context, qobjectSingleton, name,
460 QV4::QObjectWrapper::NoFlag, value);
463 QJSValue scriptSingleton = e->singletonInstance<QJSValue>(type);
464 if (!scriptSingleton.isUndefined()) {
465 QV4::ScopedObject apiprivate(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
467 QString error = QLatin1String(
"Cannot assign to read-only property \"") + name->toQString() + QLatin1Char(
'\"');
468 scope.engine->throwError(error);
471 return apiprivate->put(name, value);
507 const QV4::QQmlTypeWrapper *typeWrapper, QObject *wrapperObject)
509 QV4::ExecutionEngine *engine = typeWrapper->internalClass()->engine;
512 return engine->throwTypeError();
514 const QQmlType type = typeWrapper->d()->type();
515 const QMetaType myTypeId = type.typeId();
516 QQmlMetaObject myQmlType;
517 if (!myTypeId.isValid()) {
521 QQmlData *theirDData = QQmlData::get(wrapperObject);
522 Q_ASSERT(theirDData);
523 if (!theirDData->compilationUnit)
524 return Encode(
false);
526 QQmlRefPointer<QQmlTypeData> td
527 = engine->typeLoader()->getType(typeWrapper->d()->type().sourceUrl());
528 if (CompiledData::CompilationUnit *cu = td->compilationUnit())
529 myQmlType = QQmlMetaType::metaObjectForType(cu->metaType());
531 return Encode(
false);
533 myQmlType = QQmlMetaType::metaObjectForType(myTypeId);
534 if (myQmlType.isNull())
535 return Encode(
false);
538 const QMetaObject *theirType = wrapperObject->metaObject();
540 if (QQmlMetaObject::canConvert(theirType, myQmlType))
542 else if (type.isValueType())
543 return Encode::undefined();
545 return Encode(
false);
548ReturnedValue QQmlTypeWrapper::virtualInstanceOf(
const Object *typeObject,
const Value &var)
550 Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>());
551 const QV4::QQmlTypeWrapper *typeWrapper =
static_cast<
const QV4::QQmlTypeWrapper *>(typeObject);
553 if (
const QObjectWrapper *objectWrapper = var.as<QObjectWrapper>())
554 return instanceOfQObject(typeWrapper, objectWrapper->object());
556 if (
const QQmlTypeWrapper *varTypeWrapper = var.as<QQmlTypeWrapper>()) {
558 if (QObject *varObject = varTypeWrapper->object())
559 return instanceOfQObject(typeWrapper, varObject);
562 const QQmlType type = typeWrapper->d()->type();
565 if (!type.isValueType())
566 return Encode(
false);
568 const auto canCastValueType = [&]() ->
bool {
569 if (
const QQmlValueTypeWrapper *valueWrapper = var.as<QQmlValueTypeWrapper>()) {
570 return QQmlMetaObject::canConvert(
571 valueWrapper->metaObject(), type.metaObjectForValueType());
574 const QMetaType typeId = type.typeId();
575 if (
const VariantObject *variantObject = var.as<VariantObject>()) {
576 if (variantObject->d()->data().metaType() == typeId)
580 switch (typeId.id()) {
581 case QMetaType::Void:
582 return var.isUndefined();
583 case QMetaType::QVariant:
586 return var.isInteger();
587 case QMetaType::Double:
588 return var.isDouble();
589 case QMetaType::QString:
590 return var.isString();
591 case QMetaType::Bool:
592 return var.isBoolean();
593 case QMetaType::QUrl:
594 if (var.as<UrlObject>())
597 case QMetaType::QDate:
598 case QMetaType::QTime:
599 case QMetaType::QDateTime:
600 if (var.as<DateObject>())
611 return canCastValueType() ? Encode(
true) : Encode::undefined();
614ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(
const Object *object, ExecutionEngine *engine, Lookup *lookup)
617 PropertyKey id = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
619 return Object::virtualResolveLookupGetter(object, engine, lookup);
622 const QQmlTypeWrapper *This =
static_cast<
const QQmlTypeWrapper *>(object);
623 ScopedString name(scope, id.asStringOrSymbol());
624 QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
626 Scoped<QQmlTypeWrapper> w(scope,
static_cast<
const QQmlTypeWrapper *>(This));
627 QQmlType type = w->d()->type();
629 if (type.isValid()) {
631 if (type.isSingleton()) {
632 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
633 if (type.isQObjectSingleton() || type.isCompositeSingleton()) {
634 if (QObject *qobjectSingleton = e->singletonInstance<QObject*>(type)) {
635 const bool includeEnums
636 = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums;
637 if (!includeEnums || !name->startsWithUpper()) {
638 QQmlData *ddata = QQmlData::get(qobjectSingleton,
false);
639 if (ddata && ddata->propertyCache) {
640 const QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
642 ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
643 if (qualifiesForMethodLookup(property)) {
644 QV4::Heap::QObjectMethod *method =
nullptr;
645 setupQObjectMethodLookup(
646 lookup, ddata->propertyCache, property,
647 val->objectValue(), method);
648 lookup->call = QV4::Lookup::Call::GetterSingletonMethod;
651 lookup, ddata, property, val->objectValue(), This);
652 lookup->call = QV4::Lookup::Call::GetterSingletonProperty;
654 return lookup->getter(engine, *object);
667 if (name->startsWithUpper()) {
669 QQmlTypeLoader *typeLoader = engine->typeLoader();
670 int value = type.enumValue(typeLoader, name, &ok);
672 lookup->qmlEnumValueLookup.ic.set(engine, This->internalClass());
673 lookup->qmlEnumValueLookup.encodedEnumValue
674 = QV4::Value::fromInt32(value).asReturnedValue();
675 lookup->call = QV4::Lookup::Call::GetterEnumValue;
676 return lookup->getter(engine, *object);
679 value = type.scopedEnumIndex(typeLoader, name, &ok);
681 Scoped<QQmlEnumWrapper> enumWrapper(
682 scope, createEnumWrapper(engine, scope, type, value,
true));
683 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
684 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
685 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
686 lookup->call = QV4::Lookup::Call::GetterEnum;
687 return enumWrapper.asReturnedValue();
690 value = type.unscopedEnumIndex(typeLoader, name, &ok);
692 Scoped<QQmlEnumWrapper> enumWrapper(
693 scope, createEnumWrapper(engine, scope, type, value,
false));
694 auto *wrapper = enumWrapper->as<QQmlEnumWrapper>();
695 lookup->qmlEnumWrapperLookup.ic.set(engine, This->internalClass());
696 lookup->qmlEnumWrapperLookup.qmlEnumWrapper.set(engine, wrapper->heapObject());
697 lookup->call = QV4::Lookup::Call::GetterEnum;
698 return enumWrapper.asReturnedValue();
702 }
else if (w->d()->object) {
703 QObject *ao = qmlAttachedPropertiesObject(
704 w->d()->object, type.attachedPropertiesFunction(engine->typeLoader()));
707 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
708 return lookup->getter(engine, *object);
714
715 lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback;
716 return lookup->getter(engine, *object);
748ReturnedValue QQmlTypeWrapper::lookupSingletonProperty(Lookup *l, ExecutionEngine *engine,
const Value &object)
750 const auto revertLookup = [l, engine, &object]() {
751 l->qobjectLookup.propertyCache->release();
752 l->qobjectLookup.propertyCache =
nullptr;
753 l->call = QV4::Lookup::Call::GetterGeneric;
754 return Lookup::getterGeneric(l, engine, object);
759 Heap::Object *o =
static_cast<Heap::Object *>(object.heapObject());
770 if (!o || o->internalClass != l->qobjectLookup.qmlTypeIc)
771 return revertLookup();
773 Heap::QQmlTypeWrapper *This =
static_cast<Heap::QQmlTypeWrapper *>(o);
775 QQmlType type = This->type();
777 return revertLookup();
779 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
780 return revertLookup();
782 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
783 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
784 Q_ASSERT(qobjectSingleton);
787 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
788 const QObjectWrapper::Flags flags = l->forCall
789 ? QObjectWrapper::AllowOverride
790 : (QObjectWrapper::AttachMethods | QObjectWrapper::AllowOverride);
791 return QObjectWrapper::lookupPropertyGetterImpl(l, engine, obj, flags, revertLookup);
794ReturnedValue QQmlTypeWrapper::lookupSingletonMethod(Lookup *l, ExecutionEngine *engine,
const Value &object)
796 const auto revertLookup = [l, engine, &object]() {
797 l->qobjectMethodLookup.propertyCache->release();
798 l->qobjectMethodLookup.propertyCache =
nullptr;
799 l->call = QV4::Lookup::Call::GetterGeneric;
800 return Lookup::getterGeneric(l, engine, object);
804 const QQmlTypeWrapper *This = object.as<QQmlTypeWrapper>();
806 return revertLookup();
808 QQmlType type = This->d()->type();
810 return revertLookup();
812 if (!type.isQObjectSingleton() && !type.isCompositeSingleton())
813 return revertLookup();
815 QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine->qmlEngine());
816 QObject *qobjectSingleton = e->singletonInstance<QObject *>(type);
817 Q_ASSERT(qobjectSingleton);
820 ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, qobjectSingleton));
821 return QObjectWrapper::lookupMethodGetterImpl(
822 l, engine, obj, l->forCall ? QObjectWrapper::NoFlag : QObjectWrapper::AttachMethods,
865ReturnedValue QQmlEnumWrapper::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
868 Q_ASSERT(m->as<QQmlEnumWrapper>());
870 return Object::virtualGet(m, id, receiver, hasProperty);
872 const QQmlEnumWrapper *resource =
static_cast<
const QQmlEnumWrapper *>(m);
873 QV4::ExecutionEngine *v4 = resource->engine();
874 QV4::Scope scope(v4);
875 ScopedString name(scope, id.asStringOrSymbol());
877 QQmlType type = resource->d()->type();
878 int index = resource->d()->enumIndex;
881 auto *typeLoader = v4->typeLoader();
882 int value = resource->d()->scoped ? type.scopedEnumValue(typeLoader, index, name, &ok)
883 : type.unscopedEnumValue(typeLoader, index, name, &ok);
887 return QV4::Value::fromInt32(value).asReturnedValue();
889 return Object::virtualGet(m, id, receiver, hasProperty);