bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec, JSC::JSValue value, JSC::JSValue proto) { if (!scriptClass()->supportsExtension(QScriptClass::HasInstance)) return QScriptObjectDelegate::hasInstance(object, exec, value, proto); QScriptValueList args; QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(eng_p, exec); args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value); QVariant result = scriptClass()->extension(QScriptClass::HasInstance, QVariant::fromValue(args)); return result.toBool(); }
QScriptValue QDeclarativeObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine) { QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine); QScriptValue that = context->thisObject(); if (scriptClass(that) != p->objectClass) return engine->undefinedValue(); ObjectData *data = (ObjectData *)p->objectClass->object(that); if (!data->object) return engine->undefinedValue(); QDeclarativeData *ddata = QDeclarativeData::get(data->object, false); if (!ddata || ddata->indestructible) return engine->currentContext()->throwError(QLatin1String("Invalid attempt to destroy() an indestructible object")); QObject *obj = data->object; int delay = 0; if (context->argumentCount() > 0) delay = context->argument(0).toInt32(); if (delay > 0) QTimer::singleShot(delay, obj, SLOT(deleteLater())); else obj->deleteLater(); return engine->undefinedValue(); }
QDeclarativeContextData *QDeclarativeContextScriptClass::contextFromValue(const QScriptValue &v) { if (scriptClass(v) != this) return 0; ContextData *data = (ContextData *)object(v); return data->getContext(engine); }
int QDeclarativeObjectScriptClass::objectType(const QScriptValue &value) const { if (scriptClass(value) != this) return QVariant::Invalid; Object *o = object(value); return ((ObjectData*)(o))->type; }
QScriptClass::QueryFlags QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext, QueryHints hints) { Q_UNUSED(flags); lastData = 0; lastTNData = 0; if (name == m_destroyId.identifier || name == m_toStringId.identifier) return QScriptClass::HandlesReadAccess; if (!obj) return 0; QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine); lastData = QDeclarativePropertyCache::property(engine, obj, name, local); if ((hints & ImplicitObject) && lastData && lastData->revision != 0) { QDeclarativeData *ddata = QDeclarativeData::get(obj); if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData)) return 0; } if (lastData) return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; if (!(hints & SkipAttachedProperties)) { if (!evalContext && context()) { // Global object, QScriptContext activation object, QDeclarativeContext object QScriptValue scopeNode = scopeChainValue(context(), -3); if (scopeNode.isValid()) { Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass); evalContext = enginePrivate->contextClass->contextFromValue(scopeNode); } } if (evalContext && evalContext->imports) { QDeclarativeTypeNameCache::Data *data = evalContext->imports->data(name); if (data) { lastTNData = data; return QScriptClass::HandlesReadAccess; } } } if (!(hints & ImplicitObject)) { local.coreIndex = -1; lastData = &local; return QScriptClass::HandlesWriteAccess; } return 0; }
QUrl QDeclarativeContextScriptClass::urlFromValue(const QScriptValue &v) { if (scriptClass(v) != this) return QUrl(); ContextData *data = (ContextData *)object(v); if (data->isUrlContext) { return QUrl(static_cast<UrlContextData *>(data)->url); } else { return QUrl(); } }
QScriptValue QDeclarativeObjectMethodScriptClass::disconnect(QScriptContext *context, QScriptEngine *engine) { QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine); QScriptValue that = context->thisObject(); if (&p->objectClass->methods != scriptClass(that)) return engine->undefinedValue(); MethodData *data = (MethodData *)object(that); if (!data->object || context->argumentCount() == 0) return engine->undefinedValue(); QByteArray signal("2"); signal.append(data->object->metaObject()->method(data->data.coreIndex).signature()); if (context->argumentCount() == 1) { qScriptDisconnect(data->object, signal.constData(), QScriptValue(), context->argument(0)); } else { qScriptDisconnect(data->object, signal.constData(), context->argument(0), context->argument(1)); } return engine->undefinedValue(); }
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); } } QDeclarativeAbstractBinding *delBinding = QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, 0); 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 { 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); } } }
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); } } }
QVariant QDeclarativeValueTypeScriptClass::toVariant(const QScriptValue &value) { Q_ASSERT(scriptClass(value) == this); return toVariant(object(value), 0); }