void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier &, const QScriptValue &value) { QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj); QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value); if (o->objectType == QDeclarativeValueTypeObject::Reference) { QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj); ref->type->read(ref->object, ref->property); QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); QDeclarativeBinding *newBinding = 0; if (value.isFunction() && !value.isRegExp()) { QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(engine)->getContext(context()); QDeclarativePropertyCache::Data cacheData; cacheData.flags = QDeclarativePropertyCache::Data::IsWritable; cacheData.propType = ref->object->metaObject()->property(ref->property).userType(); cacheData.coreIndex = ref->property; QDeclarativePropertyCache::ValueTypeData valueTypeData; valueTypeData.valueTypeCoreIdx = m_lastIndex; valueTypeData.valueTypePropType = p.userType(); newBinding = new QDeclarativeBinding(value, ref->object, ctxt); QScriptContextInfo ctxtInfo(context()); newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt); newBinding->setTarget(prop); if (newBinding->expression().contains(QLatin1String("this"))) newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); } QDeclarativeAbstractBinding *delBinding = QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, newBinding); if (delBinding) delBinding->destroy(); if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); p.write(ref->type, v); ref->type->write(ref->object, ref->property, 0); } else { QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj); copy->type->setValue(copy->value); QMetaProperty p = copy->type->metaObject()->property(m_lastIndex); p.write(copy->type, v); copy->value = copy->type->value(); } }
void ObjectNodeInstance::setPropertyBinding(const QString &name, const QString &expression) { QDeclarativeProperty property(object(), name, context()); if (!property.isValid()) return; if (property.isProperty()) { QDeclarativeBinding *binding = new QDeclarativeBinding(expression, object(), context()); binding->setTarget(property); binding->setNotifyOnValueChanged(true); QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding); if (oldBinding) oldBinding->destroy(); binding->update(); } else { qWarning() << "Cannot set binding for property" << name << ": property is unknown for type" << (modelNode().isValid() ? modelNode().type() : "unknown"); } }
QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, int start, int count, const QBitField &bindingSkipList) { Q_ASSERT(comp); Q_ASSERT(ctxt); const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types; const QList<QString> &primitives = comp->primitives; const QList<QByteArray> &datas = comp->datas; const QList<QDeclarativeCompiledData::CustomTypeData> &customTypeData = comp->customTypeData; const QList<int> &intData = comp->intData; const QList<float> &floatData = comp->floatData; const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches; const QList<QDeclarativeParser::Object::ScriptBlock> &scripts = comp->scripts; const QList<QUrl> &urls = comp->urls; QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues; QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus; QDeclarativeVMEStack<ListInstance> qliststack; vmeErrors.clear(); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); int status = -1; //for dbus QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite; for (int ii = start; !isError() && ii < (start + count); ++ii) { const QDeclarativeInstruction &instr = comp->bytecode.at(ii); switch(instr.type) { case QDeclarativeInstruction::Init: { if (instr.init.bindingsSize) bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.init.bindingsSize); if (instr.init.parserStatusSize) parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.init.parserStatusSize); if (instr.init.contextCache != -1) ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); if (instr.init.compiledBinding != -1) ctxt->optimizedBindings = new QDeclarativeCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt, comp); } break; case QDeclarativeInstruction::CreateObject: { QBitField bindings; if (instr.create.bindingBits != -1) { const QByteArray &bits = datas.at(instr.create.bindingBits); bindings = QBitField((const quint32*)bits.constData(), bits.size() * 8); } if (stack.isEmpty()) bindings = bindings.united(bindingSkipList); QObject *o = types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors); if (!o) { VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className))); } QDeclarativeData *ddata = QDeclarativeData::get(o); Q_ASSERT(ddata); if (stack.isEmpty()) { if (ddata->context) { Q_ASSERT(ddata->context != ctxt); Q_ASSERT(ddata->outerContext); Q_ASSERT(ddata->outerContext != ctxt); QDeclarativeContextData *c = ddata->context; while (c->linkedContext) c = c->linkedContext; c->linkedContext = ctxt; } else { ctxt->addObject(o); } ddata->ownContext = true; } else if (!ddata->context) { ctxt->addObject(o); } ddata->setImplicitDestructible(); ddata->outerContext = ctxt; ddata->lineNumber = instr.line; ddata->columnNumber = instr.create.column; if (instr.create.data != -1) { QDeclarativeCustomParser *customParser = types.at(instr.create.type).type->customParser(); customParser->setCustomData(o, datas.at(instr.create.data)); } if (!stack.isEmpty()) { QObject *parent = stack.top(); if (o->isWidgetType()) { QWidget *widget = static_cast<QWidget*>(o); if (parent->isWidgetType()) { QWidget *parentWidget = static_cast<QWidget*>(parent); widget->setParent(parentWidget); } else { // TODO: parent might be a layout } } else { QDeclarative_setParent_noEvent(o, parent); } } stack.push(o); } break; case QDeclarativeInstruction::CreateSimpleObject: { QObject *o = (QObject *)operator new(instr.createSimple.typeSize + sizeof(QDeclarativeData)); ::memset(static_cast<void *>(o), 0, instr.createSimple.typeSize + sizeof(QDeclarativeData)); instr.createSimple.create(o); QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type); if (!ddata->propertyCache && ref.typePropertyCache) { ddata->propertyCache = ref.typePropertyCache; ddata->propertyCache->addref(); } ddata->lineNumber = instr.line; ddata->columnNumber = instr.createSimple.column; QObjectPrivate::get(o)->declarativeData = ddata; ddata->context = ddata->outerContext = ctxt; ddata->nextContextObject = ctxt->contextObjects; if (ddata->nextContextObject) ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; ddata->prevContextObject = &ctxt->contextObjects; ctxt->contextObjects = ddata; QObject *parent = stack.top(); QDeclarative_setParent_noEvent(o, parent); stack.push(o); } break; case QDeclarativeInstruction::SetId: { QObject *target = stack.top(); ctxt->setIdProperty(instr.setId.index, target); } break; case QDeclarativeInstruction::SetDefault: { ctxt->contextObject = stack.top(); } break; case QDeclarativeInstruction::CreateComponent: { QDeclarativeComponent *qcomp = new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top()); QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true); Q_ASSERT(ddata); ctxt->addObject(qcomp); if (stack.isEmpty()) ddata->ownContext = true; ddata->setImplicitDestructible(); ddata->outerContext = ctxt; ddata->lineNumber = instr.line; ddata->columnNumber = instr.create.column; QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt; stack.push(qcomp); ii += instr.createComponent.count; } break; case QDeclarativeInstruction::StoreMetaObject: { QObject *target = stack.top(); QMetaObject mo; const QByteArray &metadata = datas.at(instr.storeMeta.data); QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata); const QDeclarativeVMEMetaData *data = (const QDeclarativeVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(); (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp); if (instr.storeMeta.propertyCache != -1) { QDeclarativeData *ddata = QDeclarativeData::get(target, true); if (ddata->propertyCache) ddata->propertyCache->release(); ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); ddata->propertyCache->addref(); } } break; case QDeclarativeInstruction::StoreVariant: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeString.propertyIndex); // XXX - can be more efficient QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.storeString.value)); void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } break; case QDeclarativeInstruction::StoreVariantInteger: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeString.propertyIndex); QVariant v(instr.storeInteger.value); void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } break; case QDeclarativeInstruction::StoreVariantDouble: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeString.propertyIndex); QVariant v(instr.storeDouble.value); void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } break; case QDeclarativeInstruction::StoreVariantBool: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeString.propertyIndex); QVariant v(instr.storeBool.value); void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } break; case QDeclarativeInstruction::StoreString: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeString.propertyIndex); void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } break; case QDeclarativeInstruction::StoreUrl: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeUrl.propertyIndex); void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeUrl.propertyIndex, a); } break; case QDeclarativeInstruction::StoreFloat: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeFloat.propertyIndex); float f = instr.storeFloat.value; void *a[] = { &f, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeFloat.propertyIndex, a); } break; case QDeclarativeInstruction::StoreDouble: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeDouble.propertyIndex); double d = instr.storeDouble.value; void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDouble.propertyIndex, a); } break; case QDeclarativeInstruction::StoreBool: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeBool.propertyIndex); void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeBool.propertyIndex, a); } break; case QDeclarativeInstruction::StoreInteger: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeInteger.propertyIndex); void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeInteger.propertyIndex, a); } break; case QDeclarativeInstruction::StoreColor: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeColor.propertyIndex); QColor c = QColor::fromRgba(instr.storeColor.value); void *a[] = { &c, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeColor.propertyIndex, a); } break; case QDeclarativeInstruction::StoreDate: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeDate.propertyIndex); QDate d = QDate::fromJulianDay(instr.storeDate.value); void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDate.propertyIndex, a); } break; case QDeclarativeInstruction::StoreTime: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeTime.propertyIndex); QTime t; t.setHMS(intData.at(instr.storeTime.valueIndex), intData.at(instr.storeTime.valueIndex+1), intData.at(instr.storeTime.valueIndex+2), intData.at(instr.storeTime.valueIndex+3)); void *a[] = { &t, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeTime.propertyIndex, a); } break; case QDeclarativeInstruction::StoreDateTime: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeDateTime.propertyIndex); QTime t; t.setHMS(intData.at(instr.storeDateTime.valueIndex+1), intData.at(instr.storeDateTime.valueIndex+2), intData.at(instr.storeDateTime.valueIndex+3), intData.at(instr.storeDateTime.valueIndex+4)); QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t); void *a[] = { &dt, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDateTime.propertyIndex, a); } break; case QDeclarativeInstruction::StorePoint: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toPoint(); void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } break; case QDeclarativeInstruction::StorePointF: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); QPointF p(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } break; case QDeclarativeInstruction::StoreSize: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toSize(); void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } break; case QDeclarativeInstruction::StoreSizeF: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex); QSizeF s(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); void *a[] = { &s, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } break; case QDeclarativeInstruction::StoreRect: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeRect.propertyIndex); QRect r = QRectF(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)).toRect(); void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } break; case QDeclarativeInstruction::StoreRectF: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeRect.propertyIndex); QRectF r(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)); void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } break; case QDeclarativeInstruction::StoreVector3D: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeVector3D.propertyIndex); QVector3D p(floatData.at(instr.storeVector3D.valueIndex), floatData.at(instr.storeVector3D.valueIndex+1), floatData.at(instr.storeVector3D.valueIndex+2)); void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeVector3D.propertyIndex, a); } break; case QDeclarativeInstruction::StoreObject: { QObject *assignObj = stack.pop(); QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeObject.propertyIndex); void *a[] = { (void *)&assignObj, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } break; case QDeclarativeInstruction::AssignCustomType: { QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.assignCustomType.propertyIndex); QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex); const QString &primitive = primitives.at(data.index); QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(data.type); QVariant v = (*converter)(primitive); QMetaProperty prop = target->metaObject()->property(instr.assignCustomType.propertyIndex); if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name()))); void *a[] = { (void *)v.data(), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.assignCustomType.propertyIndex, a); } break; case QDeclarativeInstruction::AssignSignalObject: { // XXX optimize QObject *assign = stack.pop(); QObject *target = stack.top(); int sigIdx = instr.assignSignalObject.signal; const QByteArray &pr = datas.at(sigIdx); QDeclarativeProperty prop(target, QString::fromUtf8(pr)); if (prop.type() & QDeclarativeProperty::SignalProperty) { QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign); if (method.signature() == 0) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className()))); if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature())) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature()))); QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex()); } else { VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr))); } } break; case QDeclarativeInstruction::StoreSignal: { QObject *target = stack.top(); QObject *context = stack.at(stack.count() - 1 - instr.storeSignal.context); QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex); QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target); QDeclarativeExpression *expr = new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value)); expr->setSourceLocation(comp->name, instr.line); static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.storeSignal.name); bs->setExpression(expr); } break; case QDeclarativeInstruction::StoreImportedScript: { ctxt->addImportedScript(scripts.at(instr.storeScript.value)); } break; case QDeclarativeInstruction::StoreScriptString: { QObject *target = stack.top(); QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope); QDeclarativeScriptString ss; ss.setContext(ctxt->asQDeclarativeContext()); ss.setScopeObject(scope); ss.setScript(primitives.at(instr.storeScriptString.value)); void *a[] = { &ss, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeScriptString.propertyIndex, a); } break; case QDeclarativeInstruction::BeginObject: { QObject *target = stack.top(); QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue); parserStatus.append(status); status->d = &parserStatus.values[parserStatus.count - 1]; status->classBegin(); } break; case QDeclarativeInstruction::StoreBinding: case QDeclarativeInstruction::StoreBindingOnAlias: { QObject *target = stack.at(stack.count() - 1 - instr.assignBinding.owner); QObject *context = stack.at(stack.count() - 1 - instr.assignBinding.context); QDeclarativeProperty mp = QDeclarativePropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt); int coreIndex = mp.index(); if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex)) break; QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->setTarget(mp); if (instr.type == QDeclarativeInstruction::StoreBindingOnAlias) { QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind); if (old) { old->destroy(); } } else { bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp)); } } break; case QDeclarativeInstruction::StoreCompiledBinding: { QObject *target = stack.at(stack.count() - 1 - instr.assignBinding.owner); QObject *scope = stack.at(stack.count() - 1 - instr.assignBinding.context); int property = instr.assignBinding.property; if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF)) break; QDeclarativeAbstractBinding *binding = ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property); bindValues.append(binding); binding->m_mePtr = &bindValues.values[bindValues.count - 1]; binding->addToObject(target, property); } break; case QDeclarativeInstruction::StoreValueSource: { QObject *obj = stack.pop(); QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue); QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner); QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt); obj->setParent(target); vs->setTarget(prop); } break; case QDeclarativeInstruction::StoreValueInterceptor: { QObject *obj = stack.pop(); QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue); QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner); QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt); obj->setParent(target); vi->setTarget(prop); QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject()); mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi); } break; case QDeclarativeInstruction::StoreObjectQList: { QObject *assign = stack.pop(); const ListInstance &list = qliststack.top(); list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign); } break; case QDeclarativeInstruction::AssignObjectList: { // This is only used for assigning interfaces QObject *assign = stack.pop(); const ListInstance &list = qliststack.top(); int type = list.type; void *ptr = 0; const char *iid = QDeclarativeMetaType::interfaceIId(type); if (iid) ptr = assign->qt_metacast(iid); if (!ptr) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list")); list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr); } break; case QDeclarativeInstruction::StoreVariantObject: { QObject *assign = stack.pop(); QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeObject.propertyIndex); QVariant v = QVariant::fromValue(assign); void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } break; case QDeclarativeInstruction::StoreInterface: { QObject *assign = stack.pop(); QObject *target = stack.top(); CLEAN_PROPERTY(target, instr.storeObject.propertyIndex); int coreIdx = instr.storeObject.propertyIndex; QMetaProperty prop = target->metaObject()->property(coreIdx); int t = prop.userType(); const char *iid = QDeclarativeMetaType::interfaceIId(t); bool ok = false; if (iid) { void *ptr = assign->qt_metacast(iid); if (ptr) { void *a[] = { &ptr, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIdx, a); ok = true; } } if (!ok) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property")); } break; case QDeclarativeInstruction::FetchAttached: { QObject *target = stack.top(); QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target); if (!qmlObject) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object")); stack.push(qmlObject); } break; case QDeclarativeInstruction::FetchQList: { QObject *target = stack.top(); qliststack.push(ListInstance(instr.fetchQmlList.type)); void *a[1]; a[0] = (void *)&(qliststack.top().qListProperty); QMetaObject::metacall(target, QMetaObject::ReadProperty, instr.fetchQmlList.property, a); } break; case QDeclarativeInstruction::FetchObject: { QObject *target = stack.top(); QObject *obj = 0; // NOTE: This assumes a cast to QObject does not alter the // object pointer void *a[1]; a[0] = &obj; QMetaObject::metacall(target, QMetaObject::ReadProperty, instr.fetch.property, a); if (!obj) VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name()))); stack.push(obj); } break; case QDeclarativeInstruction::PopQList: { qliststack.pop(); } break; case QDeclarativeInstruction::Defer: { if (instr.defer.deferCount) { QObject *target = stack.top(); QDeclarativeData *data = QDeclarativeData::get(target, true); comp->addref(); data->deferredComponent = comp; data->deferredIdx = ii; ii += instr.defer.deferCount; } } break; case QDeclarativeInstruction::PopFetchedObject: { stack.pop(); } break; case QDeclarativeInstruction::FetchValueType: { QObject *target = stack.top(); if (instr.fetchValue.bindingSkipList != 0) { // Possibly need to clear bindings QDeclarativeData *targetData = QDeclarativeData::get(target); if (targetData) { QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::binding(target, instr.fetchValue.property, -1); if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) { QDeclarativePropertyPrivate::setBinding(target, instr.fetchValue.property, -1, 0); binding->destroy(); } else if (binding) { QDeclarativeValueTypeProxyBinding *proxy = static_cast<QDeclarativeValueTypeProxyBinding *>(binding); proxy->removeBindings(instr.fetchValue.bindingSkipList); } } } QDeclarativeValueType *valueHandler = ep->valueTypes[instr.fetchValue.type]; valueHandler->read(target, instr.fetchValue.property); stack.push(valueHandler); } break; case QDeclarativeInstruction::PopValueType: { QDeclarativeValueType *valueHandler = static_cast<QDeclarativeValueType *>(stack.pop()); QObject *target = stack.top(); valueHandler->write(target, instr.fetchValue.property, QDeclarativePropertyPrivate::BypassInterceptor); } break; default: qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", instr.type); break; } } if (isError()) { if (!stack.isEmpty()) { delete stack.at(0); // ### What about failures in deferred creation? } else { ctxt->destroy(); } QDeclarativeEnginePrivate::clear(bindValues); QDeclarativeEnginePrivate::clear(parserStatus); return 0; } if (bindValues.count) ep->bindValues << bindValues; else if (bindValues.values) bindValues.clear(); if (parserStatus.count) ep->parserStatus << parserStatus; else if (parserStatus.values) parserStatus.clear(); Q_ASSERT(stack.count() == 1); return stack.top(); }
void QDeclarativeObjectScriptClass::setProperty(QObject *obj, const Identifier &name, const QScriptValue &value, QScriptContext *context, QDeclarativeContextData *evalContext) { Q_UNUSED(name); Q_ASSERT(obj); Q_ASSERT(lastData); Q_ASSERT(context); if (!lastData->isValid()) { QString error = QLatin1String("Cannot assign to non-existent property \"") + toString(name) + QLatin1Char('\"'); context->throwError(error); return; } if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) && !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) { QString error = QLatin1String("Cannot assign to read-only property \"") + toString(name) + QLatin1Char('\"'); context->throwError(error); return; } QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); if (!evalContext) { // Global object, QScriptContext activation object, QDeclarativeContext object QScriptValue scopeNode = scopeChainValue(context, -3); if (scopeNode.isValid()) { Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass); evalContext = enginePriv->contextClass->contextFromValue(scopeNode); } } QDeclarativeBinding *newBinding = 0; if (value.isFunction() && !value.isRegExp()) { QScriptContextInfo ctxtInfo(context); QDeclarativePropertyCache::ValueTypeData valueTypeData; newBinding = new QDeclarativeBinding(value, obj, evalContext); newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext)); if (newBinding->expression().contains(QLatin1String("this"))) newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); } QDeclarativeAbstractBinding *delBinding = QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding); if (delBinding) delBinding->destroy(); if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) { QObject *o = 0; int status = -1; int flags = 0; void *argv[] = { &o, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv); } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) { void *a[] = { 0 }; QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a); } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) { QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext); } else if (value.isUndefined()) { QString error = QLatin1String("Cannot assign [undefined] to ") + QLatin1String(QMetaType::typeName(lastData->propType)); context->throwError(error); } else if (value.isFunction() && !value.isRegExp()) { // this is handled by the binding creation above } else { //### expand optimization for other known types if (lastData->propType == QMetaType::Int && value.isNumber()) { int rawValue = qRoundDouble(value.toNumber()); int status = -1; int flags = 0; void *a[] = { (void *)&rawValue, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); return; } else if (lastData->propType == QMetaType::QReal && value.isNumber()) { qreal rawValue = qreal(value.toNumber()); int status = -1; int flags = 0; void *a[] = { (void *)&rawValue, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); return; } else if (lastData->propType == QMetaType::QString && value.isString()) { const QString &rawValue = value.toString(); int status = -1; int flags = 0; void *a[] = { (void *)&rawValue, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); return; } QVariant v; if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >()); else v = enginePriv->scriptValueToVariant(value, lastData->propType); if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) { const char *valueType = 0; if (v.userType() == QVariant::Invalid) valueType = "null"; else valueType = QMetaType::typeName(v.userType()); QString error = QLatin1String("Cannot assign ") + QLatin1String(valueType) + QLatin1String(" to ") + QLatin1String(QMetaType::typeName(lastData->propType)); context->throwError(error); } } }