History

working to clean up the QtScript implementation and move towards completion of the proxy interface

Heather Anderson committed 5 years ago

Commit 2dd9d781 parent 1e018db38 files · +2240 −923Browse files

Showing the changes to libraries/script-engine/src/qtscript/ScriptEngineQtScript.h (1 of 38 files). Show all

Unified · Split

libraries/script-engine/src/qtscript/ScriptEngineQtScript.h+469−0
@@ -0,0 +1,469 @@
1+//
2+// ScriptEngineQtScript.h
3+// libraries/script-engine-qtscript/src
4+//
5+// Created by Brad Hefta-Gaub on 12/14/13.
6+// Copyright 2013 High Fidelity, Inc.
7+// Copyright 2020 Vircadia contributors.
8+//
9+// Distributed under the Apache License, Version 2.0.
10+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11+//
12+
13+#ifndef hifi_ScriptEngineQtScript_h
14+#define hifi_ScriptEngineQtScript_h
15+
16+#include <QtCore/QByteArray>
17+#include <QtCore/QEnableSharedFromThis>
18+#include <QtCore/QMetaEnum>
19+#include <QtCore/QObject>
20+#include <QtCore/QPointer>
21+#include <QtCore/QSharedPointer>
22+#include <QtCore/QString>
23+
24+#include <QtScript/QScriptEngine>
25+#include <QtScriptTools/QScriptEngineDebugger>
26+
27+#include "../ScriptEngine.h"
28+#include "../ScriptManager.h"
29+
30+#include "ArrayBufferClass.h"
31+
32+class ScriptContextQtWrapper;
33+class ScriptEngineQtScript;
34+class ScriptManager;
35+using ScriptEngineQtScriptPointer = QSharedPointer<ScriptEngineQtScript>;
36+using ScriptContextQtPointer = QSharedPointer<ScriptContextQtWrapper>;
37+
38+Q_DECLARE_METATYPE(ScriptEngineQtScriptPointer)
39+
40+/**jsdoc
41+ * The <code>Script</code> API provides facilities for working with scripts.
42+ *
43+ * @namespace Script
44+ *
45+ * @hifi-interface
46+ * @hifi-client-entity
47+ * @hifi-avatar
48+ * @hifi-server-entity
49+ * @hifi-assignment-client
50+ *
51+ * @property {string} context - The context that the script is running in:
52+ * <ul>
53+ * <li><code>"client"</code>: An Interface or avatar script.</li>
54+ * <li><code>"entity_client"</code>: A client entity script.</li>
55+ * <li><code>"entity_server"</code>: A server entity script.</li>
56+ * <li><code>"agent"</code>: An assignment client script.</li>
57+ * </ul>
58+ * <em>Read-only.</em>
59+ * @property {string} type - The type of script that is running:
60+ * <ul>
61+ * <li><code>"client"</code>: An Interface script.</li>
62+ * <li><code>"entity_client"</code>: A client entity script.</li>
63+ * <li><code>"avatar"</code>: An avatar script.</li>
64+ * <li><code>"entity_server"</code>: A server entity script.</li>
65+ * <li><code>"agent"</code>: An assignment client script.</li>
66+ * </ul>
67+ * <em>Read-only.</em>
68+ * @property {string} filename - The filename of the script file.
69+ * <em>Read-only.</em>
70+ * @property {Script.ResourceBuckets} ExternalPaths - External resource buckets.
71+ */
72+class ScriptEngineQtScript : public QScriptEngine, public ScriptEngine, public QEnableSharedFromThis<ScriptEngineQtScript> {
73+ Q_OBJECT
74+
75+public: // ScriptEngine implementation
76+ virtual void abortEvaluation();
77+ virtual void clearExceptions();
78+ virtual ScriptValuePointer cloneUncaughtException(const QString& detail = QString());
79+ virtual ScriptContext* currentContext() const;
80+ //virtual ScriptValuePointer evaluate(const QString& program, const QString& fileName = QString());
81+ //virtual ScriptValuePointer evaluate(const ScriptProgramPointer &program);
82+ //virtual ScriptValuePointer evaluateInClosure(const ScriptValuePointer& locals, const ScriptProgramPointer& program);
83+ virtual ScriptValuePointer globalObject() const;
84+ virtual bool hasUncaughtException() const;
85+ virtual bool isEvaluating() const;
86+ virtual ScriptValuePointer lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1);
87+ virtual ScriptValuePointer makeError(const ScriptValuePointer& other, const QString& type = "Error");
88+ virtual ScriptManager* manager() const;
89+
90+ // if there is a pending exception and we are at the top level (non-recursive) stack frame, this emits and resets it
91+ virtual bool maybeEmitUncaughtException(const QString& debugHint = QString());
92+
93+ virtual ScriptValuePointer newArray(uint length = 0);
94+ virtual ScriptValuePointer newArrayBuffer(const QByteArray& message);
95+ virtual ScriptValuePointer newFunction(ScriptEngine::FunctionSignature fun, int length = 0);
96+ virtual ScriptValuePointer newObject();
97+ virtual ScriptProgramPointer newProgram(const QString& sourceCode, const QString& fileName);
98+ virtual ScriptValuePointer newQObject(QObject *object, ScriptEngine::ValueOwnership ownership = ScriptEngine::QtOwnership,
99+ const ScriptEngine::QObjectWrapOptions &options = ScriptEngine::QObjectWrapOptions());
100+ virtual ScriptValuePointer newValue(bool value);
101+ virtual ScriptValuePointer newValue(int value);
102+ virtual ScriptValuePointer newValue(uint value);
103+ virtual ScriptValuePointer newValue(double value);
104+ virtual ScriptValuePointer newValue(const QString& value);
105+ virtual ScriptValuePointer newValue(const QLatin1String& value);
106+ virtual ScriptValuePointer newValue(const char* value);
107+ virtual ScriptValuePointer newVariant(const QVariant& value);
108+ virtual ScriptValuePointer nullValue();
109+ virtual bool raiseException(const ScriptValuePointer& exception);
110+ //virtual void registerEnum(const QString& enumName, QMetaEnum newEnum);
111+ //Q_INVOKABLE virtual void registerFunction(const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
112+ //Q_INVOKABLE virtual void registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
113+ //Q_INVOKABLE virtual void registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, ScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
114+ //virtual void registerGlobalObject(const QString& name, QObject* object);
115+ virtual void setDefaultPrototype(int metaTypeId, const ScriptValuePointer& prototype);
116+ virtual void setObjectName(const QString& name);
117+ virtual bool setProperty(const char* name, const QVariant& value);
118+ virtual void setProcessEventsInterval(int interval);
119+ virtual QThread* thread() const;
120+ virtual ScriptValuePointer undefinedValue();
121+ virtual ScriptValuePointer uncaughtException() const;
122+ virtual QStringList uncaughtExceptionBacktrace() const;
123+ virtual int uncaughtExceptionLineNumber() const;
124+
125+ // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
126+ inline bool IS_THREADSAFE_INVOCATION(const QString& method) { return ScriptEngine::IS_THREADSAFE_INVOCATION(method); }
127+
128+protected: // brought over from BaseScriptEngine
129+ /**jsdoc
130+ * @function Script.makeError
131+ * @param {object} [other] - Other.
132+ * @param {string} [type="Error"] - Error.
133+ * @returns {object} Object.
134+ * @deprecated This function is deprecated and will be removed.
135+ */
136+ Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error");
137+
138+ // if the currentContext() is valid then throw the passed exception; otherwise, immediately emit it.
139+ // note: this is used in cases where C++ code might call into JS API methods directly
140+ bool raiseException(const QScriptValue& exception);
141+
142+ // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
143+ static bool IS_THREADSAFE_INVOCATION(const QThread* thread, const QString& method);
144+
145+public:
146+ ScriptEngineQtScript(ScriptManager* scriptManager = nullptr);
147+ ~ScriptEngineQtScript();
148+
149+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150+ // NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can
151+ // properly ensure they are only called on the correct thread
152+
153+ /**jsdoc
154+ * @function Script.registerGlobalObject
155+ * @param {string} name - Name.
156+ * @param {object} object - Object.
157+ * @deprecated This function is deprecated and will be removed.
158+ */
159+ /// registers a global object by name
160+ Q_INVOKABLE virtual void registerGlobalObject(const QString& name, QObject* object);
161+
162+ /**jsdoc
163+ * @function Script.registerGetterSetter
164+ * @param {string} name - Name.
165+ * @param {function} getter - Getter.
166+ * @param {function} setter - Setter.
167+ * @param {string} [parent=""] - Parent.
168+ * @deprecated This function is deprecated and will be removed.
169+ */
170+ /// registers a global getter/setter
171+ Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
172+ QScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
173+
174+ Q_INVOKABLE virtual void registerGetterSetter(const QString& name, ScriptEngine::FunctionSignature getter, ScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
175+
176+ /**jsdoc
177+ * @function Script.registerFunction
178+ * @param {string} name - Name.
179+ * @param {function} function - Function.
180+ * @param {number} [numArguments=-1] - Number of arguments.
181+ * @deprecated This function is deprecated and will be removed.
182+ */
183+ /// register a global function
184+ Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
185+
186+
187+ Q_INVOKABLE virtual void registerFunction(const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
188+
189+ /**jsdoc
190+ * @function Script.registerFunction
191+ * @param {string} parent - Parent.
192+ * @param {string} name - Name.
193+ * @param {function} function - Function.
194+ * @param {number} [numArguments=-1] - Number of arguments.
195+ * @deprecated This function is deprecated and will be removed.
196+ */
197+ /// register a function as a method on a previously registered global object
198+ Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
199+ int numArguments = -1);
200+
201+
202+ Q_INVOKABLE virtual void registerFunction(const QString& parent, const QString& name, ScriptEngine::FunctionSignature fun, int numArguments = -1);
203+
204+ /**jsdoc
205+ * @function Script.registerEnum
206+ * @param {string} name - Name.
207+ * @param {object} enum - Enum.
208+ * @deprecated This function is deprecated and will be removed.
209+ */
210+ // WARNING: This function must be called after a registerGlobalObject that creates the namespace this enum is located in, or
211+ // the globalObject won't function. E.g., if you have a Foo object and a Foo.FooType enum, Foo must be registered first.
212+ /// registers a global enum
213+ Q_INVOKABLE virtual void registerEnum(const QString& enumName, QMetaEnum newEnum);
214+
215+ /**jsdoc
216+ * @function Script.registerValue
217+ * @param {string} name - Name.
218+ * @param {object} value - Value.
219+ * @deprecated This function is deprecated and will be removed.
220+ */
221+ /// registers a global object by name
222+ Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value);
223+
224+ /**jsdoc
225+ * @function Script.evaluate
226+ * @param {string} program - Program.
227+ * @param {string} filename - File name.
228+ * @param {number} [lineNumber=-1] - Line number.
229+ * @returns {object} Object.
230+ * @deprecated This function is deprecated and will be removed.
231+ */
232+ /// evaluate some code in the context of the ScriptEngineQtScript and return the result
233+ Q_INVOKABLE virtual ScriptValuePointer evaluate(const QString& program, const QString& fileName); // this is also used by the script tool widget
234+
235+
236+ Q_INVOKABLE virtual ScriptValuePointer evaluate(const ScriptProgramPointer& program);
237+
238+ /**jsdoc
239+ * @function Script.evaluateInClosure
240+ * @param {object} locals - Locals.
241+ * @param {object} program - Program.
242+ * @returns {object} Object.
243+ * @deprecated This function is deprecated and will be removed.
244+ */
245+ Q_INVOKABLE virtual ScriptValuePointer evaluateInClosure(const ScriptValuePointer& locals, const ScriptProgramPointer& program);
246+
247+ /**jsdoc
248+ * Checks whether the application was compiled as a debug build.
249+ * @function Script.isDebugMode
250+ * @returns {boolean} <code>true</code> if the application was compiled as a debug build, <code>false</code> if it was
251+ * compiled as a release build.
252+ */
253+ Q_INVOKABLE bool isDebugMode() const;
254+
255+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
256+ // MODULE related methods
257+
258+ /**jsdoc
259+ * Prints a message to the program log and emits {@link Script.printedMessage}.
260+ * <p>Alternatively, you can use {@link print} or one of the {@link console} API methods.</p>
261+ * @function Script.print
262+ * @param {string} message - The message to print.
263+ */
264+ Q_INVOKABLE void print(const QString& message);
265+
266+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
267+ // Entity Script Related methods
268+
269+ /**jsdoc
270+ * Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer
271+ * reachable.
272+ * @function Script.requestGarbageCollection
273+ */
274+ Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); }
275+
276+ bool isRunning() const { return _isRunning; } // used by ScriptWidget
277+
278+ bool isDebuggable() const { return _debuggable; }
279+
280+ void disconnectNonEssentialSignals();
281+
282+ // NOTE - this is used by the TypedArray implementation. we need to review this for thread safety
283+ ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; }
284+
285+ /**jsdoc
286+ * @function Script.updateMemoryCost
287+ * @param {number} deltaSize - Delta size.
288+ * @deprecated This function is deprecated and will be removed.
289+ */
290+ virtual void updateMemoryCost(const qint64& deltaSize);
291+
292+signals:
293+
294+ /**jsdoc
295+ * Triggered frequently at a system-determined interval.
296+ * @function Script.update
297+ * @param {number} deltaTime - The time since the last update, in s.
298+ * @returns {Signal}
299+ * @example <caption>Report script update intervals.</caption>
300+ * Script.update.connect(function (deltaTime) {
301+ * print("Update: " + deltaTime);
302+ * });
303+ */
304+ void update(float deltaTime);
305+
306+ /**jsdoc
307+ * @function Script.finished
308+ * @param {string} filename - File name.
309+ * @param {object} engine - Engine.
310+ * @returns {Signal}
311+ * @deprecated This signal is deprecated and will be removed.
312+ */
313+ void finished(const QString& fileNameString, ScriptEngineQtScriptPointer);
314+
315+ /**jsdoc
316+ * @function Script.cleanupMenuItem
317+ * @param {string} menuItem - Menu item.
318+ * @returns {Signal}
319+ * @deprecated This signal is deprecated and will be removed.
320+ */
321+ void cleanupMenuItem(const QString& menuItemString);
322+
323+ /**jsdoc
324+ * Triggered when the script prints a message to the program log via {@link print}, {@link Script.print},
325+ * {@link console.log}, {@link console.debug}, {@link console.group}, {@link console.groupEnd}, {@link console.time}, or
326+ * {@link console.timeEnd}.
327+ * @function Script.printedMessage
328+ * @param {string} message - The message.
329+ * @param {string} scriptName - The name of the script that generated the message.
330+ * @returns {Signal}
331+ */
332+ void printedMessage(const QString& message, const QString& scriptName);
333+
334+ /**jsdoc
335+ * Triggered when the script generates an error, {@link console.error} or {@link console.exception} is called, or
336+ * {@link console.assert} is called and fails.
337+ * @function Script.errorMessage
338+ * @param {string} message - The error message.
339+ * @param {string} scriptName - The name of the script that generated the error message.
340+ * @returns {Signal}
341+ */
342+ void errorMessage(const QString& message, const QString& scriptName);
343+
344+ /**jsdoc
345+ * Triggered when the script generates a warning or {@link console.warn} is called.
346+ * @function Script.warningMessage
347+ * @param {string} message - The warning message.
348+ * @param {string} scriptName - The name of the script that generated the warning message.
349+ * @returns {Signal}
350+ */
351+ void warningMessage(const QString& message, const QString& scriptName);
352+
353+ /**jsdoc
354+ * Triggered when the script generates an information message or {@link console.info} is called.
355+ * @function Script.infoMessage
356+ * @param {string} message - The information message.
357+ * @param {string} scriptName - The name of the script that generated the information message.
358+ * @returns {Signal}
359+ */
360+ void infoMessage(const QString& message, const QString& scriptName);
361+
362+ /**jsdoc
363+ * Triggered when the running state of the script changes, e.g., from running to stopping.
364+ * @function Script.runningStateChanged
365+ * @returns {Signal}
366+ */
367+ void runningStateChanged();
368+
369+ /**jsdoc
370+ * @function Script.clearDebugWindow
371+ * @returns {Signal}
372+ * @deprecated This signal is deprecated and will be removed.
373+ */
374+ void clearDebugWindow();
375+
376+ /**jsdoc
377+ * @function Script.loadScript
378+ * @param {string} scriptName - Script name.
379+ * @param {boolean} isUserLoaded - Is user loaded.
380+ * @returns {Signal}
381+ * @deprecated This signal is deprecated and will be removed.
382+ */
383+ void loadScript(const QString& scriptName, bool isUserLoaded);
384+
385+ /**jsdoc
386+ * @function Script.reloadScript
387+ * @param {string} scriptName - Script name.
388+ * @param {boolean} isUserLoaded - Is user loaded.
389+ * @returns {Signal}
390+ * @deprecated This signal is deprecated and will be removed.
391+ */
392+ void reloadScript(const QString& scriptName, bool isUserLoaded);
393+
394+ /**jsdoc
395+ * Triggered when the script has stopped.
396+ * @function Script.doneRunning
397+ * @returns {Signal}
398+ */
399+ void doneRunning();
400+
401+ /**jsdoc
402+ * @function Script.entityScriptDetailsUpdated
403+ * @returns {Signal}
404+ * @deprecated This signal is deprecated and will be removed.
405+ */
406+ // Emitted when an entity script is added or removed, or when the status of an entity
407+ // script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example)
408+ void entityScriptDetailsUpdated();
409+
410+public: // not for public use, but I don't like how Qt strings this along with private friend functions
411+ virtual ScriptValuePointer create(int type, const void* ptr);
412+ virtual bool convert(const ScriptValuePointer& value, int type, void* ptr);
413+ virtual void registerCustomType(int type, ScriptEngine::MarshalFunction mf, ScriptEngine::DemarshalFunction df, const ScriptValuePointer& prototype);
414+
415+protected:
416+ // like `newFunction`, but allows mapping inline C++ lambdas with captures as callable QScriptValues
417+ // even though the context/engine parameters are redundant in most cases, the function signature matches `newFunction`
418+ // anyway so that newLambdaFunction can be used to rapidly prototype / test utility APIs and then if becoming
419+ // permanent more easily promoted into regular static newFunction scenarios.
420+ QScriptValue newLambdaFunction(std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation,
421+ const QScriptValue& data = QScriptValue(),
422+ const QScriptEngine::ValueOwnership& ownership = QScriptEngine::AutoOwnership);
423+
424+protected:
425+
426+ /**jsdoc
427+ * @function Script.executeOnScriptThread
428+ * @param {function} function - Function.
429+ * @param {ConnectionType} [type=2] - Connection type.
430+ * @deprecated This function is deprecated and will be removed.
431+ */
432+ Q_INVOKABLE void executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type = Qt::QueuedConnection );
433+
434+ QPointer<ScriptManager> _manager;
435+
436+ ScriptValuePointer _nullValue;
437+ ScriptValuePointer _undefinedValue;
438+ mutable ScriptContextQtPointer _currContext;
439+
440+ std::atomic<bool> _isRunning { false };
441+
442+ bool _isThreaded { false };
443+ QScriptEngineDebugger* _debugger { nullptr };
444+ bool _debuggable { false };
445+ qint64 _lastUpdate;
446+
447+ ArrayBufferClass* _arrayBufferClass;
448+};
449+
450+// Lambda helps create callable QScriptValues out of std::functions:
451+// (just meant for use from within the script engine itself)
452+class Lambda : public QObject {
453+ Q_OBJECT
454+public:
455+ Lambda(ScriptEngineQtScript* engine,
456+ std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation,
457+ QScriptValue data);
458+ ~Lambda();
459+public slots:
460+ QScriptValue call();
461+ QString toString() const;
462+
463+private:
464+ ScriptEngineQtScript* engine;
465+ std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation;
466+ QScriptValue data;
467+};
468+
469+#endif // hifi_ScriptEngineQtScript_h

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