void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine, QDeclarativeError &error) { if (scriptEngine->hasUncaughtException() && scriptEngine->uncaughtException().isError()) { QString fileName; int lineNumber = scriptEngine->uncaughtExceptionLineNumber(); QScriptValue exception = scriptEngine->uncaughtException(); QLatin1String fileNameProp("fileName"); if (!exception.property(fileNameProp).toString().isEmpty()){ fileName = exception.property(fileNameProp).toString(); } else { fileName = QLatin1String("<Unknown File>"); } error.setUrl(QUrl(fileName)); error.setLine(lineNumber); error.setColumn(-1); error.setDescription(exception.toString()); } else { error = QDeclarativeError(); } }
QScriptValue QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool *isUndefined) { Q_ASSERT(context() && context()->engine); DeleteWatcher watcher(this); QDeclarativeEngine *engine = context()->engine; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); QDeclarativeContextData *oldSharedContext = 0; QObject *oldSharedScope = 0; QObject *oldOverride = 0; bool isShared = (expressionFunctionMode == SharedContext); if (isShared) { oldSharedContext = ep->sharedContext; oldSharedScope = ep->sharedScope; ep->sharedContext = context(); ep->sharedScope = scopeObject; } else { oldOverride = ep->contextClass->setOverrideObject(expressionContext, secondaryScope); } QScriptValue thisObject; if (evalFlags & RequiresThisObject) thisObject = ep->objectClass->newQObject(scopeObject); QScriptValue svalue = expressionFunction.call(thisObject); // This could cause this c++ object to be deleted if (isShared) { ep->sharedContext = oldSharedContext; ep->sharedScope = oldSharedScope; } else if (!watcher.wasDeleted()) { ep->contextClass->setOverrideObject(expressionContext, oldOverride); } if (isUndefined) *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException(); // Handle exception if (scriptEngine->hasUncaughtException()) { if (!watcher.wasDeleted()) QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); scriptEngine->clearExceptions(); return QScriptValue(); } else { if (!watcher.wasDeleted()) error = QDeclarativeError(); return svalue; } }
/*! Clear any expression errors. Calls to hasError() following this will return false. \sa hasError(), error() */ void QDeclarativeExpression::clearError() { Q_D(QDeclarativeExpression); d->data->error = QDeclarativeError(); }
QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined) { QDeclarativeExpressionData *data = this->data; QDeclarativeEngine *engine = data->context()->engine; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); if (!data->expressionFunctionValid) { QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); data->expressionContext = ep->contextClass->newContext(data->context(), data->me); scriptContext->pushScope(data->expressionContext); scriptContext->pushScope(ep->globalClass->globalObject()); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, data->url, data->line); } else { QDeclarativeRewrite::RewriteBinding rewriteBinding; bool ok = true; const QString code = rewriteBinding(data->expression, &ok); if (!ok) { scriptEngine->popContext(); return QVariant(); } data->expressionFunction = scriptEngine->evaluate(code, data->url, data->line); } scriptEngine->popContext(); data->expressionFunctionValid = true; } QDeclarativeContextData *oldSharedContext = 0; QObject *oldSharedScope = 0; QObject *oldOverride = 0; if (data->isShared) { oldSharedContext = ep->sharedContext; oldSharedScope = ep->sharedScope; ep->sharedContext = data->context(); ep->sharedScope = data->me; } else { oldOverride = ep->contextClass->setOverrideObject(data->expressionContext, secondaryScope); } QScriptValue svalue = data->expressionFunction.call(); if (data->isShared) { ep->sharedContext = oldSharedContext; ep->sharedScope = oldSharedScope; } else { ep->contextClass->setOverrideObject(data->expressionContext, oldOverride); } if (isUndefined) *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException(); // Handle exception if (scriptEngine->hasUncaughtException()) { exceptionToError(scriptEngine, data->error); scriptEngine->clearExceptions(); return QVariant(); } else { data->error = QDeclarativeError(); } QVariant rv; if (svalue.isArray()) { int length = svalue.property(QLatin1String("length")).toInt32(); if (length && svalue.property(0).isObject()) { QList<QObject *> list; for (int ii = 0; ii < length; ++ii) { QScriptValue arrayItem = svalue.property(ii); QObject *d = arrayItem.toQObject(); list << d; } rv = QVariant::fromValue(list); } } else if (svalue.isObject() && ep->objectClass->scriptClass(svalue) == ep->objectClass) { QObject *o = svalue.toQObject(); int type = QMetaType::QObjectStar; // If the object is null, we extract the predicted type. While this isn't // 100% reliable, in many cases it gives us better error messages if we // assign this null-object to an incompatible property if (!o) type = ep->objectClass->objectType(svalue); return QVariant(type, &o); } if (rv.isNull()) rv = svalue.toVariant(); return rv; }