void tst_QScriptContext::qobjectAsActivationObject()
{
    QScriptEngine eng;
    QObject object;
    QScriptValue scriptObject = eng.newQObject(&object);
    QScriptContext *ctx = eng.pushContext();
    ctx->setActivationObject(scriptObject);
    QVERIFY(ctx->activationObject().equals(scriptObject));

    QVERIFY(!scriptObject.property("foo").isValid());
    eng.evaluate("function foo() { return 123; }");
    {
        QScriptValue val = scriptObject.property("foo");
        QVERIFY(val.isValid());
        QVERIFY(val.isFunction());
    }
    QVERIFY(!eng.globalObject().property("foo").isValid());

    QVERIFY(!scriptObject.property("bar").isValid());
    eng.evaluate("var bar = 123");
    {
        QScriptValue val = scriptObject.property("bar");
        QVERIFY(val.isValid());
        QVERIFY(val.isNumber());
        QCOMPARE(val.toInt32(), 123);
    }
    QVERIFY(!eng.globalObject().property("bar").isValid());

    {
        QScriptValue val = eng.evaluate("delete foo");
        QVERIFY(val.isBool());
        QVERIFY(val.toBool());
        QVERIFY(!scriptObject.property("foo").isValid());
    }
}
static QScriptValue run(QScriptEngine* engine, const QString& fileName, bool recursive)
{
    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly)) {

        QTextStream stream(&file);
        const QString sourceCode = stream.readAll();

        if ( recursive ) {
            // A script context is pushed by the include function call.
            // Link that context to the one of the script that called include
            // Only do that, however, when called from the scipt
            QScriptContext *context = engine->currentContext();
            QScriptContext *parent=context->parentContext();
            context->setActivationObject(parent->activationObject());
            context->setThisObject(parent->thisObject());
        }

        QScriptValue result = engine->evaluate(sourceCode, fileName);
        if (engine->hasUncaughtException() && errorFileName.isNull() )
            errorFileName = fileName;

        return result;
    }
    else {
        Core::MessageManager::instance()->printToOutputPane(QObject::tr("Error: %1 doesn't exist.\n").arg(fileName),
                                                            Core::MessageManager::Flash);
        engine->abortEvaluation();
        return QScriptValue();
    }
}
QScriptValue QDeclarativeInclude::worker_include(QScriptContext *ctxt, QScriptEngine *engine)
{
    if (ctxt->argumentCount() == 0)
        return engine->undefinedValue();

    QString urlString = ctxt->argument(0).toString();
    QUrl url(ctxt->argument(0).toString());
    if (url.isRelative()) {
        QString contextUrl = QScriptDeclarativeClass::scopeChainValue(ctxt, -3).data().toString();
        Q_ASSERT(!contextUrl.isEmpty());

        url = QUrl(contextUrl).resolved(url);
        urlString = url.toString();
    }

    QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);

    QScriptValue func = ctxt->argument(1);
    if (!func.isFunction())
        func = QScriptValue();

    QScriptValue result;
    if (!localFile.isEmpty()) {

        QFile f(localFile);
        if (f.open(QIODevice::ReadOnly)) {
            QByteArray data = f.readAll();
            QString code = QString::fromUtf8(data);

            QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine);
            QScriptValue urlContext = engine->newObject();
            urlContext.setData(QScriptValue(engine, urlString));
            scriptContext->pushScope(urlContext);

            QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -4);
            scriptContext->pushScope(scope);
            scriptContext->setActivationObject(scope);
            QDeclarativeScriptParser::extractPragmas(code);

            engine->evaluate(code, urlString, 1);

            engine->popContext();

            if (engine->hasUncaughtException()) {
                result = resultValue(engine, Exception);
                result.setProperty(QLatin1String("exception"), engine->uncaughtException());
                engine->clearExceptions();
            } else {
                result = resultValue(engine, Ok);
            }
            callback(engine, func, result);
        } else {
            result = resultValue(engine, NetworkError);
            callback(engine, func, result);
        }
    }

    return result;
}
void QDeclarativeInclude::finished()
{
    m_redirectCount++;

    if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) {
        QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
        if (redirect.isValid()) {
            m_url = m_url.resolved(redirect.toUrl());
            delete m_reply; 
            
            QNetworkRequest request;
            request.setUrl(m_url);

            m_reply = m_network->get(request);
            QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
            return;
        }
    }

    if (m_reply->error() == QNetworkReply::NoError) {
        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine);

        QByteArray data = m_reply->readAll();

        QString code = QString::fromUtf8(data);

        QString urlString = m_url.toString();
        QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(m_scriptEngine);
        scriptContext->pushScope(ep->contextClass->newUrlContext(m_context, 0, urlString));
        scriptContext->pushScope(m_scope[0]);

        scriptContext->pushScope(m_scope[1]);
        scriptContext->setActivationObject(m_scope[1]);
        QDeclarativeScriptParser::extractPragmas(code);

        m_scriptEngine->evaluate(code, urlString, 1);

        m_scriptEngine->popContext();

        if (m_scriptEngine->hasUncaughtException()) {
            m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Exception));
            m_result.setProperty(QLatin1String("exception"), m_scriptEngine->uncaughtException());
            m_scriptEngine->clearExceptions();
        } else {
            m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Ok));
        }
    } else {
        m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, NetworkError));
    }

    callback(m_scriptEngine, m_callback, m_result);

    disconnect();
    deleteLater();
}
Exemple #5
0
/*!
  Executes the pending evaluate, if any.
*/
void QScriptDebuggerBackend::doPendingEvaluate(bool postEvent)
{
    Q_D(QScriptDebuggerBackend);
    QString program = d->pendingEvaluateProgram;
    if (program.isEmpty())
        return;
    int contextIndex = d->pendingEvaluateContextIndex;
    QScriptContext *ctx = context(contextIndex);
    Q_ASSERT(ctx != 0);
    QString fileName = d->pendingEvaluateFileName;
    int lineNumber = d->pendingEvaluateLineNumber;
    d->pendingEvaluateProgram = QString();
    d->pendingEvaluateFileName = QString();
    d->pendingEvaluateLineNumber = -1;
    d->pendingEvaluateContextIndex = -1;

    // push a new context and initialize its scope chain etc.
    {
        QScriptContext *evalContext = engine()->pushContext();
        QScriptValueList scopeChain = ctx->scopeChain();
        if (scopeChain.isEmpty())
            scopeChain.append(engine()->globalObject());
        while (!scopeChain.isEmpty())
            evalContext->pushScope(scopeChain.takeLast());
        evalContext->setActivationObject(ctx->activationObject());
        evalContext->setThisObject(ctx->thisObject());
    }

    d->agent->enterContinueMode();
    // set a flag so that any exception that happens in
    // the evaluate() is not sent to the debugger
    d->ignoreExceptions = true;
    bool hadException = engine()->hasUncaughtException();
    QScriptValue ret = engine()->evaluate(program, fileName, lineNumber);
    d->ignoreExceptions = false;
    if (!hadException && engine()->hasUncaughtException())
        engine()->clearExceptions();
    engine()->popContext();

    QScriptDebuggerValue retret(ret);
    QScriptDebuggerEvent e(QScriptDebuggerEvent::InlineEvalFinished);
    e.setScriptValue(retret);
    if (!ret.isUndefined())
        e.setMessage(ret.toString()); // for convenience -- we always need it

    e.setNestedEvaluate(engine()->isEvaluating());

    if (postEvent) {
        QScriptDebuggerEventEvent *de = new QScriptDebuggerEventEvent(e);
        d->postEvent(de);
    } else {
        event(e);
    }
}
void tst_QScriptContext::getSetActivationObject()
{
    QScriptEngine eng;
    QScriptContext *ctx = eng.currentContext();
    QVERIFY(ctx->activationObject().equals(eng.globalObject()));

    ctx->setActivationObject(QScriptValue());
    QVERIFY(ctx->activationObject().equals(eng.globalObject()));
    QCOMPARE(ctx->engine(), &eng);

    QScriptValue obj = eng.newObject();
    ctx->setActivationObject(obj);
    QVERIFY(ctx->activationObject().equals(obj));
    QCOMPARE(ctx->scopeChain().size(), 1);
    QVERIFY(ctx->scopeChain().at(0).equals(obj));

    {
        QScriptEngine eng2;
        QScriptValue obj2 = eng2.newObject();
        QTest::ignoreMessage(QtWarningMsg, "QScriptContext::setActivationObject() failed: cannot set an object created in a different engine");
        QScriptValue was = ctx->activationObject();
        ctx->setActivationObject(obj2);
        QVERIFY(ctx->activationObject().equals(was));
    }

    ctx->setActivationObject(eng.globalObject());
    QVERIFY(ctx->activationObject().equals(eng.globalObject()));
    QScriptValue fun = eng.newFunction(get_activationObject);
    eng.globalObject().setProperty("get_activationObject", fun);
    {
        QScriptValue ret = eng.evaluate("get_activationObject(1, 2, 3)");
        QVERIFY(ret.isObject());
        QScriptValue arguments = ret.property("arguments");
        QEXPECT_FAIL("", "Getting arguments property of activation object doesn't work", Abort);
        QVERIFY(arguments.isObject());
        QCOMPARE(arguments.property("length").toInt32(), 3);
        QCOMPARE(arguments.property("0").toInt32(), 1);
        QCOMPARE(arguments.property("1").toInt32(), 1);
        QCOMPARE(arguments.property("2").toInt32(), 1);
    }
}
void JavascriptInstance::IncludeFile(const QString &path)
{
    for(uint i = 0; i < includedFiles.size(); ++i)
        if (includedFiles[i].toLower() == path.toLower())
        {
            LogDebug("JavascriptInstance::IncludeFile: Not including already included file " + path);
            return;
        }

    QString script = LoadScript(path);

    QScriptContext *context = engine_->currentContext();
    assert(context);
    if (!context)
    {
        LogError("JavascriptInstance::IncludeFile: QScriptEngine::currentContext() returned null!");
        return;
    }

    QScriptContext *parent = context->parentContext();
    if (!parent)
    {
        LogError("JavascriptInstance::IncludeFile: QScriptEngine::parentContext() returned null!");
        return;
    }

    context->setActivationObject(context->parentContext()->activationObject());
    context->setThisObject(context->parentContext()->thisObject());

    QScriptSyntaxCheckResult syntaxResult = engine_->checkSyntax(script);
    if(syntaxResult.state() != QScriptSyntaxCheckResult::Valid)
    {
        LogError("JavascriptInstance::IncludeFile: Syntax error in " + path + ". " + syntaxResult.errorMessage() +
            " In line:" + QString::number(syntaxResult.errorLineNumber()));
        return;
    }

    QScriptValue result = engine_->evaluate(script, path);

    includedFiles.push_back(path);
    
    if (engine_->hasUncaughtException())
        LogError(result.toString());
}
void tst_QScriptContext::popNativeContextScope()
{
    QScriptEngine eng;
    QScriptContext *ctx = eng.pushContext();
    QVERIFY(ctx->popScope().isObject()); // the activation object

    QCOMPARE(ctx->scopeChain().size(), 1);
    QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject()));
    // This was different in 4.5: scope and activation were decoupled
    QVERIFY(ctx->activationObject().strictlyEquals(eng.globalObject()));

    QVERIFY(!eng.evaluate("var foo = 123; function bar() {}").isError());
    QVERIFY(eng.globalObject().property("foo").isNumber());
    QVERIFY(eng.globalObject().property("bar").isFunction());

    QScriptValue customScope = eng.newObject();
    ctx->pushScope(customScope);
    QCOMPARE(ctx->scopeChain().size(), 2);
    QVERIFY(ctx->scopeChain().at(0).strictlyEquals(customScope));
    QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject()));
    QVERIFY(ctx->activationObject().strictlyEquals(eng.globalObject()));
    ctx->setActivationObject(customScope);
    QVERIFY(ctx->activationObject().strictlyEquals(customScope));
    QCOMPARE(ctx->scopeChain().size(), 2);
    QVERIFY(ctx->scopeChain().at(0).strictlyEquals(customScope));
    QEXPECT_FAIL("", "QTBUG-11012", Continue);
    QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject()));

    QVERIFY(!eng.evaluate("baz = 456; var foo = 789; function barbar() {}").isError());
    QEXPECT_FAIL("", "QTBUG-11012", Continue);
    QVERIFY(eng.globalObject().property("baz").isNumber());
    QVERIFY(customScope.property("foo").isNumber());
    QVERIFY(customScope.property("barbar").isFunction());

    QVERIFY(ctx->popScope().strictlyEquals(customScope));
    QCOMPARE(ctx->scopeChain().size(), 1);
    QEXPECT_FAIL("", "QTBUG-11012", Continue);
    QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject()));

    // Need to push another object, otherwise we crash in popContext() (QTBUG-11012)
    ctx->pushScope(customScope);
    eng.popContext();
}
bool HttpHandlerQtScriptFile::handleRequest(Pillow::HttpConnection *request)
{
	if (!_lastModified.isValid() || (_autoReload && QFileInfo(_fileName).lastModified() > _lastModified))
	{
		// Time to (re)load the script.
		qDebug() << "HttpHandlerQtScriptFile::handleRequest: (re)loading" << _fileName;
		QFile file(_fileName);
		if (!file.open(QIODevice::ReadOnly))
		{
			request->writeResponseString(500, HttpHeaderCollection(), QString("HttpHandlerQtScriptFile::handleRequest: Could not read file %1").arg(_fileName));
			return true;
		}

		QScriptEngine* engine = _scriptObject.engine();
		_scriptObject = engine->newObject();
		QScriptContext* context = engine->pushContext();
		context->setActivationObject(_scriptObject);
		context->setThisObject(_scriptObject);
		QScriptValue result = engine->evaluate(file.readAll(), _fileName);
		engine->popContext();

		if (result.isError())
		{
			request->writeResponseString(500, HttpHeaderCollection(), QString("HttpHandlerQtScriptFile::handleRequest: Error while evaluating script %1: %2").arg(_fileName).arg(objectToString(result)));
			return true;
		}

		QScriptValue scriptFunction = _scriptObject.property(_functionName);
		if (!scriptFunction.isFunction())
		{
			request->writeResponseString(500, HttpHeaderCollection(), QString("HttpHandlerQtScriptFile::handleRequest: Error while evaluating script %1: '%2' is not a function defined in the script").arg(_fileName).arg(_functionName));
			return true;
		}

		_lastModified = QFileInfo(_fileName).lastModified();
		setScriptFunction(scriptFunction);
	}

	return HttpHandlerQtScript::handleRequest(request);
}
/*
    Documented in qdeclarativeengine.cpp
*/
QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *engine)
{
    if (ctxt->argumentCount() == 0)
        return engine->undefinedValue();

    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);

    QUrl contextUrl = ep->contextClass->urlFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));
    if (contextUrl.isEmpty()) 
        return ctxt->throwError(QLatin1String("Qt.include(): Can only be called from JavaScript files"));

    QString urlString = ctxt->argument(0).toString();
    QUrl url(urlString);
    if (url.isRelative()) {
        url = QUrl(contextUrl).resolved(url);
        urlString = url.toString();
    }

    QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);

    QScriptValue func = ctxt->argument(1);
    if (!func.isFunction())
        func = QScriptValue();

    QScriptValue result;
    if (localFile.isEmpty()) {
        QDeclarativeInclude *i = 
            new QDeclarativeInclude(url, QDeclarativeEnginePrivate::getEngine(engine), ctxt);

        if (func.isValid())
            i->setCallback(func);

        result = i->result();
    } else {

        QFile f(localFile);
        if (f.open(QIODevice::ReadOnly)) {
            QByteArray data = f.readAll();
            QString code = QString::fromUtf8(data);

            QDeclarativeContextData *context = 
                ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));

            QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine);
            scriptContext->pushScope(ep->contextClass->newUrlContext(context, 0, urlString));
            scriptContext->pushScope(ep->globalClass->staticGlobalObject());
            QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -5);
            scriptContext->pushScope(scope);
            scriptContext->setActivationObject(scope);
            QDeclarativeScriptParser::extractPragmas(code);

            engine->evaluate(code, urlString, 1);

            engine->popContext();

            if (engine->hasUncaughtException()) {
                result = resultValue(engine, Exception);
                result.setProperty(QLatin1String("exception"), engine->uncaughtException());
                engine->clearExceptions();
            } else {
                result = resultValue(engine, Ok);
            }
            callback(engine, func, result);
        } else {
            result = resultValue(engine, NetworkError);
            callback(engine, func, result);
        }
    }

    return result;
}
Exemple #11
0
void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script)
{
    if (!engine) 
        return;

    Q_ASSERT(script.codes.count() == 1);

    QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
    QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);

    const QString &code = script.codes.at(0);
    const QString &url = script.files.at(0);
    const QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = script.pragmas.at(0);

    Q_ASSERT(!url.isEmpty());

    if (pragmas & QDeclarativeParser::Object::ScriptBlock::Shared) {

        QHash<QString, QScriptValue>::Iterator iter = enginePriv->m_sharedScriptImports.find(url);
        if (iter == enginePriv->m_sharedScriptImports.end()) {
            QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);

            scriptContext->pushScope(enginePriv->contextClass->newContext(0, 0));
            scriptContext->pushScope(enginePriv->globalClass->globalObject());
        
            QScriptValue scope = scriptEngine->newObject();
            scriptContext->setActivationObject(scope);
            scriptContext->pushScope(scope);

            scriptEngine->evaluate(code, url, 1);

            if (scriptEngine->hasUncaughtException()) {
                QDeclarativeError error;
                QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
                enginePriv->warning(error);
            }

            scriptEngine->popContext();

            iter = enginePriv->m_sharedScriptImports.insert(url, scope);
        }

        importedScripts.append(*iter);

    } else {

        QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);

        scriptContext->pushScope(enginePriv->contextClass->newContext(this, 0));
        scriptContext->pushScope(enginePriv->globalClass->globalObject());
        
        QScriptValue scope = scriptEngine->newObject();
        scriptContext->setActivationObject(scope);
        scriptContext->pushScope(scope);

        scriptEngine->evaluate(code, url, 1);

        if (scriptEngine->hasUncaughtException()) {
            QDeclarativeError error;
            QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
            enginePriv->warning(error);
        }

        scriptEngine->popContext();

        importedScripts.append(scope);

    }
}