932 lines · 37.4 KB · C++
RawDownload
        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);    }} ScriptValue ScriptEngineQtScript::evaluateInClosure(const ScriptValue& _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    ScriptValue 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 = ScriptValue(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;} ScriptValue ScriptEngineQtScript::evaluate(const QString& sourceCode, const QString& fileName) {    if (_scriptManager && _scriptManager->isStopped()) {        return undefinedValue(); // bail early    }     if (QThread::currentThread() != QScriptEngine::thread()) {        ScriptValue 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(ScriptValue, 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 ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} Q_INVOKABLE ScriptValue ScriptEngineQtScript::evaluate(const ScriptProgramPointer& program) {    if (_scriptManager && _scriptManager->isStopped()) {        return undefinedValue(); // bail early    }     if (QThread::currentThread() != QScriptEngine::thread()) {        ScriptValue 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(ScriptValue, 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 ScriptValue(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    }}  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ScriptEngine implementation ScriptValue ScriptEngineQtScript::globalObject() const {    QScriptValue global = QScriptEngine::globalObject(); // can't cache the value as it may change    return ScriptValue(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(global)));} ScriptManager* ScriptEngineQtScript::manager() const {    return _scriptManager;} ScriptValue ScriptEngineQtScript::newArray(uint length) {    QScriptValue result = QScriptEngine::newArray(length);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue 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 ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newObject() {    QScriptValue result = QScriptEngine::newObject();    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptProgramPointer ScriptEngineQtScript::newProgram(const QString& sourceCode, const QString& fileName) {    QScriptProgram result(sourceCode, fileName);    return std::make_shared<ScriptProgramQtWrapper>(this, result);} ScriptValue ScriptEngineQtScript::newQObject(QObject* object,                                                    ScriptEngine::ValueOwnership ownership,                                                    const ScriptEngine::QObjectWrapOptions& options) {    QScriptValue result = ScriptObjectQtProxy::newQObject(this, object, ownership, options);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newValue(bool value) {    QScriptValue result(this, value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newValue(int value) {    QScriptValue result(this, value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newValue(uint value) {    QScriptValue result(this, value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newValue(double value) {    QScriptValue result(this, value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newValue(const QString& value) {    QScriptValue result(this, value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newValue(const QLatin1String& value) {    QScriptValue result(this, value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newValue(const char* value) {    QScriptValue result(this, value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::newVariant(const QVariant& value) {    QScriptValue result = castVariantToValue(value);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(result)));} ScriptValue ScriptEngineQtScript::nullValue() {    return _nullValue;} ScriptValue 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 = std::make_shared<ScriptContextQtWrapper>(const_cast<ScriptEngineQtScript*>(this), localCtx);    }    return _currContext.get();} bool ScriptEngineQtScript::hasUncaughtException() const {    return QScriptEngine::hasUncaughtException();} bool ScriptEngineQtScript::isEvaluating() const {    return QScriptEngine::isEvaluating();} ScriptValue 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);        ScriptValue 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 ScriptValue(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();} void ScriptEngineQtScript::setThread(QThread* thread) {    moveToThread(thread);} ScriptValue ScriptEngineQtScript::uncaughtException() const {    QScriptValue result = QScriptEngine::uncaughtException();    return ScriptValue(new ScriptValueQtWrapper(const_cast<ScriptEngineQtScript*>(this), std::move(result)));} QStringList ScriptEngineQtScript::uncaughtExceptionBacktrace() const {    return QScriptEngine::uncaughtExceptionBacktrace();} int ScriptEngineQtScript::uncaughtExceptionLineNumber() const {    return QScriptEngine::uncaughtExceptionLineNumber();} bool ScriptEngineQtScript::raiseException(const ScriptValue& exception) {    ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(exception);    QScriptValue qException = unwrapped ? unwrapped->toQtValue() : QScriptEngine::newVariant(exception.toVariant());    return raiseException(qException);} ScriptValue ScriptEngineQtScript::create(int type, const void* ptr) {    QVariant variant(type, ptr);    QScriptValue scriptValue = castVariantToValue(variant);    return ScriptValue(new ScriptValueQtWrapper(this, std::move(scriptValue)));} QVariant ScriptEngineQtScript::convert(const ScriptValue& value, int type) {    ScriptValueQtWrapper* unwrapped = ScriptValueQtWrapper::unwrap(value);    if (unwrapped == nullptr) {        return QVariant();    }     QVariant var;    if (!castValueToVariant(unwrapped->toQtValue(), var, type)) {        return QVariant();    }     int destType = var.userType();    if (destType != type) {        var.convert(type); // if conversion fails then var is set to QVariant()    }     return var;}

Lines 501–932 of 932. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t