1037 lines · 42.5 KB · C++
RawDownload
        } else {            QScriptEngine::globalObject().setProperty(name, QScriptValue());        }    }} void ScriptEngineQtScript::registerFunction(const QString& name, QScriptEngine::FunctionSignature functionSignature, int numArguments) {    if (QThread::currentThread() != QScriptEngine::thread()) {#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;#endif        QMetaObject::invokeMethod(this, "registerFunction",                                  Q_ARG(const QString&, name),                                  Q_ARG(QScriptEngine::FunctionSignature, functionSignature),                                  Q_ARG(int, numArguments));        return;    }#ifdef THREAD_DEBUGGING    qCDebug(scriptengine) << "ScriptEngineQtScript::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name;#endif     QScriptValue scriptFun = QScriptEngine::newFunction(functionSignature, numArguments);    QScriptEngine::globalObject().setProperty(name, scriptFun);} void ScriptEngineQtScript::registerFunction(const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) {    if (QThread::currentThread() != QScriptEngine::thread()) {#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] name:" << name;#endif        QMetaObject::invokeMethod(this, "registerFunction",                                  Q_ARG(const QString&, name),                                  Q_ARG(ScriptEngine::FunctionSignature, functionSignature),                                  Q_ARG(int, numArguments));        return;    }#ifdef THREAD_DEBUGGING    qCDebug(scriptengine) << "ScriptEngineQtScript::registerFunction() called on thread [" << QThread::currentThread() << "] name:" << name;#endif     auto scriptFun = newFunction(functionSignature, numArguments);    globalObject()->setProperty(name, scriptFun);} void ScriptEngineQtScript::registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature functionSignature, int numArguments) {    if (QThread::currentThread() != QScriptEngine::thread()) {#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] parent:" << parent << "name:" << name;#endif        QMetaObject::invokeMethod(this, "registerFunction",                                  Q_ARG(const QString&, name),                                  Q_ARG(QScriptEngine::FunctionSignature, functionSignature),                                  Q_ARG(int, numArguments));        return;    }#ifdef THREAD_DEBUGGING    qCDebug(scriptengine) << "ScriptEngineQtScript::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name;#endif     QScriptValue object = QScriptEngine::globalObject().property(parent);    if (object.isValid()) {        QScriptValue scriptFun = QScriptEngine::newFunction(functionSignature, numArguments);        object.setProperty(name, scriptFun);    }} void ScriptEngineQtScript::registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature functionSignature, int numArguments) {    if (QThread::currentThread() != QScriptEngine::thread()) {#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::registerFunction() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] parent:" << parent << "name:" << name;#endif        QMetaObject::invokeMethod(this, "registerFunction",                                  Q_ARG(const QString&, name),                                  Q_ARG(ScriptEngine::FunctionSignature, functionSignature),                                  Q_ARG(int, numArguments));        return;    }#ifdef THREAD_DEBUGGING    qCDebug(scriptengine) << "ScriptEngineQtScript::registerFunction() called on thread [" << QThread::currentThread() << "] parent:" << parent << "name:" << name;#endif     auto object = globalObject()->property(parent);    if (object->isValid()) {        auto scriptFun = newFunction(functionSignature, numArguments);        object->setProperty(name, scriptFun);    }} void ScriptEngineQtScript::registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,                                        QScriptEngine::FunctionSignature setter, const QString& parent) {    if (QThread::currentThread() != QScriptEngine::thread()) {#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::registerGetterSetter() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "            " name:" << name << "parent:" << parent;#endif        QMetaObject::invokeMethod(this, "registerGetterSetter",                                  Q_ARG(const QString&, name),                                  Q_ARG(QScriptEngine::FunctionSignature, getter),                                  Q_ARG(QScriptEngine::FunctionSignature, setter),                                  Q_ARG(const QString&, parent));        return;    }#ifdef THREAD_DEBUGGING    qCDebug(scriptengine) << "ScriptEngineQtScript::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent;#endif     QScriptValue setterFunction = QScriptEngine::newFunction(setter, 1);    QScriptValue getterFunction = QScriptEngine::newFunction(getter);     if (!parent.isNull() && !parent.isEmpty()) {        QScriptValue object = QScriptEngine::globalObject().property(parent);        if (object.isValid()) {            object.setProperty(name, setterFunction, QScriptValue::PropertySetter);            object.setProperty(name, getterFunction, QScriptValue::PropertyGetter);        }    } else {        QScriptEngine::globalObject().setProperty(name, setterFunction, QScriptValue::PropertySetter);        QScriptEngine::globalObject().setProperty(name, getterFunction, QScriptValue::PropertyGetter);    }} void ScriptEngineQtScript::registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter,                                        ScriptEngine::FunctionSignature setter, const QString& parent) {    if (QThread::currentThread() != QScriptEngine::thread()) {#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::registerGetterSetter() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "            " name:" << name << "parent:" << parent;#endif        QMetaObject::invokeMethod(this, "registerGetterSetter",                                  Q_ARG(const QString&, name),                                  Q_ARG(ScriptEngine::FunctionSignature, getter),                                  Q_ARG(ScriptEngine::FunctionSignature, setter),                                  Q_ARG(const QString&, parent));        return;    }#ifdef THREAD_DEBUGGING    qCDebug(scriptengine) << "ScriptEngineQtScript::registerGetterSetter() called on thread [" << QThread::currentThread() << "] name:" << name << "parent:" << parent;#endif     auto setterFunction = newFunction(setter, 1);    auto getterFunction = newFunction(getter);     if (!parent.isNull() && !parent.isEmpty()) {        auto object = globalObject()->property(parent);        if (object->isValid()) {            object->setProperty(name, setterFunction, ScriptValue::PropertySetter);            object->setProperty(name, getterFunction, ScriptValue::PropertyGetter);        }    } else {        globalObject()->setProperty(name, setterFunction, ScriptValue::PropertySetter);        globalObject()->setProperty(name, getterFunction, ScriptValue::PropertyGetter);    }} ScriptValuePointer ScriptEngineQtScript::evaluateInClosure(const ScriptValuePointer& _closure,                                                           const ScriptProgramPointer& _program) {    PROFILE_RANGE(script, "evaluateInClosure");    if (!IS_THREADSAFE_INVOCATION(thread(), __FUNCTION__)) {        return nullValue();    }    ScriptProgramQtWrapper* unwrappedProgram = ScriptProgramQtWrapper::unwrap(_program);    if (unwrappedProgram == nullptr) {        return nullValue();    }    const QScriptProgram& program = unwrappedProgram->toQtValue();     const auto fileName = program.fileName();    const auto shortName = QUrl(fileName).fileName();     ScriptValueQtWrapper* unwrappedClosure = ScriptValueQtWrapper::unwrap(_closure);    if (unwrappedClosure == nullptr) {        return nullValue();    }    const QScriptValue& closure = unwrappedClosure->toQtValue();     QScriptValue oldGlobal;    auto global = closure.property("global");    if (global.isObject()) {#ifdef DEBUG_JS        qCDebug(shared) << " setting global = closure.global" << shortName;#endif        oldGlobal = QScriptEngine::globalObject();        setGlobalObject(global);    }     auto context = pushContext();     auto thiz = closure.property("this");    if (thiz.isObject()) {#ifdef DEBUG_JS        qCDebug(shared) << " setting this = closure.this" << shortName;#endif        context->setThisObject(thiz);    }     context->pushScope(closure);#ifdef DEBUG_JS    qCDebug(shared) << QString("[%1] evaluateInClosure %2").arg(isEvaluating()).arg(shortName);#endif    ScriptValuePointer result;    {        auto qResult = QScriptEngine::evaluate(program);         if (hasUncaughtException()) {            auto err = cloneUncaughtException(__FUNCTION__);#ifdef DEBUG_JS_EXCEPTIONS            qCWarning(shared) << __FUNCTION__ << "---------- hasCaught:" << err.toString() << result.toString();            err.setProperty("_result", result);#endif            result = err;        } else {            result = ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(qResult)));        }    }#ifdef DEBUG_JS    qCDebug(shared) << QString("[%1] //evaluateInClosure %2").arg(isEvaluating()).arg(shortName);#endif    popContext();     if (oldGlobal.isValid()) {#ifdef DEBUG_JS        qCDebug(shared) << " restoring global" << shortName;#endif        setGlobalObject(oldGlobal);    }     return result;} ScriptValuePointer ScriptEngineQtScript::evaluate(const QString& sourceCode, const QString& fileName) {    if (_manager && _manager->isStopped()) {        return undefinedValue(); // bail early    }     if (QThread::currentThread() != QScriptEngine::thread()) {        ScriptValuePointer result;#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "            "sourceCode:" << sourceCode << " fileName:" << fileName;#endif        BLOCKING_INVOKE_METHOD(this, "evaluate",                                  Q_RETURN_ARG(ScriptValuePointer, result),                                  Q_ARG(const QString&, sourceCode),                                  Q_ARG(const QString&, fileName));        return result;    }     // Check syntax    auto syntaxError = lintScript(sourceCode, fileName);    if (syntaxError->isError()) {        if (!isEvaluating()) {            syntaxError->setProperty("detail", "evaluate");        }        raiseException(syntaxError);        maybeEmitUncaughtException("lint");        return syntaxError;    }    QScriptProgram program { sourceCode, fileName, 1 };    if (program.isNull()) {        // can this happen?        auto err = makeError(newValue("could not create QScriptProgram for " + fileName));        raiseException(err);        maybeEmitUncaughtException("compile");        return err;    }     QScriptValue result = QScriptEngine::evaluate(program);    maybeEmitUncaughtException("evaluate");        return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} Q_INVOKABLE ScriptValuePointer ScriptEngineQtScript::evaluate(const ScriptProgramPointer& program) {    if (_manager && _manager->isStopped()) {        return undefinedValue(); // bail early    }     if (QThread::currentThread() != QScriptEngine::thread()) {        ScriptValuePointer result;#ifdef THREAD_DEBUGGING        qCDebug(scriptengine) << "*** WARNING *** ScriptEngineQtScript::evaluate() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "            "sourceCode:" << sourceCode << " fileName:" << fileName;#endif        BLOCKING_INVOKE_METHOD(this, "evaluate",                                  Q_RETURN_ARG(ScriptValuePointer, result),                                  Q_ARG(const ScriptProgramPointer&, program));        return result;    }     ScriptProgramQtWrapper* unwrapped = ScriptProgramQtWrapper::unwrap(program);    if (!unwrapped) {        auto err = makeError(newValue("could not unwrap program"));        raiseException(err);        maybeEmitUncaughtException("compile");        return err;    }     const QScriptProgram& qProgram = unwrapped->toQtValue();    if (qProgram.isNull()) {        // can this happen?        auto err = makeError(newValue("requested program is empty"));        raiseException(err);        maybeEmitUncaughtException("compile");        return err;    }     QScriptValue result = QScriptEngine::evaluate(qProgram);    maybeEmitUncaughtException("evaluate");     return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));}  void ScriptEngineQtScript::updateMemoryCost(const qint64& deltaSize) {    if (deltaSize > 0) {        // We've patched qt to fix https://highfidelity.atlassian.net/browse/BUGZ-46 on mac and windows only.#if defined(Q_OS_WIN) || defined(Q_OS_MAC)        reportAdditionalMemoryCost(deltaSize);#endif    }} void ScriptEngineQtScript::print(const QString& message) {    QString filename;    auto scriptManager = manager();    if (scriptManager) {        filename = scriptManager->getFilename();    }     emit printedMessage(message, filename);}  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ScriptEngine implementation ScriptValuePointer ScriptEngineQtScript::globalObject() const {    QScriptValue global = QScriptEngine::globalObject(); // can't cache the value as it may change    return ScriptValuePointer(new ScriptValueQtWrapper(const_cast < ScriptEngineQtScript*>(this), std::move(global)));} ScriptManager* ScriptEngineQtScript::manager() const {    return _manager;} ScriptValuePointer ScriptEngineQtScript::newArray(uint length) {    QScriptValue result = QScriptEngine::newArray(length);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newArrayBuffer(const QByteArray& message) {    QScriptValue data = QScriptEngine::newVariant(QVariant::fromValue(message));    QScriptValue ctor = QScriptEngine::globalObject().property("ArrayBuffer");    auto array = qscriptvalue_cast<ArrayBufferClass*>(ctor.data());    if (!array) {        return undefinedValue();    }    QScriptValue result = QScriptEngine::newObject(array, data);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newObject() {    QScriptValue result = QScriptEngine::newObject();    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptProgramPointer ScriptEngineQtScript::newProgram(const QString& sourceCode, const QString& fileName) {    QScriptProgram result(sourceCode, fileName);    return ScriptProgramPointer(new ScriptProgramQtWrapper(this, result));} ScriptValuePointer ScriptEngineQtScript::newQObject(QObject* object,                                                    ScriptEngine::ValueOwnership ownership,                                                    const ScriptEngine::QObjectWrapOptions& options) {    QScriptValue result = QScriptEngine::newQObject(object, static_cast<QScriptEngine::ValueOwnership>(ownership),        (QScriptEngine::QObjectWrapOptions)((int)options | DEFAULT_QOBJECT_WRAP_OPTIONS));    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newValue(bool value) {    QScriptValue result(this, value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newValue(int value) {    QScriptValue result(this, value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newValue(uint value) {    QScriptValue result(this, value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newValue(double value) {    QScriptValue result(this, value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newValue(const QString& value) {    QScriptValue result(this, value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newValue(const QLatin1String& value) {    QScriptValue result(this, value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newValue(const char* value) {    QScriptValue result(this, value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::newVariant(const QVariant& value) {    QScriptValue result = QScriptEngine::newVariant(value);    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValuePointer ScriptEngineQtScript::nullValue() {    return _nullValue;} void ScriptEngineQtScript::setDefaultPrototype(int metaTypeId, const ScriptValuePointer& prototype){    ScriptValueQtWrapper* unwrappedPrototype = ScriptValueQtWrapper::unwrap(prototype);    if (unwrappedPrototype) {        QScriptEngine::setDefaultPrototype(metaTypeId, unwrappedPrototype->toQtValue());    }} ScriptValuePointer ScriptEngineQtScript::undefinedValue() {    return _undefinedValue;} void ScriptEngineQtScript::abortEvaluation() {    QScriptEngine::abortEvaluation();} void ScriptEngineQtScript::clearExceptions() {    QScriptEngine::clearExceptions();} ScriptContext* ScriptEngineQtScript::currentContext() const {    QScriptContext* localCtx = QScriptEngine::currentContext();    if (!localCtx) {        return nullptr;    }    if (!_currContext || _currContext->toQtValue() != localCtx) {        _currContext = ScriptContextQtPointer(new ScriptContextQtWrapper(const_cast<ScriptEngineQtScript*>(this), localCtx));    }    return _currContext.get();} bool ScriptEngineQtScript::hasUncaughtException() const {    return QScriptEngine::hasUncaughtException();} bool ScriptEngineQtScript::isEvaluating() const {    return QScriptEngine::isEvaluating();} ScriptValuePointer ScriptEngineQtScript::newFunction(ScriptEngine::FunctionSignature fun, int length) {    auto innerFunc = [](QScriptContext* _context, QScriptEngine* _engine) -> QScriptValue {        auto callee = _context->callee();        QVariant funAddr = callee.property("_func").toVariant();        ScriptEngine::FunctionSignature fun = reinterpret_cast<ScriptEngine::FunctionSignature>(funAddr.toULongLong());        ScriptEngineQtScript* engine = static_cast<ScriptEngineQtScript*>(_engine);        ScriptContextQtWrapper context(engine, _context);        ScriptValuePointer result = fun(&context, engine);        ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(result);        return unwrapped ? unwrapped->toQtValue() : QScriptValue();    };     QScriptValue result = QScriptEngine::newFunction(innerFunc, length);    auto funAddr = QScriptEngine::newVariant(QVariant(reinterpret_cast<qulonglong>(fun)));    result.setProperty("_func", funAddr, QScriptValue::PropertyFlags(QScriptValue::ReadOnly + QScriptValue::Undeletable + QScriptValue::SkipInEnumeration));    return ScriptValuePointer(new ScriptValueQtWrapper(this, std::move(result)));} void ScriptEngineQtScript::setObjectName(const QString& name) {    QScriptEngine::setObjectName(name);} bool ScriptEngineQtScript::setProperty(const char* name, const QVariant& value) {    return QScriptEngine::setProperty(name, value);} void ScriptEngineQtScript::setProcessEventsInterval(int interval) {    QScriptEngine::setProcessEventsInterval(interval);} QThread* ScriptEngineQtScript::thread() const {    return QScriptEngine::thread();} ScriptValuePointer ScriptEngineQtScript::uncaughtException() const {    QScriptValue result = QScriptEngine::uncaughtException();    return ScriptValuePointer(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result)));} 

Lines 501–1000 of 1037. Previous lines