Класс QJSEngine
Класс QJSEngine предоставляет среду для оценки кода JavaScript. Подробнее...
| Заголовок: | #include <QJSEngine> |
| qmake: | QT += qml |
| С момента: | Qt 5.0 |
| Наследует: | QObject |
| Наследуется от: |
Этот класс был представлен в Qt 5.0.
Примечание: Все функции в этом классе являются повторно входящими.
Типы public
| Перечисление | Extension { РасширениеПеревода, РасширениеКонсоли, РасширениеСборкиМусора, ВсеРасширения } |
| флаги | Расширения |
Public Функции
| QJSEngine(QObject *parent) | |
| QJSEngine() | |
| virtual | ~QJSEngine() override |
| void | collectGarbage() |
| QJSValue | evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1) |
| T | fromScriptValue(const QJSValue &value) |
| QJSValue | globalObject() const |
| QJSValue | importModule(const QString &fileName) |
| void | installExtensions(QJSEngine::Extensions extensions, const QJSValue &object = QJSValue()) |
| bool | isInterrupted() const |
| QJSValue | newArray(uint length = 0) |
| QJSValue | newErrorObject(QJSValue::ErrorType errorType, const QString &message = QString()) |
| QJSValue | newObject() |
| QJSValue | newQMetaObject(const QMetaObject *metaObject) |
| QJSValue | newQMetaObject() |
| QJSValue | newQObject(QObject *object) |
| void | setInterrupted(bool interrupted) |
| void | throwError(const QString &message) |
| void | throwError(QJSValue::ErrorType errorType, const QString &message = QString()) |
| QJSValue | toScriptValue(const T &value) |
Связанные нечлены
| QJSEngine * | qjsEngine(const QObject *object) |
Подробное описание
Оценка скриптов
Используйте evaluate() для оценки кода скрипта.
QJSEngine myEngine;
QJSValue three = myEngine.evaluate("1 + 2"); evaluate() возвращает QJSValue, содержащую результат оценки. Класс QJSValue предоставляет функции для преобразования результата в различные типы C++ (например, QJSValue::toString() и QJSValue::toNumber()).
Следующий фрагмент кода демонстрирует, как можно определить функцию скрипта и затем вызвать ее из C++ с помощью QJSValue::call():
QJSValue fun = myEngine.evaluate("(function(a, b) { return a + b; })");
QJSValueList args;
args << 1 << 2;
QJSValue threeAgain = fun.call(args); Как видно из приведенных фрагментов, скрипт предоставляется движку в виде строки. Один из распространенных способов загрузки скриптов — чтение содержимого файла и передача его в evaluate():
QString fileName = "helloworld.qs";
QFile scriptFile(fileName);
if (!scriptFile.open(QIODevice::ReadOnly))
// handle error
QTextStream stream(&scriptFile);
QString contents = stream.readAll();
scriptFile.close();
myEngine.evaluate(contents, fileName); Здесь мы передаем имя файла в качестве второго аргумента в evaluate(). Это никак не влияет на оценку; второй аргумент — строка общего назначения, хранящаяся в Error объекте для отладки.
Для более крупных функциональных возможностей вы можете упаковать свой код и данные в модули. Модуль — это файл, содержащий код скрипта, переменные и т. д., и использующий операторы экспорта для описания своего интерфейса с остальной частью приложения. С помощью операторов импорта модуль может ссылаться на функциональность из других модулей. Это позволяет создавать приложение со скриптами из меньших взаимосвязанных строительных блоков безопасным способом. В отличие от этого подход с использованием evaluate() сопряжен с риском того, что внутренние переменные или функции одного вызова evaluate() случайно загрязните глобальный объект и повлияют на последующие оценки.
Следующий пример предоставляет модуль, который может складывать числа:
export function sum(left, right)
{
return left + right
} Этот модуль можно загрузить с помощью QJSEngine::import(), если он сохранен под именем math.mjs:
QJSvalue module = myEngine.importModule("./math.mjs");
QJSValue sumFunction = module.property("sum");
QJSValue result = sumFunction.call(args); Модули также могут использовать функциональность других модулей с помощью операторов импорта:
import { sum } from "./math.mjs";
export function addTwice(left, right)
{
return sum(left, right) * 2;
} Настройка движка
Функция globalObject() возвращает связанный с движком скрипта Глобальный объект. Свойства Глобального объекта доступны из любого кода скрипта (то есть они являются глобальными переменными). Обычно перед оценкой «пользовательских» скриптов вы хотите настроить движок скриптов, добавив одно или несколько свойств в Глобальный объект:
myEngine.globalObject().setProperty("myNumber", 123);
...
QJSValue myNumberPlusOne = myEngine.evaluate("myNumber + 1"); Добавление пользовательских свойств в среду скриптинга — один из стандартных способов предоставления API скриптинга, специфичного для вашего приложения. Обычно эти пользовательские свойства представляют собой объекты, созданные с помощью функций newQObject() или newObject().
Исключения скрипта
evaluate() может генерировать исключение скрипта (например, из-за синтаксической ошибки). В случае возникновения исключения evaluate() возвращает значение, сгенерировавшее исключение (обычно объект Error). Используйте QJSValue::isError(), чтобы проверить наличие исключений.
Для получения подробной информации об ошибке используйте QJSValue::toString() для получения сообщения об ошибке и QJSValue::property() для запроса свойств объекта Error. Доступны следующие свойства:
namemessagefileNamelineNumberstack
QJSValue result = myEngine.evaluate(...);
if (result.isError())
qDebug()
<< "Uncaught exception at line"
<< result.property("lineNumber").toInt()
<< ":" << result.toString(); Создание объекта скрипта
Используйте newObject() для создания объекта JavaScript; это эквивалент оператора скрипта new Object() в C++. Вы можете использовать функциональность, специфичную для объектов, в QJSValue для управления объектом скрипта (например, QJSValue::setProperty()). Аналогично, используйте newArray() для создания объекта массива JavaScript.
Интеграция QObject
Используйте newQObject() для упаковки указателя QObject (или подкласса). newQObject() возвращает прокси-объект скрипта; свойства, дочерние элементы, сигналы и слоты QObject доступны как свойства прокси-объекта. Код привязки не требуется, поскольку он выполняется динамически с помощью системы метаобъектов Qt.
QPushButton *button = new QPushButton;
QJSValue scriptButton = myEngine.newQObject(button);
myEngine.globalObject().setProperty("button", scriptButton);
myEngine.evaluate("button.checkable = true");
qDebug() << scriptButton.property("checkable").toBool();
scriptButton.property("show").call(); // call the show() slot Используйте newQMetaObject() для упаковки QMetaObject; это дает вам «представление скрипта» класса на основе QObject. newQMetaObject() возвращает прокси-объект скрипта; значения перечислений класса доступны как свойства прокси-объекта.
Конструкторы, доступные для системы метаобъектов (с использованием Q_INVOKABLE), могут вызываться из скрипта для создания нового экземпляра QObject с JavaScriptOwnership. Например, при наличии следующего определения класса:
class MyObject : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyObject() {}
}; staticMetaObject для класса можно сделать доступными для JavaScript следующим образом:
QJSValue jsMetaObject = engine.newQMetaObject(&MyObject::staticMetaObject);
engine.globalObject().setProperty("MyObject", jsMetaObject); Экземпляры класса можно создать в JavaScript:
engine.evaluate("var myObject = new MyObject()"); Примечание: В настоящее время поддерживаются только классы, использующие макрос Q_OBJECT; невозможно экспонировать staticMetaObject класса Q_GADGET в JavaScript.
Динамические свойства QObject
Динамические свойства QObject не поддерживаются. Например, следующий код не будет работать:
QJSEngine engine;
QObject *myQObject = new QObject();
myQObject->setProperty("dynamicProperty", 3);
QJSValue myScriptQObject = engine.newQObject(myQObject);
engine.globalObject().setProperty("myObject", myScriptQObject);
qDebug() << engine.evaluate("myObject.dynamicProperty").toInt(); Расширения
QJSEngine предоставляет совместимую реализацию ECMAScript. По умолчанию такие знакомые инструменты, как регистрация, недоступны, но их можно установить с помощью функции installExtensions().
См. также QJSValue, Делаем приложения расширяемыми скриптами и Список JavaScript-объектов и функций.
Документация по типам членов
enum QJSEngine::Extensionflags QJSEngine::Extensions
Этот перечисление используется для указания расширений, которые необходимо установить с помощью installExtensions().
| Константа | Значение | Описание |
|---|---|---|
QJSEngine::TranslationExtension |
0x1 |
Указывает, что необходимо установить функции перевода (например, qsTr()). |
QJSEngine::ConsoleExtension |
0x2 |
Указывает, что необходимо установить функции консоли (например, console.log()). |
QJSEngine::GarbageCollectionExtension |
0x4 |
Указывает, что необходимо установить функции сбора мусора (например, gc()). |
QJSEngine::AllExtensions |
0xffffffff |
Указывает, что необходимо установить все расширения. |
TranslationExtension
Взаимосвязь между функциями перевода скриптов и функциями перевода C++ описывается в следующей таблице:
| Функция скрипта | Соответствующая функция C++ |
|---|---|
| qsTr() | QObject::tr() |
| QT_TR_NOOP() | QT_TR_NOOP() |
| qsTranslate() | QCoreApplication::translate() |
| QT_TRANSLATE_NOOP() | QT_TRANSLATE_NOOP() |
| qsTrId() | qtTrId() |
| QT_TRID_NOOP() | QT_TRID_NOOP() |
Этот флаг также добавляет функцию arg() к прототипу строки.
Дополнительную информацию см. в документации Локализация с Qt.
ConsoleExtension
Объект console реализует подмножество Console API, которое предоставляет знакомые функции регистрации, такие как console.log().
Список добавленных функций:
console.assert()console.debug()console.exception()console.info()-
console.log()(эквивалентconsole.debug()) console.error()console.time()console.timeEnd()console.trace()console.count()console.warn()-
print()(эквивалентconsole.debug())
Дополнительную информацию см. в документации Console API.
GarbageCollectionExtension
Функция gc() эквивалентна вызову collectGarbage().
Тип Extensions — это typedef для QFlags<Extension>. Он хранит логическое ИЛИ комбинацию значений Extension.
Документация по функциям членов
QJSEngine::QJSEngine(QObject *parent)
Создает объект QJSEngine с заданным parent.
globalObject() инициализируется свойствами, описанными в ECMA-262, раздел 15.1.
QJSEngine::QJSEngine()
Создает объект QJSEngine.
globalObject() инициализируется свойствами, описанными в ECMA-262, раздел 15.1.
[override virtual] QJSEngine::~QJSEngine()
Удаляет этот QJSEngine.
Мусор из постоянной JS-кучи не собирается во время уничтожения QJSEngine. Если вам нужно освободить всю память, вызовите collectGarbage вручную перед уничтожением QJSEngine.
void QJSEngine::collectGarbage()
Выполняет сборщик мусора.
Сборщик мусора попытается вернуть память, обнаружив и удалив объекты, которые больше недоступны в среде скриптов.
Обычно вам не нужно вызывать эту функцию; сборщик мусора будет автоматически вызываться, когда QJSEngine сочтет это целесообразным (т. е. когда было создано определенное количество новых объектов). Однако вы можете вызвать эту функцию, чтобы явно запросить выполнение сбора мусора как можно скорее.
QJSValue QJSEngine::evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1)
Оценивает program, используя lineNumber в качестве базового номера строки, и возвращает результат оценки.
Код скрипта будет оцениваться в контексте глобального объекта.
Оценивание program может вызвать исключение исключение в движке; в этом случае возвращаемое значение будет исключением, которое было выброшено (обычно объект Error; см. QJSValue::isError()).
lineNumber используется для указания начального номера строки для program; информация о номере строки, предоставляемая движком, относящаяся к этой оценке, будет основана на этом аргументе. Например, если program состоит из двух строк кода, и оператор на второй строке вызывает исключение скрипта, номер строки исключения будет lineNumber плюс один. При отсутствии начального номера строки номера строк будут 1-основанными.
fileName используется для отладки ошибок. Например, в объектах ошибок имя файла доступно через свойство «fileName», если оно указано в этой функции.
Примечание: Если было выброшено исключение, и значение исключения не является экземпляром Error (т. е. QJSValue::isError() возвращает false), значение исключения всё равно будет возвращено, но в настоящее время нет API для обнаружения того, что исключение произошло в этом случае.
T QJSEngine::fromScriptValue(const QJSValue &value)
Возвращает заданное value, преобразованное к типу шаблона T.
См. также toScriptValue().
QJSValue QJSEngine::globalObject() const
Возвращает глобальный объект этого движка.
По умолчанию глобальный объект содержит встроенные объекты, которые являются частью ECMA-262, такие как Math, Date и String. Кроме того, вы можете установить свойства глобального объекта, чтобы сделать свои расширения доступными для всего кода скрипта. Нелокальные переменные в коде скрипта будут созданы как свойства глобального объекта, а также локальные переменные в глобальном коде.
QJSValue QJSEngine::importModule(const QString &fileName)
Импортирует модуль, расположенный по адресу fileName, и возвращает объект пространства имен модуля, который содержит все экспортированные переменные, константы и функции в качестве свойств.
Если этот модуль импортируется в движок впервые, файл загружается из указанного расположения в локальной файловой системе или системе ресурсов Qt и оценивается как модуль ECMAScript. Ожидается, что файл будет закодирован в формате UTF-8.
Последующие импорты того же модуля вернут ранее импортированный экземпляр. Модули являются синглетонами и сохраняются до тех пор, пока не будет уничтожен движок.
Указанное fileName внутри будет нормализовано с помощью QFileInfo::canonicalFilePath(). Это означает, что несколько импортов одного файла на диске с использованием различных относительных путей загрузит файл только один раз.
Примечание: Если при загрузке модуля было выброшено исключение, возвращаемое значение будет исключением (обычно объект Error; см. QJSValue::isError()).
Эта функция была добавлена в Qt 5.12.
void QJSEngine::installExtensions(QJSEngine::Extensions extensions, const QJSValue &object = QJSValue())
Устанавливает JavaScript-расширения для добавления функциональности, которая недоступна в стандартной реализации ECMAScript.
Расширения устанавливаются на указанный object или на глобальный объект, если объект не указан.
Несколько расширений можно установить одновременно, используя логическое ИЛИ для значений перечисления:
installExtensions(QJSEngine::TranslationExtension | QJSEngine::ConsoleExtension);
Эта функция была добавлена в Qt 5.6.
См. также Extension.
bool QJSEngine::isInterrupted() const
Возвращает значение, указывающее, прервано ли выполнение JavaScript.
Данная функция была добавлена в Qt 5.14.
См. также setInterrupted().
QJSValue QJSEngine::newArray(uint length = 0)
Создаёт объект JavaScript класса Array с заданной length.
См. также newObject().
QJSValue QJSEngine::newErrorObject(QJSValue::ErrorType errorType, const QString &message = QString())
Создаёт объект JavaScript класса Error с сообщением об ошибке message.
Прототипом созданного объекта будет errorType.
Данная функция была добавлена в Qt 5.12.
См. также newObject(), throwError() и QJSValue::isError().
QJSValue QJSEngine::newObject()
Создаёт объект JavaScript класса Object.
Прототипом созданного объекта будет прототип объекта Object.
См. также newArray() и QJSValue::setProperty().
QJSValue QJSEngine::newQMetaObject(const QMetaObject *metaObject)
Создаёт объект JavaScript, оборачивающий заданный QMetaObject. metaObject должен существовать дольше, чем движок сценария. Рекомендуется использовать только со статическими метаобъектами.
При вызове в качестве конструктора, будет создан новый экземпляр класса. Только конструкторы, экспонированные с помощью Q_INVOKABLE, будут видны из движка сценария.
Данная функция была добавлена в Qt 5.8.
См. также newQObject() и Интеграция QObject.
QJSValue QJSEngine::newQMetaObject()
Создаёт объект JavaScript, оборачивающий статический QMetaObject, ассоциированный с классом T.
Данная функция была добавлена в Qt 5.8.
См. также newQObject() и Интеграция QObject.
QJSValue QJSEngine::newQObject(QObject *object)
Создаёт объект JavaScript, оборачивающий заданный QObject object, используя JavaScriptOwnership.
Сигналы и слоты, свойства и дочерние элементы object доступны как свойства созданного QJSValue.
Если object равен null, эта функция возвращает значение null.
Если для класса object (или его суперкласса, рекурсивно) зарегистрирован прототип по умолчанию, прототип нового объекта сценария будет установлен на этот прототип по умолчанию.
Если заданный object удалён вне управления движка, любая попытка доступа к членам удалённого QObject через объект обертки JavaScript (в коде сценария или C++) приведёт к исключению сценария.
См. также QJSValue::toQObject().
void QJSEngine::setInterrupted(bool interrupted)
Прерывает или возобновляет выполнение JavaScript.
Если interrupted равно true, любое выполнение JavaScript этим движком немедленно прерывается и возвращает объект ошибки, пока эта функция не будет вызвана снова со значением false для interrupted.
Данная функция потокобезопасна. Вы можете вызвать её из другого потока, чтобы, например, прервать бесконечный цикл в JavaScript.
Данная функция была добавлена в Qt 5.14.
См. также isInterrupted().
void QJSEngine::throwError(const QString &message)
Выбрасывает ошибку выполнения (исключение) с заданным сообщением message.
Этот метод является аналогом выражения throw() в JavaScript. Он позволяет коду C++ сообщать об ошибках выполнения движку QJSEngine. Поэтому его следует вызывать только из кода C++, который был вызван функцией JavaScript через QJSEngine.
При возвращении из C++, движок прервёт обычный поток выполнения и вызовет следующий зарегистрированный обработчик исключений с объектом ошибки, содержащим заданное message. Объект ошибки укажет на расположение самого верхнего контекста в стеке вызовов JavaScript; в частности, он будет иметь свойства lineNumber, fileName и stack. Эти свойства описаны в Исключения сценария.
В следующем примере метод C++ в FileAccess.cpp выбросит ошибку в qmlFile.qml в позиции, где вызывается readFileAsText().
// qmlFile.qml
function someFunction() {
...
var text = FileAccess.readFileAsText("/path/to/file.txt");
} // FileAccess.cpp
// Assuming that FileAccess is a QObject-derived class that has been
// registered as a singleton type and provides an invokable method
// readFileAsText()
QJSValue FileAccess::readFileAsText(const QString & filePath) {
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
jsEngine->throwError(file.errorString());
return QString();
}
...
return content;
} Также возможно перехватить выброшенную ошибку в JavaScript:
// qmlFile.qml
function someFunction() {
...
var text;
try {
text = FileAccess.readFileAsText("/path/to/file.txt");
} catch (error) {
console.warn("In " + error.fileName + ":" + "error.lineNumber" +
": " + error.message);
}
} Если вам нужна более специфичная ошибка выполнения для описания исключения, вы можете использовать перегрузку throwError(QJSValue::ErrorType errorType, const QString &message).
Данная функция была добавлена в Qt 5.12.
См. также Исключения сценария.
void QJSEngine::throwError(QJSValue::ErrorType errorType, const QString &message = QString())
Эта функция перегружает throwError().
Выбрасывает ошибку выполнения (исключение) с заданным errorType и message.
// Assuming that DataEntry is a QObject-derived class that has been
// registered as a singleton type and provides an invokable method
// setAge().
void DataEntry::setAge(int age) {
if (age < 0 || age > 200) {
jsEngine->throwError(QJSValue::RangeError,
"Age must be between 0 and 200");
}
...
} Данная функция была добавлена в Qt 5.12.
См. также Исключения сценария и newErrorObject().
QJSValue QJSEngine::toScriptValue(const T &value)
Создаёт QJSValue с заданным value.
См. также fromScriptValue().
Связанные нечлены
QJSEngine *qjsEngine(const QObject *object)
Возвращает QJSEngine, связанный с object, если таковой имеется.
Эта функция полезна, если вы экспонировали QObject в среде JavaScript и позднее в вашей программе хотите получить к нему доступ. Она не требует сохранения обертки, возвращённой из QJSEngine::newQObject().
Данная функция была добавлена в Qt 5.5.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.14/qjsengine.html