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
32class ScriptContextQtWrapper;
33class ScriptEngineQtScript;
34class ScriptManager;
35using ScriptEngineQtScriptPointer = QSharedPointer<ScriptEngineQtScript>;
36using ScriptContextQtPointer = QSharedPointer<ScriptContextQtWrapper>;
37
38Q_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 */
72class ScriptEngineQtScript : public QScriptEngine, public ScriptEngine, public QEnableSharedFromThis<ScriptEngineQtScript> {
73 Q_OBJECT
74
75public: // 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
128protected: // 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
145public:
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
292signals:
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
410public: // 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
415protected:
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
424protected:
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)
452class Lambda : public QObject {
453 Q_OBJECT
454public:
455 Lambda(ScriptEngineQtScript* engine,
456 std::function<QScriptValue(QScriptContext* context, ScriptEngineQtScript* engine)> operation,
457 QScriptValue data);
458 ~Lambda();
459public slots:
460 QScriptValue call();
461 QString toString() const;
462
463private:
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