source: trunk/src/script/api/qscriptengine.cpp@ 618

Last change on this file since 618 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 133.7 KB
RevLine 
[556]1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtScript module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL-ONLY$
10** GNU Lesser General Public License Usage
11** This file may be used under the terms of the GNU Lesser
12** General Public License version 2.1 as published by the Free Software
13** Foundation and appearing in the file LICENSE.LGPL included in the
14** packaging of this file. Please review the following information to
15** ensure the GNU Lesser General Public License version 2.1 requirements
16** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17**
18** If you have questions regarding the use of this file, please contact
19** Nokia at [email protected].
20** $QT_END_LICENSE$
21**
22****************************************************************************/
23
24#include "config.h"
25#include "qscriptengine.h"
26#include "qscriptsyntaxchecker_p.h"
27#include "qnumeric.h"
28
29#include "qscriptengine_p.h"
30#include "qscriptengineagent_p.h"
31#include "qscriptcontext_p.h"
32#include "qscriptstring_p.h"
33#include "qscriptvalue_p.h"
34#include "qscriptvalueiterator.h"
35#include "qscriptclass.h"
36#include "qscriptcontextinfo.h"
37#include "qscriptprogram.h"
38#include "qscriptprogram_p.h"
39#include "qdebug.h"
40
41#include <QtCore/qstringlist.h>
42#include <QtCore/qmetaobject.h>
43
44#include "Error.h"
45#include "JSArray.h"
46#include "JSLock.h"
47#include "Interpreter.h"
48#include "DateConstructor.h"
49#include "RegExpConstructor.h"
50
51#include "PrototypeFunction.h"
52#include "InitializeThreading.h"
53#include "ObjectPrototype.h"
54#include "SourceCode.h"
55#include "FunctionPrototype.h"
56#include "TimeoutChecker.h"
57#include "JSFunction.h"
58#include "Parser.h"
59#include "Operations.h"
60
61#include "utils/qscriptdate_p.h"
62#include "bridge/qscriptfunction_p.h"
63#include "bridge/qscriptobject_p.h"
64#include "bridge/qscriptclassobject_p.h"
65#include "bridge/qscriptvariant_p.h"
66#include "bridge/qscriptqobject_p.h"
67#include "bridge/qscriptglobalobject_p.h"
68#include "bridge/qscriptactivationobject_p.h"
69
70#ifndef QT_NO_QOBJECT
71#include <QtCore/qcoreapplication.h>
72#include <QtCore/qdir.h>
73#include <QtCore/qfile.h>
74#include <QtCore/qfileinfo.h>
75#include <QtCore/qpluginloader.h>
76#include <QtCore/qset.h>
77#include <QtCore/qtextstream.h>
78#include "qscriptextensioninterface.h"
79#endif
80
81Q_DECLARE_METATYPE(QScriptValue)
82#ifndef QT_NO_QOBJECT
83Q_DECLARE_METATYPE(QObjectList)
84#endif
85Q_DECLARE_METATYPE(QList<int>)
86
87QT_BEGIN_NAMESPACE
88
89/*!
90 \since 4.3
91 \class QScriptEngine
92 \reentrant
93
94 \brief The QScriptEngine class provides an environment for evaluating Qt Script code.
95
96 \ingroup script
97 \mainclass
98
99 See the \l{QtScript} documentation for information about the Qt Script language,
100 and how to get started with scripting your C++ application.
101
102 \section1 Evaluating Scripts
103
104 Use evaluate() to evaluate script code; this is the C++ equivalent
105 of the built-in script function \c{eval()}.
106
107 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 0
108
109 evaluate() returns a QScriptValue that holds the result of the
110 evaluation. The QScriptValue class provides functions for converting
111 the result to various C++ types (e.g. QScriptValue::toString()
112 and QScriptValue::toNumber()).
113
114 The following code snippet shows how a script function can be
115 defined and then invoked from C++ using QScriptValue::call():
116
117 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 1
118
119 As can be seen from the above snippets, a script is provided to the
120 engine in the form of a string. One common way of loading scripts is
121 by reading the contents of a file and passing it to evaluate():
122
123 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 2
124
125 Here we pass the name of the file as the second argument to
126 evaluate(). This does not affect evaluation in any way; the second
127 argument is a general-purpose string that is used to identify the
128 script for debugging purposes (for example, our filename will now
129 show up in any uncaughtExceptionBacktrace() involving the script).
130
131 \section1 Engine Configuration
132
133 The globalObject() function returns the \bold {Global Object}
134 associated with the script engine. Properties of the Global Object
135 are accessible from any script code (i.e. they are global
136 variables). Typically, before evaluating "user" scripts, you will
137 want to configure a script engine by adding one or more properties
138 to the Global Object:
139
140 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 3
141
142 Adding custom properties to the scripting environment is one of the
143 standard means of providing a scripting API that is specific to your
144 application. Usually these custom properties are objects created by
145 the newQObject() or newObject() functions, or constructor functions
146 created by newFunction().
147
148 \section1 Script Exceptions
149
150 evaluate() can throw a script exception (e.g. due to a syntax
151 error); in that case, the return value is the value that was thrown
152 (typically an \c{Error} object). You can check whether the
153 evaluation caused an exception by calling hasUncaughtException(). In
154 that case, you can call toString() on the error object to obtain an
155 error message. The current uncaught exception is also available
156 through uncaughtException(). You can obtain a human-readable
157 backtrace of the exception with uncaughtExceptionBacktrace().
158 Calling clearExceptions() will cause any uncaught exceptions to be
159 cleared.
160
161 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4
162
163 The checkSyntax() function can be used to determine whether code can be
164 usefully passed to evaluate().
165
166 \section1 Script Object Creation
167
168 Use newObject() to create a standard Qt Script object; this is the
169 C++ equivalent of the script statement \c{new Object()}. You can use
170 the object-specific functionality in QScriptValue to manipulate the
171 script object (e.g. QScriptValue::setProperty()). Similarly, use
172 newArray() to create a Qt Script array object. Use newDate() to
173 create a \c{Date} object, and newRegExp() to create a \c{RegExp}
174 object.
175
176 \section1 QObject Integration
177
178 Use newQObject() to wrap a QObject (or subclass)
179 pointer. newQObject() returns a proxy script object; properties,
180 children, and signals and slots of the QObject are available as
181 properties of the proxy object. No binding code is needed because it
182 is done dynamically using the Qt meta object system.
183
184 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 5
185
186 Use qScriptConnect() to connect a C++ signal to a script function;
187 this is the Qt Script equivalent of QObject::connect(). When a
188 script function is invoked in response to a C++ signal, it can cause
189 a script exception; you can connect to the signalHandlerException()
190 signal to catch such an exception.
191
192 Use newQMetaObject() to wrap a QMetaObject; this gives you a "script
193 representation" of a QObject-based class. newQMetaObject() returns a
194 proxy script object; enum values of the class are available as
195 properties of the proxy object. You can also specify a function that
196 will be used to construct objects of the class (e.g. when the
197 constructor is invoked from a script). For classes that have a
198 "standard" Qt constructor, Qt Script can provide a default script
199 constructor for you; see scriptValueFromQMetaObject().
200
201 See the \l{QtScript} documentation for more information on
202 the QObject integration.
203
204 \section1 Support for Custom C++ Types
205
206 Use newVariant() to wrap a QVariant. This can be used to store
207 values of custom (non-QObject) C++ types that have been registered
208 with the Qt meta-type system. To make such types scriptable, you
209 typically associate a prototype (delegate) object with the C++ type
210 by calling setDefaultPrototype(); the prototype object defines the
211 scripting API for the C++ type. Unlike the QObject integration,
212 there is no automatic binding possible here; i.e. you have to create
213 the scripting API yourself, for example by using the QScriptable
214 class.
215
216 Use fromScriptValue() to cast from a QScriptValue to another type,
217 and toScriptValue() to create a QScriptValue from another value.
218 You can specify how the conversion of C++ types is to be performed
219 with qScriptRegisterMetaType() and qScriptRegisterSequenceMetaType().
220 By default, Qt Script will use QVariant to store values of custom
221 types.
222
223 \section1 Importing Extensions
224
225 Use importExtension() to import plugin-based extensions into the
226 engine. Call availableExtensions() to obtain a list naming all the
227 available extensions, and importedExtensions() to obtain a list
228 naming only those extensions that have been imported.
229
230 Call pushContext() to open up a new variable scope, and popContext()
231 to close the current scope. This is useful if you are implementing
232 an extension that evaluates script code containing temporary
233 variable definitions (e.g. \c{var foo = 123;}) that are safe to
234 discard when evaluation has completed.
235
236 \section1 Native Functions
237
238 Use newFunction() to wrap native (C++) functions, including
239 constructors for your own custom types, so that these can be invoked
240 from script code. Such functions must have the signature
241 QScriptEngine::FunctionSignature. You may then pass the function as
242 argument to newFunction(). Here is an example of a function that
243 returns the sum of its first two arguments:
244
245 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 6
246
247 To expose this function to script code, you can set it as a property
248 of the Global Object:
249
250 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 7
251
252 Once this is done, script code can call your function in the exact
253 same manner as a "normal" script function:
254
255 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 8
256
257 \section1 Long-running Scripts
258
259 If you need to evaluate possibly long-running scripts from the main
260 (GUI) thread, you should first call setProcessEventsInterval() to
261 make sure that the GUI stays responsive. You can abort a currently
262 running script by calling abortEvaluation(). You can determine
263 whether an engine is currently running a script by calling
264 isEvaluating().
265
266 \section1 Core Debugging/Tracing Facilities
267
268 Since Qt 4.4, you can be notified of events pertaining to script
269 execution (e.g. script function calls and statement execution)
270 through the QScriptEngineAgent interface; see the setAgent()
271 function. This can be used to implement debugging and profiling of a
272 QScriptEngine.
273
274 \sa QScriptValue, QScriptContext, QScriptEngineAgent
275
276*/
277
278/*!
279 \enum QScriptEngine::ValueOwnership
280
281 This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject().
282
283 \value QtOwnership The standard Qt ownership rules apply, i.e. the associated object will never be explicitly deleted by the script engine. This is the default. (QObject ownership is explained in \l{Object Trees and Object Ownership}.)
284 \value ScriptOwnership The value is owned by the script environment. The associated data will be deleted when appropriate (i.e. after the garbage collector has discovered that there are no more live references to the value).
285 \value AutoOwnership If the associated object has a parent, the Qt ownership rules apply (QtOwnership); otherwise, the object is owned by the script environment (ScriptOwnership).
286*/
287
288/*!
289 \enum QScriptEngine::QObjectWrapOption
290
291 These flags specify options when wrapping a QObject pointer with newQObject().
292
293 \value ExcludeChildObjects The script object will not expose child objects as properties.
294 \value ExcludeSuperClassMethods The script object will not expose signals and slots inherited from the superclass.
295 \value ExcludeSuperClassProperties The script object will not expose properties inherited from the superclass.
296 \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties
297 \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot.
298 \value AutoCreateDynamicProperties Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object.
299 \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object.
300 \value SkipMethodsInEnumeration Don't include methods (signals and slots) when enumerating the object's properties.
301*/
302
303class QScriptSyntaxCheckResultPrivate
304{
305public:
306 QScriptSyntaxCheckResultPrivate() { ref = 0; }
307 ~QScriptSyntaxCheckResultPrivate() {}
308
309 QScriptSyntaxCheckResult::State state;
310 int errorColumnNumber;
311 int errorLineNumber;
312 QString errorMessage;
313 QBasicAtomicInt ref;
314};
315
316class QScriptTypeInfo
317{
318public:
319 QScriptTypeInfo() : signature(0, '\0'), marshal(0), demarshal(0)
320 { }
321
322 QByteArray signature;
323 QScriptEngine::MarshalFunction marshal;
324 QScriptEngine::DemarshalFunction demarshal;
325 JSC::JSValue prototype;
326};
327
328namespace QScript
329{
330
331void GlobalClientData::mark(JSC::MarkStack& markStack)
332{
333 engine->mark(markStack);
334}
335
336class TimeoutCheckerProxy : public JSC::TimeoutChecker
337{
338public:
339 TimeoutCheckerProxy(const JSC::TimeoutChecker& originalChecker)
340 : JSC::TimeoutChecker(originalChecker)
341 , m_shouldProcessEvents(false)
342 , m_shouldAbortEvaluation(false)
343 {}
344
345 void setShouldProcessEvents(bool shouldProcess) { m_shouldProcessEvents = shouldProcess; }
346 void setShouldAbort(bool shouldAbort) { m_shouldAbortEvaluation = shouldAbort; }
347 bool shouldAbort() { return m_shouldAbortEvaluation; }
348
349 virtual bool didTimeOut(JSC::ExecState* exec)
350 {
351 if (JSC::TimeoutChecker::didTimeOut(exec))
352 return true;
353
354 if (m_shouldProcessEvents)
355 QCoreApplication::processEvents();
356
357 return m_shouldAbortEvaluation;
358 }
359
360private:
361 bool m_shouldProcessEvents;
362 bool m_shouldAbortEvaluation;
363};
364
365static int toDigit(char c)
366{
367 if ((c >= '0') && (c <= '9'))
368 return c - '0';
369 else if ((c >= 'a') && (c <= 'z'))
370 return 10 + c - 'a';
371 else if ((c >= 'A') && (c <= 'Z'))
372 return 10 + c - 'A';
373 return -1;
374}
375
376qsreal integerFromString(const char *buf, int size, int radix)
377{
378 if (size == 0)
379 return qSNaN();
380
381 qsreal sign = 1.0;
382 int i = 0;
383 if (buf[0] == '+') {
384 ++i;
385 } else if (buf[0] == '-') {
386 sign = -1.0;
387 ++i;
388 }
389
390 if (((size-i) >= 2) && (buf[i] == '0')) {
391 if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
392 && (radix < 34)) {
393 if ((radix != 0) && (radix != 16))
394 return 0;
395 radix = 16;
396 i += 2;
397 } else {
398 if (radix == 0) {
399 radix = 8;
400 ++i;
401 }
402 }
403 } else if (radix == 0) {
404 radix = 10;
405 }
406
407 int j = i;
408 for ( ; i < size; ++i) {
409 int d = toDigit(buf[i]);
410 if ((d == -1) || (d >= radix))
411 break;
412 }
413 qsreal result;
414 if (j == i) {
415 if (!qstrcmp(buf, "Infinity"))
416 result = qInf();
417 else
418 result = qSNaN();
419 } else {
420 result = 0;
421 qsreal multiplier = 1;
422 for (--i ; i >= j; --i, multiplier *= radix)
423 result += toDigit(buf[i]) * multiplier;
424 }
425 result *= sign;
426 return result;
427}
428
429qsreal integerFromString(const QString &str, int radix)
430{
431 QByteArray ba = str.trimmed().toUtf8();
432 return integerFromString(ba.constData(), ba.size(), radix);
433}
434
435bool isFunction(JSC::JSValue value)
436{
437 if (!value || !value.isObject())
438 return false;
439 JSC::CallData callData;
440 return (JSC::asObject(value)->getCallData(callData) != JSC::CallTypeNone);
441}
442
443static JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
444static JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
445
446JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
447{
448#ifndef QT_NO_QOBJECT
449 if (args.size() == 0) {
450 return JSC::throwError(exec, JSC::GeneralError, "Function.prototype.disconnect: no arguments given");
451 }
452
453 if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
454 return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: this object is not a signal");
455 }
456
457 QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
458
459 const QMetaObject *meta = qtSignal->metaObject();
460 if (!meta) {
461 return JSC::throwError(exec, JSC::TypeError, "Function.prototype.discconnect: cannot disconnect from deleted QObject");
462 }
463
464 QMetaMethod sig = meta->method(qtSignal->initialIndex());
465 if (sig.methodType() != QMetaMethod::Signal) {
466 QString message = QString::fromLatin1("Function.prototype.disconnect: %0::%1 is not a signal")
467 .arg(QLatin1String(qtSignal->metaObject()->className()))
468 .arg(QLatin1String(sig.signature()));
469 return JSC::throwError(exec, JSC::TypeError, message);
470 }
471
472 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
473
474 JSC::JSValue receiver;
475 JSC::JSValue slot;
476 JSC::JSValue arg0 = args.at(0);
477 if (args.size() < 2) {
478 slot = arg0;
479 } else {
480 receiver = arg0;
481 JSC::JSValue arg1 = args.at(1);
482 if (isFunction(arg1))
483 slot = arg1;
484 else {
485 // ### don't go via QScriptValue
486 QScript::SaveFrameHelper saveFrame(engine, exec);
487 QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
488 QString propertyName(arg1.toString(exec));
489 slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
490 }
491 }
492
493 if (!isFunction(slot)) {
494 return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: target is not a function");
495 }
496
497 bool ok = engine->scriptDisconnect(thisObject, receiver, slot);
498 if (!ok) {
499 QString message = QString::fromLatin1("Function.prototype.disconnect: failed to disconnect from %0::%1")
500 .arg(QLatin1String(qtSignal->metaObject()->className()))
501 .arg(QLatin1String(sig.signature()));
502 return JSC::throwError(exec, JSC::GeneralError, message);
503 }
504 return JSC::jsUndefined();
505#else
506 Q_UNUSED(eng);
507 return context->throwError(QScriptContext::TypeError,
508 QLatin1String("Function.prototype.disconnect"));
509#endif // QT_NO_QOBJECT
510}
511
512JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject * /*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args)
513{
514#ifndef QT_NO_QOBJECT
515 if (args.size() == 0) {
516 return JSC::throwError(exec, JSC::GeneralError,"Function.prototype.connect: no arguments given");
517 }
518
519 if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) {
520 return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: this object is not a signal");
521 }
522
523 QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject));
524
525 const QMetaObject *meta = qtSignal->metaObject();
526 if (!meta) {
527 return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: cannot connect to deleted QObject");
528 }
529
530 QMetaMethod sig = meta->method(qtSignal->initialIndex());
531 if (sig.methodType() != QMetaMethod::Signal) {
532 QString message = QString::fromLatin1("Function.prototype.connect: %0::%1 is not a signal")
533 .arg(QLatin1String(qtSignal->metaObject()->className()))
534 .arg(QLatin1String(sig.signature()));
535 return JSC::throwError(exec, JSC::TypeError, message);
536 }
537
538 {
539 QList<int> overloads = qtSignal->overloadedIndexes();
540 if (!overloads.isEmpty()) {
541 overloads.append(qtSignal->initialIndex());
542 QByteArray signature = sig.signature();
543 QString message = QString::fromLatin1("Function.prototype.connect: ambiguous connect to %0::%1(); candidates are\n")
544 .arg(QLatin1String(qtSignal->metaObject()->className()))
545 .arg(QLatin1String(signature.left(signature.indexOf('('))));
546 for (int i = 0; i < overloads.size(); ++i) {
547 QMetaMethod mtd = meta->method(overloads.at(i));
548 message.append(QString::fromLatin1(" %0\n").arg(QString::fromLatin1(mtd.signature())));
549 }
550 message.append(QString::fromLatin1("Use e.g. object['%0'].connect() to connect to a particular overload")
551 .arg(QLatin1String(signature)));
552 return JSC::throwError(exec, JSC::GeneralError, message);
553 }
554 }
555
556 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
557
558 JSC::JSValue receiver;
559 JSC::JSValue slot;
560 JSC::JSValue arg0 = args.at(0);
561 if (args.size() < 2) {
562 slot = arg0;
563 } else {
564 receiver = arg0;
565 JSC::JSValue arg1 = args.at(1);
566 if (isFunction(arg1))
567 slot = arg1;
568 else {
569 // ### don't go via QScriptValue
570 QScript::SaveFrameHelper saveFrame(engine, exec);
571 QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
572 QString propertyName = arg1.toString(exec);
573 slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
574 }
575 }
576
577 if (!isFunction(slot)) {
578 return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: target is not a function");
579 }
580
581 bool ok = engine->scriptConnect(thisObject, receiver, slot, Qt::AutoConnection);
582 if (!ok) {
583 QString message = QString::fromLatin1("Function.prototype.connect: failed to connect to %0::%1")
584 .arg(QLatin1String(qtSignal->metaObject()->className()))
585 .arg(QLatin1String(sig.signature()));
586 return JSC::throwError(exec, JSC::GeneralError, message);
587 }
588 return JSC::jsUndefined();
589#else
590 Q_UNUSED(eng);
591 Q_UNUSED(classInfo);
592 return context->throwError(QScriptContext::TypeError,
593 QLatin1String("Function.prototype.connect"));
594#endif // QT_NO_QOBJECT
595}
596
597static JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
598static JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
599static JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
600
601JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList& args)
602{
603 QString result;
604 for (unsigned i = 0; i < args.size(); ++i) {
605 if (i != 0)
606 result.append(QLatin1Char(' '));
607 QString s(args.at(i).toString(exec));
608 if (exec->hadException())
609 break;
610 result.append(s);
611 }
612 if (exec->hadException())
613 return exec->exception();
614 qDebug("%s", qPrintable(result));
615 return JSC::jsUndefined();
616}
617
618JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
619{
620 QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
621 engine->collectGarbage();
622 return JSC::jsUndefined();
623}
624
625JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&)
626{
627 return JSC::JSValue(exec, 1);
628}
629
630static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
631static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
632static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
633static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
634
635JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
636{
637 if (args.size() < 2)
638 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate() requires at least two arguments");
639 if (!args.at(0).isString())
640 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): first argument (context) must be a string");
641 if (!args.at(1).isString())
642 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): second argument (text) must be a string");
643 if ((args.size() > 2) && !args.at(2).isString())
644 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (comment) must be a string");
645 if ((args.size() > 3) && !args.at(3).isString())
646 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fourth argument (encoding) must be a string");
647 if ((args.size() > 4) && !args.at(4).isNumber())
648 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number");
649#ifndef QT_NO_QOBJECT
650 QString context(args.at(0).toString(exec));
651#endif
652 QString text(args.at(1).toString(exec));
653#ifndef QT_NO_QOBJECT
654 QString comment;
655 if (args.size() > 2)
656 comment = args.at(2).toString(exec);
657 QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr;
658 if (args.size() > 3) {
659 QString encStr(args.at(3).toString(exec));
660 if (encStr == QLatin1String("CodecForTr"))
661 encoding = QCoreApplication::CodecForTr;
662 else if (encStr == QLatin1String("UnicodeUTF8"))
663 encoding = QCoreApplication::UnicodeUTF8;
664 else
665 return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("qsTranslate(): invalid encoding '%s'").arg(encStr));
666 }
667 int n = -1;
668 if (args.size() > 4)
669 n = args.at(4).toInt32(exec);
670#endif
671 QString result;
672#ifndef QT_NO_QOBJECT
673 result = QCoreApplication::translate(context.toLatin1().constData(),
674 text.toLatin1().constData(),
675 comment.toLatin1().constData(),
676 encoding, n);
677#else
678 result = text;
679#endif
680 return JSC::jsString(exec, result);
681}
682
683JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
684{
685 if (args.size() < 2)
686 return JSC::jsUndefined();
687 return args.at(1);
688}
689
690JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
691{
692 if (args.size() < 1)
693 return JSC::throwError(exec, JSC::GeneralError, "qsTr() requires at least one argument");
694 if (!args.at(0).isString())
695 return JSC::throwError(exec, JSC::GeneralError, "qsTr(): first argument (text) must be a string");
696 if ((args.size() > 1) && !args.at(1).isString())
697 return JSC::throwError(exec, JSC::GeneralError, "qsTr(): second argument (comment) must be a string");
698 if ((args.size() > 2) && !args.at(2).isNumber())
699 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (n) must be a number");
700#ifndef QT_NO_QOBJECT
701 QString context;
702 QScriptContext *ctx = QScriptEnginePrivate::contextForFrame(exec);
703 if (ctx && ctx->parentContext())
704 context = QFileInfo(QScriptContextInfo(ctx->parentContext()).fileName()).baseName();
705#endif
706 QString text(args.at(0).toString(exec));
707#ifndef QT_NO_QOBJECT
708 QString comment;
709 if (args.size() > 1)
710 comment = args.at(1).toString(exec);
711 int n = -1;
712 if (args.size() > 2)
713 n = args.at(2).toInt32(exec);
714#endif
715 QString result;
716#ifndef QT_NO_QOBJECT
717 result = QCoreApplication::translate(context.toLatin1().constData(),
718 text.toLatin1().constData(),
719 comment.toLatin1().constData(),
720 QCoreApplication::CodecForTr, n);
721#else
722 result = text;
723#endif
724 return JSC::jsString(exec, result);
725}
726
727JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
728{
729 if (args.size() < 1)
730 return JSC::jsUndefined();
731 return args.at(0);
732}
733
734static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
735
736JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args)
737{
738 QString value(thisObject.toString(exec));
739 JSC::JSValue arg = (args.size() != 0) ? args.at(0) : JSC::jsUndefined();
740 QString result;
741 if (arg.isString())
742 result = value.arg(arg.toString(exec));
743 else if (arg.isNumber())
744 result = value.arg(arg.toNumber(exec));
745 return JSC::jsString(exec, result);
746}
747
748
749#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY)
750static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng)
751{
752 QString path = ctx->argument(0).toString();
753 QStringList components = path.split(QLatin1Char('.'));
754 QScriptValue o = eng->globalObject();
755 for (int i = 0; i < components.count(); ++i) {
756 QString name = components.at(i);
757 QScriptValue oo = o.property(name);
758 if (!oo.isValid()) {
759 oo = eng->newObject();
760 o.setProperty(name, oo);
761 }
762 o = oo;
763 }
764 return o;
765}
766#endif
767
768} // namespace QScript
769
770QScriptEnginePrivate::QScriptEnginePrivate()
771 : registeredScriptValues(0), freeScriptValues(0),
772 registeredScriptStrings(0), inEval(false)
773{
774 qMetaTypeId<QScriptValue>();
775 qMetaTypeId<QList<int> >();
776#ifndef QT_NO_QOBJECT
777 qMetaTypeId<QObjectList>();
778#endif
779
780 if (!QCoreApplication::instance()) {
781 qFatal("QScriptEngine: Must construct a Q(Core)Application before a QScriptEngine");
782 return;
783 }
784 JSC::initializeThreading();
785
786 globalData = JSC::JSGlobalData::create().releaseRef();
787 globalData->clientData = new QScript::GlobalClientData(this);
788 JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
789
790 JSC::ExecState* exec = globalObject->globalExec();
791
792 scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype());
793
794 qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
795 qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype);
796
797 qmetaobjectPrototype = new (exec) QScript::QMetaObjectPrototype(exec, QScript::QMetaObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
798 qmetaobjectWrapperObjectStructure = QScript::QMetaObjectWrapperObject::createStructure(qmetaobjectPrototype);
799
800 variantPrototype = new (exec) QScript::QVariantPrototype(exec, QScript::QVariantPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
801 variantWrapperObjectStructure = QScriptObject::createStructure(variantPrototype);
802
803 globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "print"), QScript::functionPrint));
804 globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "gc"), QScript::functionGC));
805 globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "version"), QScript::functionVersion));
806
807 // ### rather than extending Function.prototype, consider creating a QtSignal.prototype
808 globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "disconnect"), QScript::functionDisconnect));
809 globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "connect"), QScript::functionConnect));
810
811 JSC::TimeoutChecker* originalChecker = globalData->timeoutChecker;
812 globalData->timeoutChecker = new QScript::TimeoutCheckerProxy(*originalChecker);
813 delete originalChecker;
814
815 currentFrame = exec;
816
817 originalGlobalObjectProxy = 0;
818 activeAgent = 0;
819 agentLineNumber = -1;
820 processEventsInterval = -1;
821}
822
823QScriptEnginePrivate::~QScriptEnginePrivate()
824{
825 //disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events
826 QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it;
827 for (it = loadedScripts.constBegin(); it != loadedScripts.constEnd(); ++it)
828 it.value()->disconnectFromEngine();
829
830 while (!ownedAgents.isEmpty())
831 delete ownedAgents.takeFirst();
832
833 detachAllRegisteredScriptValues();
834 detachAllRegisteredScriptStrings();
835 qDeleteAll(m_qobjectData);
836 qDeleteAll(m_typeInfos);
837 JSC::JSLock lock(false);
838 globalData->heap.destroy();
839 globalData->deref();
840 while (freeScriptValues) {
841 QScriptValuePrivate *p = freeScriptValues;
842 freeScriptValues = p->next;
843 qFree(p);
844 }
845}
846
847QScriptValue QScriptEnginePrivate::scriptValueFromVariant(const QVariant &v)
848{
849 Q_Q(QScriptEngine);
850 QScriptValue result = q->create(v.userType(), v.data());
851 Q_ASSERT(result.isValid());
852 return result;
853}
854
855QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, int targetType)
856{
857 QVariant v(targetType, (void *)0);
858 if (QScriptEnginePrivate::convert(value, targetType, v.data(), this))
859 return v;
860 if (uint(targetType) == QVariant::LastType)
861 return value.toVariant();
862 if (value.isVariant()) {
863 v = value.toVariant();
864 if (v.canConvert(QVariant::Type(targetType))) {
865 v.convert(QVariant::Type(targetType));
866 return v;
867 }
868 QByteArray typeName = v.typeName();
869 if (typeName.endsWith('*')
870 && (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) {
871 return QVariant(targetType, *reinterpret_cast<void* *>(v.data()));
872 }
873 }
874
875 return QVariant();
876}
877
878JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(const QVariant &v)
879{
880 // ### it's inefficient to convert to QScriptValue and then to JSValue
881 QScriptValue vv = scriptValueFromVariant(v);
882 QScriptValuePrivate *p = QScriptValuePrivate::get(vv);
883 switch (p->type) {
884 case QScriptValuePrivate::JavaScriptCore:
885 return p->jscValue;
886 case QScriptValuePrivate::Number:
887 return JSC::jsNumber(currentFrame, p->numberValue);
888 case QScriptValuePrivate::String: {
889 JSC::UString str = p->stringValue;
890 return JSC::jsString(currentFrame, str);
891 }
892 }
893 return JSC::JSValue();
894}
895
896QVariant QScriptEnginePrivate::jscValueToVariant(JSC::JSValue value, int targetType)
897{
898 // ### it's inefficient to convert to QScriptValue and then to QVariant
899 return scriptValueToVariant(scriptValueFromJSCValue(value), targetType);
900}
901
902QScriptValue QScriptEnginePrivate::arrayFromStringList(const QStringList &lst)
903{
904 Q_Q(QScriptEngine);
905 QScriptValue arr = q->newArray(lst.size());
906 for (int i = 0; i < lst.size(); ++i)
907 arr.setProperty(i, QScriptValue(q, lst.at(i)));
908 return arr;
909}
910
911QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValue &arr)
912{
913 QStringList lst;
914 uint len = arr.property(QLatin1String("length")).toUInt32();
915 for (uint i = 0; i < len; ++i)
916 lst.append(arr.property(i).toString());
917 return lst;
918}
919
920QScriptValue QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst)
921{
922 Q_Q(QScriptEngine);
923 QScriptValue arr = q->newArray(lst.size());
924 for (int i = 0; i < lst.size(); ++i)
925 arr.setProperty(i, scriptValueFromVariant(lst.at(i)));
926 return arr;
927}
928
929QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValue &arr)
930{
931 QVariantList lst;
932 uint len = arr.property(QLatin1String("length")).toUInt32();
933 for (uint i = 0; i < len; ++i)
934 lst.append(arr.property(i).toVariant());
935 return lst;
936}
937
938QScriptValue QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap)
939{
940 Q_Q(QScriptEngine);
941 QScriptValue obj = q->newObject();
942 QVariantMap::const_iterator it;
943 for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
944 obj.setProperty(it.key(), scriptValueFromVariant(it.value()));
945 return obj;
946}
947
948QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValue &obj)
949{
950 QVariantMap vmap;
951 QScriptValueIterator it(obj);
952 while (it.hasNext()) {
953 it.next();
954 vmap.insert(it.name(), it.value().toVariant());
955 }
956 return vmap;
957}
958
959JSC::JSValue QScriptEnginePrivate::defaultPrototype(int metaTypeId) const
960{
961 QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
962 if (!info)
963 return JSC::JSValue();
964 return info->prototype;
965}
966
967void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, JSC::JSValue prototype)
968{
969 QScriptTypeInfo *info = m_typeInfos.value(metaTypeId);
970 if (!info) {
971 info = new QScriptTypeInfo();
972 m_typeInfos.insert(metaTypeId, info);
973 }
974 info->prototype = prototype;
975}
976
977JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const
978{
979 return globalData->head;
980}
981
982JSC::JSObject *QScriptEnginePrivate::customGlobalObject() const
983{
984 QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
985 return glob->customGlobalObject;
986}
987
988JSC::JSObject *QScriptEnginePrivate::getOriginalGlobalObjectProxy()
989{
990 if (!originalGlobalObjectProxy) {
991 JSC::ExecState* exec = currentFrame;
992 originalGlobalObjectProxy = new (exec)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
993 }
994 return originalGlobalObjectProxy;
995}
996
997JSC::JSObject *QScriptEnginePrivate::globalObject() const
998{
999 QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
1000 if (glob->customGlobalObject)
1001 return glob->customGlobalObject;
1002 return glob;
1003}
1004
1005void QScriptEnginePrivate::setGlobalObject(JSC::JSObject *object)
1006{
1007 if (object == globalObject())
1008 return;
1009 QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject());
1010 if (object == originalGlobalObjectProxy)
1011 glob->customGlobalObject = 0;
1012 else {
1013 Q_ASSERT(object != originalGlobalObject());
1014 glob->customGlobalObject = object;
1015 }
1016}
1017
1018/*!
1019 \internal
1020
1021 If the given \a value is the original global object, returns the custom
1022 global object or a proxy to the original global object; otherwise returns \a
1023 value.
1024*/
1025JSC::JSValue QScriptEnginePrivate::toUsableValue(JSC::JSValue value)
1026{
1027 if (!value || !value.isObject() || !JSC::asObject(value)->isGlobalObject())
1028 return value;
1029 Q_ASSERT(JSC::asObject(value) == originalGlobalObject());
1030 if (customGlobalObject())
1031 return customGlobalObject();
1032 if (!originalGlobalObjectProxy)
1033 originalGlobalObjectProxy = new (currentFrame)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject());
1034 return originalGlobalObjectProxy;
1035}
1036/*!
1037 \internal
1038 Return the 'this' value for a given context
1039*/
1040JSC::JSValue QScriptEnginePrivate::thisForContext(JSC::ExecState *frame)
1041{
1042 if (frame->codeBlock() != 0) {
1043 return frame->thisValue();
1044 } else if(frame == frame->lexicalGlobalObject()->globalExec()) {
1045 return frame->globalThisValue();
1046 } else {
1047 JSC::Register *thisRegister = thisRegisterForFrame(frame);
1048 return thisRegister->jsValue();
1049 }
1050}
1051
1052JSC::Register* QScriptEnginePrivate::thisRegisterForFrame(JSC::ExecState *frame)
1053{
1054 Q_ASSERT(frame->codeBlock() == 0); // only for native calls
1055 return frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount();
1056}
1057
1058/*! \internal
1059 For native context, we use the ReturnValueRegister entry in the stackframe header to store flags.
1060 We can do that because this header is not used as the native function return their value thought C++
1061
1062 when setting flags, NativeContext should always be set
1063
1064 contextFlags returns 0 for non native context
1065 */
1066uint QScriptEnginePrivate::contextFlags(JSC::ExecState *exec)
1067{
1068 if (exec->codeBlock())
1069 return 0; //js function doesn't have flags
1070
1071 return exec->returnValueRegister();
1072}
1073
1074void QScriptEnginePrivate::setContextFlags(JSC::ExecState *exec, uint flags)
1075{
1076 Q_ASSERT(!exec->codeBlock());
1077 exec->registers()[JSC::RegisterFile::ReturnValueRegister] = JSC::Register::withInt(flags);
1078}
1079
1080
1081void QScriptEnginePrivate::mark(JSC::MarkStack& markStack)
1082{
1083 Q_Q(QScriptEngine);
1084
1085 markStack.append(originalGlobalObject());
1086 markStack.append(globalObject());
1087 if (originalGlobalObjectProxy)
1088 markStack.append(originalGlobalObjectProxy);
1089
1090 if (qobjectPrototype)
1091 markStack.append(qobjectPrototype);
1092 if (qmetaobjectPrototype)
1093 markStack.append(qmetaobjectPrototype);
1094 if (variantPrototype)
1095 markStack.append(variantPrototype);
1096
1097 {
1098 QScriptValuePrivate *it;
1099 for (it = registeredScriptValues; it != 0; it = it->next) {
1100 if (it->isJSC())
1101 markStack.append(it->jscValue);
1102 }
1103 }
1104
1105 {
1106 QHash<int, QScriptTypeInfo*>::const_iterator it;
1107 for (it = m_typeInfos.constBegin(); it != m_typeInfos.constEnd(); ++it) {
1108 if ((*it)->prototype)
1109 markStack.append((*it)->prototype);
1110 }
1111 }
1112
1113 {
1114 QScriptContext *context = q->currentContext();
1115
1116 while (context) {
1117 JSC::ScopeChainNode *node = frameForContext(context)->scopeChain();
1118 JSC::ScopeChainIterator it(node);
1119 for (it = node->begin(); it != node->end(); ++it) {
1120 JSC::JSObject *object = *it;
1121 if (object)
1122 markStack.append(object);
1123 }
1124
1125 context = context->parentContext();
1126 }
1127 }
1128
1129#ifndef QT_NO_QOBJECT
1130 markStack.drain(); // make sure everything is marked before marking qobject data
1131 {
1132 QHash<QObject*, QScript::QObjectData*>::const_iterator it;
1133 for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) {
1134 QScript::QObjectData *qdata = it.value();
1135 qdata->mark(markStack);
1136 }
1137 }
1138#endif
1139}
1140
1141bool QScriptEnginePrivate::isCollecting() const
1142{
1143 return globalData->heap.isBusy();
1144}
1145
1146void QScriptEnginePrivate::collectGarbage()
1147{
1148 JSC::JSLock lock(false);
1149 globalData->heap.collect();
1150}
1151
1152QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const
1153{
1154 return static_cast<QScript::TimeoutCheckerProxy*>(globalData->timeoutChecker);
1155}
1156
1157void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent)
1158{
1159 ownedAgents.removeOne(agent);
1160 if (activeAgent == agent) {
1161 QScriptEngineAgentPrivate::get(agent)->detach();
1162 activeAgent = 0;
1163 }
1164}
1165
1166JSC::JSValue QScriptEnginePrivate::evaluateHelper(JSC::ExecState *exec, intptr_t sourceId,
1167 JSC::EvalExecutable *executable,
1168 bool &compile)
1169{
1170 Q_Q(QScriptEngine);
1171 JSC::JSLock lock(false); // ### hmmm
1172 QBoolBlocker inEvalBlocker(inEval, true);
1173 q->currentContext()->activationObject(); //force the creation of a context for native function;
1174
1175 JSC::Debugger* debugger = originalGlobalObject()->debugger();
1176 if (debugger)
1177 debugger->evaluateStart(sourceId);
1178
1179 q->clearExceptions();
1180 JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
1181
1182 if (compile) {
1183 JSC::JSObject* error = executable->compile(exec, exec->scopeChain());
1184 if (error) {
1185 compile = false;
1186 exec->setException(error);
1187
1188 if (debugger) {
1189 debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, error), sourceId, false);
1190 debugger->evaluateStop(error, sourceId);
1191 }
1192
1193 return error;
1194 }
1195 }
1196
1197 JSC::JSValue thisValue = thisForContext(exec);
1198 JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull())
1199 ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
1200 JSC::JSValue exceptionValue;
1201 timeoutChecker()->setShouldAbort(false);
1202 if (processEventsInterval > 0)
1203 timeoutChecker()->reset();
1204
1205 JSC::JSValue result = exec->interpreter()->execute(executable, exec, thisObject, exec->scopeChain(), &exceptionValue);
1206
1207 if (timeoutChecker()->shouldAbort()) {
1208 if (abortResult.isError())
1209 exec->setException(scriptValueToJSCValue(abortResult));
1210
1211 if (debugger)
1212 debugger->evaluateStop(scriptValueToJSCValue(abortResult), sourceId);
1213
1214 return scriptValueToJSCValue(abortResult);
1215 }
1216
1217 if (exceptionValue) {
1218 exec->setException(exceptionValue);
1219
1220 if (debugger)
1221 debugger->evaluateStop(exceptionValue, sourceId);
1222
1223 return exceptionValue;
1224 }
1225
1226 if (debugger)
1227 debugger->evaluateStop(result, sourceId);
1228
1229 Q_ASSERT(!exec->hadException());
1230 return result;
1231}
1232
1233#ifndef QT_NO_QOBJECT
1234
1235JSC::JSValue QScriptEnginePrivate::newQObject(
1236 QObject *object, QScriptEngine::ValueOwnership ownership,
1237 const QScriptEngine::QObjectWrapOptions &options)
1238{
1239 if (!object)
1240 return JSC::jsNull();
1241 JSC::ExecState* exec = currentFrame;
1242 QScript::QObjectData *data = qobjectData(object);
1243 bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0;
1244 QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject;
1245 QScriptObject *result = 0;
1246 if (preferExisting) {
1247 result = data->findWrapper(ownership, opt);
1248 if (result)
1249 return result;
1250 }
1251 result = new (exec) QScriptObject(qobjectWrapperObjectStructure);
1252 if (preferExisting)
1253 data->registerWrapper(result, ownership, opt);
1254 result->setDelegate(new QScript::QObjectDelegate(object, ownership, options));
1255 /*if (setDefaultPrototype)*/ {
1256 const QMetaObject *meta = object->metaObject();
1257 while (meta) {
1258 QByteArray typeString = meta->className();
1259 typeString.append('*');
1260 int typeId = QMetaType::type(typeString);
1261 if (typeId != 0) {
1262 JSC::JSValue proto = defaultPrototype(typeId);
1263 if (proto) {
1264 result->setPrototype(proto);
1265 break;
1266 }
1267 }
1268 meta = meta->superClass();
1269 }
1270 }
1271 return result;
1272}
1273
1274JSC::JSValue QScriptEnginePrivate::newQMetaObject(
1275 const QMetaObject *metaObject, JSC::JSValue ctor)
1276{
1277 if (!metaObject)
1278 return JSC::jsNull();
1279 JSC::ExecState* exec = currentFrame;
1280 QScript::QMetaObjectWrapperObject *result = new (exec) QScript::QMetaObjectWrapperObject(exec, metaObject, ctor, qmetaobjectWrapperObjectStructure);
1281 return result;
1282}
1283
1284bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValue &value,
1285 const QByteArray &targetType,
1286 void **result)
1287{
1288 if (!targetType.endsWith('*'))
1289 return false;
1290 if (QObject *qobject = value.toQObject()) {
1291 int start = targetType.startsWith("const ") ? 6 : 0;
1292 QByteArray className = targetType.mid(start, targetType.size()-start-1);
1293 if (void *instance = qobject->qt_metacast(className)) {
1294 *result = instance;
1295 return true;
1296 }
1297 }
1298 return false;
1299}
1300
1301QScript::QObjectData *QScriptEnginePrivate::qobjectData(QObject *object)
1302{
1303 QHash<QObject*, QScript::QObjectData*>::const_iterator it;
1304 it = m_qobjectData.constFind(object);
1305 if (it != m_qobjectData.constEnd())
1306 return it.value();
1307
1308 QScript::QObjectData *data = new QScript::QObjectData(this);
1309 m_qobjectData.insert(object, data);
1310 QObject::connect(object, SIGNAL(destroyed(QObject*)),
1311 q_func(), SLOT(_q_objectDestroyed(QObject*)));
1312 return data;
1313}
1314
1315void QScriptEnginePrivate::_q_objectDestroyed(QObject *object)
1316{
1317 QHash<QObject*, QScript::QObjectData*>::iterator it;
1318 it = m_qobjectData.find(object);
1319 Q_ASSERT(it != m_qobjectData.end());
1320 QScript::QObjectData *data = it.value();
1321 m_qobjectData.erase(it);
1322 delete data;
1323}
1324
1325void QScriptEnginePrivate::disposeQObject(QObject *object)
1326{
1327 // TODO
1328/* if (isCollecting()) {
1329 // wait until we're done with GC before deleting it
1330 int index = m_qobjectsToBeDeleted.indexOf(object);
1331 if (index == -1)
1332 m_qobjectsToBeDeleted.append(object);
1333 } else*/ {
1334 delete object;
1335 }
1336}
1337
1338void QScriptEnginePrivate::emitSignalHandlerException()
1339{
1340 Q_Q(QScriptEngine);
1341 emit q->signalHandlerException(q->uncaughtException());
1342}
1343
1344bool QScriptEnginePrivate::scriptConnect(QObject *sender, const char *signal,
1345 JSC::JSValue receiver, JSC::JSValue function,
1346 Qt::ConnectionType type)
1347{
1348 Q_ASSERT(sender);
1349 Q_ASSERT(signal);
1350 const QMetaObject *meta = sender->metaObject();
1351 int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
1352 if (index == -1)
1353 return false;
1354 return scriptConnect(sender, index, receiver, function, /*wrapper=*/JSC::JSValue(), type);
1355}
1356
1357bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, const char *signal,
1358 JSC::JSValue receiver, JSC::JSValue function)
1359{
1360 Q_ASSERT(sender);
1361 Q_ASSERT(signal);
1362 const QMetaObject *meta = sender->metaObject();
1363 int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1));
1364 if (index == -1)
1365 return false;
1366 return scriptDisconnect(sender, index, receiver, function);
1367}
1368
1369bool QScriptEnginePrivate::scriptConnect(QObject *sender, int signalIndex,
1370 JSC::JSValue receiver, JSC::JSValue function,
1371 JSC::JSValue senderWrapper,
1372 Qt::ConnectionType type)
1373{
1374 QScript::QObjectData *data = qobjectData(sender);
1375 return data->addSignalHandler(sender, signalIndex, receiver, function, senderWrapper, type);
1376}
1377
1378bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, int signalIndex,
1379 JSC::JSValue receiver, JSC::JSValue function)
1380{
1381 QScript::QObjectData *data = qobjectData(sender);
1382 if (!data)
1383 return false;
1384 return data->removeSignalHandler(sender, signalIndex, receiver, function);
1385}
1386
1387bool QScriptEnginePrivate::scriptConnect(JSC::JSValue signal, JSC::JSValue receiver,
1388 JSC::JSValue function, Qt::ConnectionType type)
1389{
1390 QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
1391 int index = fun->mostGeneralMethod();
1392 return scriptConnect(fun->qobject(), index, receiver, function, fun->wrapperObject(), type);
1393}
1394
1395bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver,
1396 JSC::JSValue function)
1397{
1398 QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal));
1399 int index = fun->mostGeneralMethod();
1400 return scriptDisconnect(fun->qobject(), index, receiver, function);
1401}
1402
1403#endif
1404
1405void QScriptEnginePrivate::detachAllRegisteredScriptValues()
1406{
1407 QScriptValuePrivate *it;
1408 QScriptValuePrivate *next;
1409 for (it = registeredScriptValues; it != 0; it = next) {
1410 it->detachFromEngine();
1411 next = it->next;
1412 it->prev = 0;
1413 it->next = 0;
1414 }
1415 registeredScriptValues = 0;
1416}
1417
1418void QScriptEnginePrivate::detachAllRegisteredScriptStrings()
1419{
1420 QScriptStringPrivate *it;
1421 QScriptStringPrivate *next;
1422 for (it = registeredScriptStrings; it != 0; it = next) {
1423 it->detachFromEngine();
1424 next = it->next;
1425 it->prev = 0;
1426 it->next = 0;
1427 }
1428 registeredScriptStrings = 0;
1429}
1430
1431#ifdef QT_NO_QOBJECT
1432
1433QScriptEngine::QScriptEngine()
1434 : d_ptr(new QScriptEnginePrivate)
1435{
1436 d_ptr->q_ptr = this;
1437}
1438
1439/*! \internal
1440*/
1441QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd)
1442 : d_ptr(&dd)
1443{
1444 d_ptr->q_ptr = this;
1445}
1446#else
1447
1448/*!
1449 Constructs a QScriptEngine object.
1450
1451 The globalObject() is initialized to have properties as described in
1452 \l{ECMA-262}, Section 15.1.
1453*/
1454QScriptEngine::QScriptEngine()
1455 : QObject(*new QScriptEnginePrivate, 0)
1456{
1457}
1458
1459/*!
1460 Constructs a QScriptEngine object with the given \a parent.
1461
1462 The globalObject() is initialized to have properties as described in
1463 \l{ECMA-262}, Section 15.1.
1464*/
1465
1466QScriptEngine::QScriptEngine(QObject *parent)
1467 : QObject(*new QScriptEnginePrivate, parent)
1468{
1469}
1470
1471/*! \internal
1472*/
1473QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent)
1474 : QObject(dd, parent)
1475{
1476}
1477#endif
1478
1479/*!
1480 Destroys this QScriptEngine.
1481*/
1482QScriptEngine::~QScriptEngine()
1483{
1484#ifdef QT_NO_QOBJECT
1485 delete d_ptr;
1486 d_ptr = 0;
1487#endif
1488}
1489
1490/*!
1491 Returns this engine's Global Object.
1492
1493 By default, the Global Object contains the built-in objects that are
1494 part of \l{ECMA-262}, such as Math, Date and String. Additionally,
1495 you can set properties of the Global Object to make your own
1496 extensions available to all script code. Non-local variables in
1497 script code will be created as properties of the Global Object, as
1498 well as local variables in global code.
1499*/
1500QScriptValue QScriptEngine::globalObject() const
1501{
1502 Q_D(const QScriptEngine);
1503 JSC::JSObject *result = d->globalObject();
1504 return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result);
1505}
1506
1507/*!
1508 \since 4.5
1509
1510 Sets this engine's Global Object to be the given \a object.
1511 If \a object is not a valid script object, this function does
1512 nothing.
1513
1514 When setting a custom global object, you may want to use
1515 QScriptValueIterator to copy the properties of the standard Global
1516 Object; alternatively, you can set the internal prototype of your
1517 custom object to be the original Global Object.
1518*/
1519void QScriptEngine::setGlobalObject(const QScriptValue &object)
1520{
1521 Q_D(QScriptEngine);
1522 if (!object.isObject())
1523 return;
1524 JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));
1525 d->setGlobalObject(jscObject);
1526}
1527
1528/*!
1529 Returns a QScriptValue of the primitive type Null.
1530
1531 \sa undefinedValue()
1532*/
1533QScriptValue QScriptEngine::nullValue()
1534{
1535 Q_D(QScriptEngine);
1536 return d->scriptValueFromJSCValue(JSC::jsNull());
1537}
1538
1539/*!
1540 Returns a QScriptValue of the primitive type Undefined.
1541
1542 \sa nullValue()
1543*/
1544QScriptValue QScriptEngine::undefinedValue()
1545{
1546 Q_D(QScriptEngine);
1547 return d->scriptValueFromJSCValue(JSC::jsUndefined());
1548}
1549
1550/*!
1551 Creates a constructor function from \a fun, with the given \a length.
1552 The \c{prototype} property of the resulting function is set to be the
1553 given \a prototype. The \c{constructor} property of \a prototype is
1554 set to be the resulting function.
1555
1556 When a function is called as a constructor (e.g. \c{new Foo()}), the
1557 `this' object associated with the function call is the new object
1558 that the function is expected to initialize; the prototype of this
1559 default constructed object will be the function's public
1560 \c{prototype} property. If you always want the function to behave as
1561 a constructor (e.g. \c{Foo()} should also create a new object), or
1562 if you need to create your own object rather than using the default
1563 `this' object, you should make sure that the prototype of your
1564 object is set correctly; either by setting it manually, or, when
1565 wrapping a custom type, by having registered the defaultPrototype()
1566 of that type. Example:
1567
1568 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
1569
1570 To wrap a custom type and provide a constructor for it, you'd typically
1571 do something like this:
1572
1573 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
1574*/
1575QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun,
1576 const QScriptValue &prototype,
1577 int length)
1578{
1579 Q_D(QScriptEngine);
1580 JSC::ExecState* exec = d->currentFrame;
1581 JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
1582 QScriptValue result = d->scriptValueFromJSCValue(function);
1583 result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable);
1584 const_cast<QScriptValue&>(prototype)
1585 .setProperty(QLatin1String("constructor"), result,
1586 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1587 return result;
1588}
1589
1590#ifndef QT_NO_REGEXP
1591
1592extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
1593
1594/*!
1595 Creates a QtScript object of class RegExp with the given
1596 \a regexp.
1597
1598 \sa QScriptValue::toRegExp()
1599*/
1600QScriptValue QScriptEngine::newRegExp(const QRegExp &regexp)
1601{
1602 Q_D(QScriptEngine);
1603 JSC::ExecState* exec = d->currentFrame;
1604 JSC::JSValue buf[2];
1605 JSC::ArgList args(buf, sizeof(buf));
1606
1607 //convert the pattern to a ECMAScript pattern
1608 QString pattern = qt_regexp_toCanonical(regexp.pattern(), regexp.patternSyntax());
1609 if (regexp.isMinimal()) {
1610 QString ecmaPattern;
1611 int len = pattern.length();
1612 ecmaPattern.reserve(len);
1613 int i = 0;
1614 const QChar *wc = pattern.unicode();
1615 bool inBracket = false;
1616 while (i < len) {
1617 QChar c = wc[i++];
1618 ecmaPattern += c;
1619 switch (c.unicode()) {
1620 case '?':
1621 case '+':
1622 case '*':
1623 case '}':
1624 if (!inBracket)
1625 ecmaPattern += QLatin1Char('?');
1626 break;
1627 case '\\':
1628 if (i < len)
1629 ecmaPattern += wc[i++];
1630 break;
1631 case '[':
1632 inBracket = true;
1633 break;
1634 case ']':
1635 inBracket = false;
1636 break;
1637 default:
1638 break;
1639 }
1640 }
1641 pattern = ecmaPattern;
1642 }
1643
1644 JSC::UString jscPattern = pattern;
1645 QString flags;
1646 if (regexp.caseSensitivity() == Qt::CaseInsensitive)
1647 flags.append(QLatin1Char('i'));
1648 JSC::UString jscFlags = flags;
1649 buf[0] = JSC::jsString(exec, jscPattern);
1650 buf[1] = JSC::jsString(exec, jscFlags);
1651 JSC::JSObject* result = JSC::constructRegExp(exec, args);
1652 return d->scriptValueFromJSCValue(result);
1653}
1654
1655#endif // QT_NO_REGEXP
1656
1657/*!
1658 Creates a QtScript object holding the given variant \a value.
1659
1660 If a default prototype has been registered with the meta type id of
1661 \a value, then the prototype of the created object will be that
1662 prototype; otherwise, the prototype will be the Object prototype
1663 object.
1664
1665 \sa setDefaultPrototype(), QScriptValue::toVariant()
1666*/
1667QScriptValue QScriptEngine::newVariant(const QVariant &value)
1668{
1669 Q_D(QScriptEngine);
1670 JSC::ExecState* exec = d->currentFrame;
1671 QScriptObject *obj = new (exec) QScriptObject(d->variantWrapperObjectStructure);
1672 obj->setDelegate(new QScript::QVariantDelegate(value));
1673 QScriptValue result = d->scriptValueFromJSCValue(obj);
1674 QScriptValue proto = defaultPrototype(value.userType());
1675 if (proto.isValid())
1676 result.setPrototype(proto);
1677 return result;
1678}
1679
1680/*!
1681 \since 4.4
1682 \overload
1683
1684 Initializes the given Qt Script \a object to hold the given variant
1685 \a value, and returns the \a object.
1686
1687 This function enables you to "promote" a plain Qt Script object
1688 (created by the newObject() function) to a variant, or to replace
1689 the variant contained inside an object previously created by the
1690 newVariant() function.
1691
1692 The prototype() of the \a object will remain unchanged.
1693
1694 If \a object is not an object, this function behaves like the normal
1695 newVariant(), i.e. it creates a new script object and returns it.
1696
1697 This function is useful when you want to provide a script
1698 constructor for a C++ type. If your constructor is invoked in a
1699 \c{new} expression (QScriptContext::isCalledAsConstructor() returns
1700 true), you can pass QScriptContext::thisObject() (the default
1701 constructed script object) to this function to initialize the new
1702 object.
1703*/
1704QScriptValue QScriptEngine::newVariant(const QScriptValue &object,
1705 const QVariant &value)
1706{
1707 if (!object.isObject())
1708 return newVariant(value);
1709 JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue);
1710 if (!jscObject->inherits(&QScriptObject::info)) {
1711 qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported");
1712 return QScriptValue();
1713 }
1714 QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
1715 if (!object.isVariant()) {
1716 jscScriptObject->setDelegate(new QScript::QVariantDelegate(value));
1717 } else {
1718 QScriptValuePrivate::get(object)->setVariantValue(value);
1719 }
1720 return object;
1721}
1722
1723#ifndef QT_NO_QOBJECT
1724/*!
1725 Creates a QtScript object that wraps the given QObject \a
1726 object, using the given \a ownership. The given \a options control
1727 various aspects of the interaction with the resulting script object.
1728
1729 Signals and slots, properties and children of \a object are
1730 available as properties of the created QScriptValue. For more
1731 information, see the \l{QtScript} documentation.
1732
1733 If \a object is a null pointer, this function returns nullValue().
1734
1735 If a default prototype has been registered for the \a object's class
1736 (or its superclass, recursively), the prototype of the new script
1737 object will be set to be that default prototype.
1738
1739 If the given \a object is deleted outside of QtScript's control, any
1740 attempt to access the deleted QObject's members through the QtScript
1741 wrapper object (either by script code or C++) will result in a
1742 script exception.
1743
1744 \sa QScriptValue::toQObject()
1745*/
1746QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership,
1747 const QObjectWrapOptions &options)
1748{
1749 Q_D(QScriptEngine);
1750 JSC::JSValue jscQObject = d->newQObject(object, ownership, options);
1751 return d->scriptValueFromJSCValue(jscQObject);
1752}
1753
1754/*!
1755 \since 4.4
1756 \overload
1757
1758 Initializes the given \a scriptObject to hold the given \a qtObject,
1759 and returns the \a scriptObject.
1760
1761 This function enables you to "promote" a plain Qt Script object
1762 (created by the newObject() function) to a QObject proxy, or to
1763 replace the QObject contained inside an object previously created by
1764 the newQObject() function.
1765
1766 The prototype() of the \a scriptObject will remain unchanged.
1767
1768 If \a scriptObject is not an object, this function behaves like the
1769 normal newQObject(), i.e. it creates a new script object and returns
1770 it.
1771
1772 This function is useful when you want to provide a script
1773 constructor for a QObject-based class. If your constructor is
1774 invoked in a \c{new} expression
1775 (QScriptContext::isCalledAsConstructor() returns true), you can pass
1776 QScriptContext::thisObject() (the default constructed script object)
1777 to this function to initialize the new object.
1778*/
1779QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject,
1780 QObject *qtObject,
1781 ValueOwnership ownership,
1782 const QObjectWrapOptions &options)
1783{
1784 if (!scriptObject.isObject())
1785 return newQObject(qtObject, ownership, options);
1786 JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue);
1787 if (!jscObject->inherits(&QScriptObject::info)) {
1788 qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported");
1789 return QScriptValue();
1790 }
1791 QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
1792 if (!scriptObject.isQObject()) {
1793 jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options));
1794 } else {
1795 QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate());
1796 delegate->setValue(qtObject);
1797 delegate->setOwnership(ownership);
1798 delegate->setOptions(options);
1799 }
1800 return scriptObject;
1801}
1802
1803#endif // QT_NO_QOBJECT
1804
1805/*!
1806 Creates a QtScript object of class Object.
1807
1808 The prototype of the created object will be the Object
1809 prototype object.
1810
1811 \sa newArray(), QScriptValue::setProperty()
1812*/
1813QScriptValue QScriptEngine::newObject()
1814{
1815 Q_D(QScriptEngine);
1816 JSC::ExecState* exec = d->currentFrame;
1817 JSC::JSObject *result = new (exec)QScriptObject(d->scriptObjectStructure);
1818 return d->scriptValueFromJSCValue(result);
1819}
1820
1821/*!
1822 \since 4.4
1823 \overload
1824
1825 Creates a QtScript Object of the given class, \a scriptClass.
1826
1827 The prototype of the created object will be the Object
1828 prototype object.
1829
1830 \a data, if specified, is set as the internal data of the
1831 new object (using QScriptValue::setData()).
1832
1833 \sa QScriptValue::scriptClass()
1834*/
1835QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass,
1836 const QScriptValue &data)
1837{
1838 Q_D(QScriptEngine);
1839 JSC::ExecState* exec = d->currentFrame;
1840 QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure);
1841 result->setDelegate(new QScript::ClassObjectDelegate(scriptClass));
1842 QScriptValue scriptObject = d->scriptValueFromJSCValue(result);
1843 scriptObject.setData(data);
1844 QScriptValue proto = scriptClass->prototype();
1845 if (proto.isValid())
1846 scriptObject.setPrototype(proto);
1847 return scriptObject;
1848}
1849
1850/*!
1851 \internal
1852*/
1853QScriptValue QScriptEngine::newActivationObject()
1854{
1855 qWarning("QScriptEngine::newActivationObject() not implemented");
1856 // ### JSActivation or JSVariableObject?
1857 return QScriptValue();
1858}
1859
1860/*!
1861 Creates a QScriptValue that wraps a native (C++) function. \a fun
1862 must be a C++ function with signature QScriptEngine::FunctionSignature. \a
1863 length is the number of arguments that \a fun expects; this becomes
1864 the \c{length} property of the created QScriptValue.
1865
1866 Note that \a length only gives an indication of the number of
1867 arguments that the function expects; an actual invocation of a
1868 function can include any number of arguments. You can check the
1869 \l{QScriptContext::argumentCount()}{argumentCount()} of the
1870 QScriptContext associated with the invocation to determine the
1871 actual number of arguments passed.
1872
1873 A \c{prototype} property is automatically created for the resulting
1874 function object, to provide for the possibility that the function
1875 will be used as a constructor.
1876
1877 By combining newFunction() and the property flags
1878 QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
1879 can create script object properties that behave like normal
1880 properties in script code, but are in fact accessed through
1881 functions (analogous to how properties work in \l{Qt's Property
1882 System}). Example:
1883
1884 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
1885
1886 When the property \c{foo} of the script object is subsequently
1887 accessed in script code, \c{getSetFoo()} will be invoked to handle
1888 the access. In this particular case, we chose to store the "real"
1889 value of \c{foo} as a property of the accessor function itself; you
1890 are of course free to do whatever you like in this function.
1891
1892 In the above example, a single native function was used to handle
1893 both reads and writes to the property; the argument count is used to
1894 determine if we are handling a read or write. You can also use two
1895 separate functions; just specify the relevant flag
1896 (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
1897 setting the property, e.g.:
1898
1899 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
1900
1901 \sa QScriptValue::call()
1902*/
1903QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
1904{
1905 Q_D(QScriptEngine);
1906 JSC::ExecState* exec = d->currentFrame;
1907 JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
1908 QScriptValue result = d->scriptValueFromJSCValue(function);
1909 QScriptValue proto = newObject();
1910 result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
1911 proto.setProperty(QLatin1String("constructor"), result,
1912 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1913 return result;
1914}
1915
1916/*!
1917 \internal
1918 \since 4.4
1919*/
1920QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg)
1921{
1922 Q_D(QScriptEngine);
1923 JSC::ExecState* exec = d->currentFrame;
1924 JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg);
1925 QScriptValue result = d->scriptValueFromJSCValue(function);
1926 QScriptValue proto = newObject();
1927 result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
1928 proto.setProperty(QLatin1String("constructor"), result,
1929 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1930 return result;
1931}
1932
1933/*!
1934 Creates a QtScript object of class Array with the given \a length.
1935
1936 \sa newObject()
1937*/
1938QScriptValue QScriptEngine::newArray(uint length)
1939{
1940 Q_D(QScriptEngine);
1941 JSC::ExecState* exec = d->currentFrame;
1942 JSC::JSArray* result = JSC::constructEmptyArray(exec, length);
1943 return d->scriptValueFromJSCValue(result);
1944}
1945
1946/*!
1947 Creates a QtScript object of class RegExp with the given
1948 \a pattern and \a flags.
1949
1950 The legal flags are 'g' (global), 'i' (ignore case), and 'm'
1951 (multiline).
1952*/
1953QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags)
1954{
1955 Q_D(QScriptEngine);
1956 JSC::ExecState* exec = d->currentFrame;
1957 JSC::JSValue buf[2];
1958 JSC::ArgList args(buf, sizeof(buf));
1959 JSC::UString jscPattern = pattern;
1960 QString strippedFlags;
1961 if (flags.contains(QLatin1Char('i')))
1962 strippedFlags += QLatin1Char('i');
1963 if (flags.contains(QLatin1Char('m')))
1964 strippedFlags += QLatin1Char('m');
1965 if (flags.contains(QLatin1Char('g')))
1966 strippedFlags += QLatin1Char('g');
1967 JSC::UString jscFlags = strippedFlags;
1968 buf[0] = JSC::jsString(exec, jscPattern);
1969 buf[1] = JSC::jsString(exec, jscFlags);
1970 JSC::JSObject* result = JSC::constructRegExp(exec, args);
1971 return d->scriptValueFromJSCValue(result);
1972}
1973
1974/*!
1975 Creates a QtScript object of class Date with the given
1976 \a value (the number of milliseconds since 01 January 1970,
1977 UTC).
1978*/
1979QScriptValue QScriptEngine::newDate(qsreal value)
1980{
1981 Q_D(QScriptEngine);
1982 JSC::ExecState* exec = d->currentFrame;
1983 JSC::JSValue val = JSC::jsNumber(exec, value);
1984 JSC::ArgList args(&val, 1);
1985 JSC::JSObject *result = JSC::constructDate(exec, args);
1986 return d->scriptValueFromJSCValue(result);
1987}
1988
1989/*!
1990 Creates a QtScript object of class Date from the given \a value.
1991
1992 \sa QScriptValue::toDateTime()
1993*/
1994QScriptValue QScriptEngine::newDate(const QDateTime &value)
1995{
1996 return newDate(QScript::FromDateTime(value));
1997}
1998
1999#ifndef QT_NO_QOBJECT
2000/*!
2001 Creates a QtScript object that represents a QObject class, using the
2002 the given \a metaObject and constructor \a ctor.
2003
2004 Enums of \a metaObject (declared with Q_ENUMS) are available as
2005 properties of the created QScriptValue. When the class is called as
2006 a function, \a ctor will be called to create a new instance of the
2007 class.
2008
2009 Example:
2010
2011 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 27
2012
2013 \sa newQObject(), scriptValueFromQMetaObject()
2014*/
2015QScriptValue QScriptEngine::newQMetaObject(
2016 const QMetaObject *metaObject, const QScriptValue &ctor)
2017{
2018 Q_D(QScriptEngine);
2019 JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor);
2020 JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor);
2021 return d->scriptValueFromJSCValue(jscQMetaObject);
2022}
2023
2024/*!
2025 \fn QScriptValue QScriptEngine::scriptValueFromQMetaObject()
2026
2027 Creates a QScriptValue that represents the Qt class \c{T}.
2028
2029 This function is used in combination with one of the
2030 Q_SCRIPT_DECLARE_QMETAOBJECT() macro. Example:
2031
2032 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13
2033
2034 \warning This function is not available with MSVC 6. Use
2035 qScriptValueFromQMetaObject() instead if you need to support that version
2036 of the compiler.
2037
2038 \sa QScriptEngine::newQMetaObject()
2039*/
2040
2041/*!
2042 \fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine)
2043 \since 4.3
2044 \relates QScriptEngine
2045
2046 Uses \a engine to create a QScriptValue that represents the Qt class
2047 \c{T}.
2048
2049 This function is equivalent to
2050 QScriptEngine::scriptValueFromQMetaObject(). It is provided as a
2051 work-around for MSVC 6, which doesn't support member template
2052 functions.
2053
2054 \sa QScriptEngine::newQMetaObject()
2055*/
2056#endif // QT_NO_QOBJECT
2057
2058/*!
2059 \obsolete
2060
2061 Returns true if \a program can be evaluated; i.e. the code is
2062 sufficient to determine whether it appears to be a syntactically
2063 correct program, or contains a syntax error.
2064
2065 This function returns false if \a program is incomplete; i.e. the
2066 input is syntactically correct up to the point where the input is
2067 terminated.
2068
2069 Note that this function only does a static check of \a program;
2070 e.g. it does not check whether references to variables are
2071 valid, and so on.
2072
2073 A typical usage of canEvaluate() is to implement an interactive
2074 interpreter for QtScript. The user is repeatedly queried for
2075 individual lines of code; the lines are concatened internally, and
2076 only when canEvaluate() returns true for the resulting program is it
2077 passed to evaluate().
2078
2079 The following are some examples to illustrate the behavior of
2080 canEvaluate(). (Note that all example inputs are assumed to have an
2081 explicit newline as their last character, since otherwise the
2082 QtScript parser would automatically insert a semi-colon character at
2083 the end of the input, and this could cause canEvaluate() to produce
2084 different results.)
2085
2086 Given the input
2087 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 14
2088 canEvaluate() will return true, since the program appears to be complete.
2089
2090 Given the input
2091 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 15
2092 canEvaluate() will return false, since the if-statement is not complete,
2093 but is syntactically correct so far.
2094
2095 Given the input
2096 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 16
2097 canEvaluate() will return true, but evaluate() will throw a
2098 SyntaxError given the same input.
2099
2100 Given the input
2101 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 17
2102 canEvaluate() will return true, even though the code is clearly not
2103 syntactically valid QtScript code. evaluate() will throw a
2104 SyntaxError when this code is evaluated.
2105
2106 Given the input
2107 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 18
2108 canEvaluate() will return true, but evaluate() will throw a
2109 ReferenceError if \c{foo} is not defined in the script
2110 environment.
2111
2112 \sa evaluate(), checkSyntax()
2113*/
2114bool QScriptEngine::canEvaluate(const QString &program) const
2115{
2116 return QScriptEnginePrivate::canEvaluate(program);
2117}
2118
2119
2120bool QScriptEnginePrivate::canEvaluate(const QString &program)
2121{
2122 QScript::SyntaxChecker checker;
2123 QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
2124 return (result.state != QScript::SyntaxChecker::Intermediate);
2125}
2126
2127/*!
2128 \since 4.5
2129
2130 Checks the syntax of the given \a program. Returns a
2131 QScriptSyntaxCheckResult object that contains the result of the check.
2132*/
2133QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program)
2134{
2135 return QScriptEnginePrivate::checkSyntax(program);
2136}
2137
2138QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &program)
2139{
2140 QScript::SyntaxChecker checker;
2141 QScript::SyntaxChecker::Result result = checker.checkSyntax(program);
2142 QScriptSyntaxCheckResultPrivate *p = new QScriptSyntaxCheckResultPrivate();
2143 switch (result.state) {
2144 case QScript::SyntaxChecker::Error:
2145 p->state = QScriptSyntaxCheckResult::Error;
2146 break;
2147 case QScript::SyntaxChecker::Intermediate:
2148 p->state = QScriptSyntaxCheckResult::Intermediate;
2149 break;
2150 case QScript::SyntaxChecker::Valid:
2151 p->state = QScriptSyntaxCheckResult::Valid;
2152 break;
2153 }
2154 p->errorLineNumber = result.errorLineNumber;
2155 p->errorColumnNumber = result.errorColumnNumber;
2156 p->errorMessage = result.errorMessage;
2157 return QScriptSyntaxCheckResult(p);
2158}
2159
2160
2161
2162/*!
2163 Evaluates \a program, using \a lineNumber as the base line number,
2164 and returns the result of the evaluation.
2165
2166 The script code will be evaluated in the current context.
2167
2168 The evaluation of \a program can cause an exception in the
2169 engine; in this case the return value will be the exception
2170 that was thrown (typically an \c{Error} object). You can call
2171 hasUncaughtException() to determine if an exception occurred in
2172 the last call to evaluate().
2173
2174 \a lineNumber is used to specify a starting line number for \a
2175 program; line number information reported by the engine that pertain
2176 to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
2177 based on this argument. For example, if \a program consists of two
2178 lines of code, and the statement on the second line causes a script
2179 exception, uncaughtExceptionLineNumber() would return the given \a
2180 lineNumber plus one. When no starting line number is specified, line
2181 numbers will be 1-based.
2182
2183 \a fileName is used for error reporting. For example in error objects
2184 the file name is accessible through the "fileName" property if it's
2185 provided with this function.
2186
2187 \sa canEvaluate(), hasUncaughtException(), isEvaluating(), abortEvaluation()
2188*/
2189
2190QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber)
2191{
2192 Q_D(QScriptEngine);
2193 WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
2194 = QScript::UStringSourceProviderWithFeedback::create(program, fileName, lineNumber, d);
2195 intptr_t sourceId = provider->asID();
2196 JSC::SourceCode source(provider, lineNumber); //after construction of SourceCode provider variable will be null.
2197
2198 JSC::ExecState* exec = d->currentFrame;
2199 JSC::EvalExecutable executable(exec, source);
2200 bool compile = true;
2201 return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, &executable, compile));
2202}
2203
2204/*!
2205 \internal
2206 \since 4.6
2207
2208 Evaluates the given \a program and returns the result of the
2209 evaluation.
2210*/
2211QScriptValue QScriptEngine::evaluate(const QScriptProgram &program)
2212{
2213 Q_D(QScriptEngine);
2214 QScriptProgramPrivate *program_d = QScriptProgramPrivate::get(program);
2215 if (!program_d)
2216 return QScriptValue();
2217
2218 JSC::ExecState* exec = d->currentFrame;
2219 JSC::EvalExecutable *executable = program_d->executable(exec, d);
2220 bool compile = !program_d->isCompiled;
2221 JSC::JSValue result = d->evaluateHelper(exec, program_d->sourceId,
2222 executable, compile);
2223 if (compile)
2224 program_d->isCompiled = true;
2225 return d->scriptValueFromJSCValue(result);
2226}
2227
2228/*!
2229 Returns the current context.
2230
2231 The current context is typically accessed to retrieve the arguments
2232 and `this' object in native functions; for convenience, it is
2233 available as the first argument in QScriptEngine::FunctionSignature.
2234*/
2235QScriptContext *QScriptEngine::currentContext() const
2236{
2237 Q_D(const QScriptEngine);
2238 return const_cast<QScriptEnginePrivate*>(d)->contextForFrame(d->currentFrame);
2239}
2240
2241/*!
2242 Enters a new execution context and returns the associated
2243 QScriptContext object.
2244
2245 Once you are done with the context, you should call popContext() to
2246 restore the old context.
2247
2248 By default, the `this' object of the new context is the Global Object.
2249 The context's \l{QScriptContext::callee()}{callee}() will be invalid.
2250
2251 This function is useful when you want to evaluate script code
2252 as if it were the body of a function. You can use the context's
2253 \l{QScriptContext::activationObject()}{activationObject}() to initialize
2254 local variables that will be available to scripts. Example:
2255
2256 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 19
2257
2258 In the above example, the new variable "tmp" defined in the script
2259 will be local to the context; in other words, the script doesn't
2260 have any effect on the global environment.
2261
2262 Returns 0 in case of stack overflow
2263
2264 \sa popContext()
2265*/
2266QScriptContext *QScriptEngine::pushContext()
2267{
2268 Q_D(QScriptEngine);
2269
2270 JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject,
2271 JSC::ArgList(), /*callee = */0);
2272
2273 if (agent())
2274 agent()->contextPush();
2275
2276 return d->contextForFrame(newFrame);
2277}
2278
2279/*! \internal
2280 push a context for a native function.
2281 JSC native function doesn't have different stackframe or context. so we need to create one.
2282
2283 use popContext right after to go back to the previous context the context if no stack overflow has hapenned
2284
2285 exec is the current top frame.
2286
2287 return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow
2288*/
2289JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject,
2290 const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor,
2291 bool clearScopeChain)
2292{
2293 JSC::JSValue thisObject = _thisObject;
2294 if (calledAsConstructor) {
2295 //JSC doesn't create default created object for native functions. so we do it
2296 JSC::JSValue prototype = callee->get(exec, exec->propertyNames().prototype);
2297 JSC::Structure *structure = prototype.isObject() ? JSC::asObject(prototype)->inheritorID()
2298 : originalGlobalObject()->emptyObjectStructure();
2299 thisObject = new (exec) QScriptObject(structure);
2300 }
2301
2302 int flags = NativeContext;
2303 if (calledAsConstructor)
2304 flags |= CalledAsConstructorContext;
2305
2306 //build a frame
2307 JSC::CallFrame *newCallFrame = exec;
2308 if (callee == 0 //called from public QScriptEngine::pushContext
2309 || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call
2310 || (exec->codeBlock() && exec->callee() != callee)) { //the interpreter did not build a frame for us.
2311 //We need to check if the Interpreter might have already created a frame for function called from JS.
2312 JSC::Interpreter *interp = exec->interpreter();
2313 JSC::Register *oldEnd = interp->registerFile().end();
2314 int argc = args.size() + 1; //add "this"
2315 JSC::Register *newEnd = oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize;
2316 if (!interp->registerFile().grow(newEnd))
2317 return 0; //### Stack overflow
2318 newCallFrame = JSC::CallFrame::create(oldEnd);
2319 newCallFrame[0] = thisObject;
2320 int dst = 0;
2321 JSC::ArgList::const_iterator it;
2322 for (it = args.begin(); it != args.end(); ++it)
2323 newCallFrame[++dst] = *it;
2324 newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
2325
2326 if (!clearScopeChain) {
2327 newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
2328 } else {
2329 JSC::JSObject *jscObject = originalGlobalObject();
2330 JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject);
2331 newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee);
2332 }
2333 } else {
2334 setContextFlags(newCallFrame, flags);
2335#if ENABLE(JIT)
2336 exec->registers()[JSC::RegisterFile::Callee] = JSC::JSValue(callee); //JIT let the callee set the 'callee'
2337#endif
2338 if (calledAsConstructor) {
2339 //update the new created this
2340 JSC::Register* thisRegister = thisRegisterForFrame(newCallFrame);
2341 *thisRegister = thisObject;
2342 }
2343 }
2344 currentFrame = newCallFrame;
2345 return newCallFrame;
2346}
2347
2348
2349/*!
2350 Pops the current execution context and restores the previous one.
2351 This function must be used in conjunction with pushContext().
2352
2353 \sa pushContext()
2354*/
2355void QScriptEngine::popContext()
2356{
2357 if (agent())
2358 agent()->contextPop();
2359 Q_D(QScriptEngine);
2360 if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0
2361 || !currentContext()->parentContext()) {
2362 qWarning("QScriptEngine::popContext() doesn't match with pushContext()");
2363 return;
2364 }
2365
2366 d->popContext();
2367}
2368
2369/*! \internal
2370 counter part of QScriptEnginePrivate::pushContext
2371 */
2372void QScriptEnginePrivate::popContext()
2373{
2374 uint flags = contextFlags(currentFrame);
2375 bool hasScope = flags & HasScopeContext;
2376 if (flags & ShouldRestoreCallFrame) { //normal case
2377 JSC::RegisterFile &registerFile = currentFrame->interpreter()->registerFile();
2378 JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount();
2379 if (hasScope)
2380 currentFrame->scopeChain()->pop()->deref();
2381 registerFile.shrink(newEnd);
2382 } else if(hasScope) { //the stack frame was created by the Interpreter, we don't need to rewind it.
2383 currentFrame->setScopeChain(currentFrame->scopeChain()->pop());
2384 currentFrame->scopeChain()->deref();
2385 }
2386 currentFrame = currentFrame->callerFrame();
2387}
2388
2389/*!
2390 Returns true if the last script evaluation resulted in an uncaught
2391 exception; otherwise returns false.
2392
2393 The exception state is cleared when evaluate() is called.
2394
2395 \sa uncaughtException(), uncaughtExceptionLineNumber(),
2396 uncaughtExceptionBacktrace()
2397*/
2398bool QScriptEngine::hasUncaughtException() const
2399{
2400 Q_D(const QScriptEngine);
2401 JSC::ExecState* exec = d->globalExec();
2402 return exec->hadException() || d->currentException().isValid();
2403}
2404
2405/*!
2406 Returns the current uncaught exception, or an invalid QScriptValue
2407 if there is no uncaught exception.
2408
2409 The exception value is typically an \c{Error} object; in that case,
2410 you can call toString() on the return value to obtain an error
2411 message.
2412
2413 \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
2414 uncaughtExceptionBacktrace()
2415*/
2416QScriptValue QScriptEngine::uncaughtException() const
2417{
2418 Q_D(const QScriptEngine);
2419 QScriptValue result;
2420 JSC::ExecState* exec = d->globalExec();
2421 if (exec->hadException())
2422 result = const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(exec->exception());
2423 else
2424 result = d->currentException();
2425 return result;
2426}
2427
2428/*!
2429 Returns the line number where the last uncaught exception occurred.
2430
2431 Line numbers are 1-based, unless a different base was specified as
2432 the second argument to evaluate().
2433
2434 \sa hasUncaughtException(), uncaughtExceptionBacktrace()
2435*/
2436int QScriptEngine::uncaughtExceptionLineNumber() const
2437{
2438 if (!hasUncaughtException())
2439 return -1;
2440 return uncaughtException().property(QLatin1String("lineNumber")).toInt32();
2441}
2442
2443/*!
2444 Returns a human-readable backtrace of the last uncaught exception.
2445
2446 Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
2447
2448 \sa uncaughtException()
2449*/
2450QStringList QScriptEngine::uncaughtExceptionBacktrace() const
2451{
2452 if (!hasUncaughtException())
2453 return QStringList();
2454// ### currently no way to get a full backtrace from JSC without installing a
2455// debugger that reimplements exception() and store the backtrace there.
2456 QScriptValue value = uncaughtException();
2457 if (!value.isError())
2458 return QStringList();
2459 QStringList result;
2460 result.append(QString::fromLatin1("<anonymous>()@%0:%1")
2461 .arg(value.property(QLatin1String("fileName")).toString())
2462 .arg(value.property(QLatin1String("lineNumber")).toInt32()));
2463 return result;
2464}
2465
2466/*!
2467 \since 4.4
2468
2469 Clears any uncaught exceptions in this engine.
2470
2471 \sa hasUncaughtException()
2472*/
2473void QScriptEngine::clearExceptions()
2474{
2475 Q_D(QScriptEngine);
2476 JSC::ExecState* exec = d->currentFrame;
2477 exec->clearException();
2478 d->clearCurrentException();
2479}
2480
2481/*!
2482 Returns the default prototype associated with the given \a metaTypeId,
2483 or an invalid QScriptValue if no default prototype has been set.
2484
2485 \sa setDefaultPrototype()
2486*/
2487QScriptValue QScriptEngine::defaultPrototype(int metaTypeId) const
2488{
2489 Q_D(const QScriptEngine);
2490 return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(d->defaultPrototype(metaTypeId));
2491}
2492
2493/*!
2494 Sets the default prototype of the C++ type identified by the given
2495 \a metaTypeId to \a prototype.
2496
2497 The default prototype provides a script interface for values of
2498 type \a metaTypeId when a value of that type is accessed from script
2499 code. Whenever the script engine (implicitly or explicitly) creates
2500 a QScriptValue from a value of type \a metaTypeId, the default
2501 prototype will be set as the QScriptValue's prototype.
2502
2503 The \a prototype object itself may be constructed using one of two
2504 principal techniques; the simplest is to subclass QScriptable, which
2505 enables you to define the scripting API of the type through QObject
2506 properties and slots. Another possibility is to create a script
2507 object by calling newObject(), and populate the object with the
2508 desired properties (e.g. native functions wrapped with
2509 newFunction()).
2510
2511 \sa defaultPrototype(), qScriptRegisterMetaType(), QScriptable, {Default Prototypes Example}
2512*/
2513void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prototype)
2514{
2515 Q_D(QScriptEngine);
2516 d->setDefaultPrototype(metaTypeId, d->scriptValueToJSCValue(prototype));
2517}
2518
2519/*!
2520 \typedef QScriptEngine::FunctionSignature
2521 \relates QScriptEngine
2522
2523 The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}.
2524
2525 A function with such a signature can be passed to
2526 QScriptEngine::newFunction() to wrap the function.
2527*/
2528
2529/*!
2530 \typedef QScriptEngine::FunctionWithArgSignature
2531 \relates QScriptEngine
2532
2533 The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}.
2534
2535 A function with such a signature can be passed to
2536 QScriptEngine::newFunction() to wrap the function.
2537*/
2538
2539/*!
2540 \typedef QScriptEngine::MarshalFunction
2541 \internal
2542*/
2543
2544/*!
2545 \typedef QScriptEngine::DemarshalFunction
2546 \internal
2547*/
2548
2549/*!
2550 \internal
2551*/
2552QScriptValue QScriptEngine::create(int type, const void *ptr)
2553{
2554 Q_D(QScriptEngine);
2555 return d->create(type, ptr);
2556}
2557
2558QScriptValue QScriptEnginePrivate::create(int type, const void *ptr)
2559{
2560 Q_Q(QScriptEngine);
2561 Q_ASSERT(ptr != 0);
2562 QScriptValue result;
2563 QScriptTypeInfo *info = m_typeInfos.value(type);
2564 if (info && info->marshal) {
2565 result = info->marshal(q, ptr);
2566 } else {
2567 // check if it's one of the types we know
2568 switch (QMetaType::Type(type)) {
2569 case QMetaType::Void:
2570 return QScriptValue(q, QScriptValue::UndefinedValue);
2571 case QMetaType::Bool:
2572 return QScriptValue(q, *reinterpret_cast<const bool*>(ptr));
2573 case QMetaType::Int:
2574 return QScriptValue(q, *reinterpret_cast<const int*>(ptr));
2575 case QMetaType::UInt:
2576 return QScriptValue(q, *reinterpret_cast<const uint*>(ptr));
2577 case QMetaType::LongLong:
2578 return QScriptValue(q, qsreal(*reinterpret_cast<const qlonglong*>(ptr)));
2579 case QMetaType::ULongLong:
2580#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
2581#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
2582 return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
2583#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
2584 return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
2585#else
2586 return QScriptValue(q, qsreal(*reinterpret_cast<const qulonglong*>(ptr)));
2587#endif
2588 case QMetaType::Double:
2589 return QScriptValue(q, qsreal(*reinterpret_cast<const double*>(ptr)));
2590 case QMetaType::QString:
2591 return QScriptValue(q, *reinterpret_cast<const QString*>(ptr));
2592 case QMetaType::Float:
2593 return QScriptValue(q, *reinterpret_cast<const float*>(ptr));
2594 case QMetaType::Short:
2595 return QScriptValue(q, *reinterpret_cast<const short*>(ptr));
2596 case QMetaType::UShort:
2597 return QScriptValue(q, *reinterpret_cast<const unsigned short*>(ptr));
2598 case QMetaType::Char:
2599 return QScriptValue(q, *reinterpret_cast<const char*>(ptr));
2600 case QMetaType::UChar:
2601 return QScriptValue(q, *reinterpret_cast<const unsigned char*>(ptr));
2602 case QMetaType::QChar:
2603 return QScriptValue(q, (*reinterpret_cast<const QChar*>(ptr)).unicode());
2604 case QMetaType::QStringList:
2605 result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr));
2606 break;
2607 case QMetaType::QVariantList:
2608 result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr));
2609 break;
2610 case QMetaType::QVariantMap:
2611 result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr));
2612 break;
2613 case QMetaType::QDateTime:
2614 result = q->newDate(*reinterpret_cast<const QDateTime *>(ptr));
2615 break;
2616 case QMetaType::QDate:
2617 result = q->newDate(QDateTime(*reinterpret_cast<const QDate *>(ptr)));
2618 break;
2619#ifndef QT_NO_REGEXP
2620 case QMetaType::QRegExp:
2621 result = q->newRegExp(*reinterpret_cast<const QRegExp *>(ptr));
2622 break;
2623#endif
2624#ifndef QT_NO_QOBJECT
2625 case QMetaType::QObjectStar:
2626 case QMetaType::QWidgetStar:
2627 result = q->newQObject(*reinterpret_cast<QObject* const *>(ptr));
2628 break;
2629#endif
2630 default:
2631 if (type == qMetaTypeId<QScriptValue>()) {
2632 result = *reinterpret_cast<const QScriptValue*>(ptr);
2633 if (!result.isValid())
2634 return QScriptValue(q, QScriptValue::UndefinedValue);
2635 }
2636
2637#ifndef QT_NO_QOBJECT
2638 // lazy registration of some common list types
2639 else if (type == qMetaTypeId<QObjectList>()) {
2640 qScriptRegisterSequenceMetaType<QObjectList>(q);
2641 return create(type, ptr);
2642 }
2643#endif
2644 else if (type == qMetaTypeId<QList<int> >()) {
2645 qScriptRegisterSequenceMetaType<QList<int> >(q);
2646 return create(type, ptr);
2647 }
2648
2649 else {
2650 QByteArray typeName = QMetaType::typeName(type);
2651 if (typeName == "QVariant")
2652 result = scriptValueFromVariant(*reinterpret_cast<const QVariant*>(ptr));
2653 if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
2654 return QScriptValue(q, QScriptValue::NullValue);
2655 else
2656 result = q->newVariant(QVariant(type, ptr));
2657 }
2658 }
2659 }
2660 if (result.isObject() && info && info->prototype
2661 && JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), originalGlobalObject()->objectPrototype())) {
2662 result.setPrototype(scriptValueFromJSCValue(info->prototype));
2663 }
2664 return result;
2665}
2666
2667bool QScriptEnginePrivate::convert(const QScriptValue &value,
2668 int type, void *ptr,
2669 QScriptEnginePrivate *eng)
2670{
2671 if (!eng)
2672 eng = QScriptValuePrivate::getEngine(value);
2673 if (eng) {
2674 QScriptTypeInfo *info = eng->m_typeInfos.value(type);
2675 if (info && info->demarshal) {
2676 info->demarshal(value, ptr);
2677 return true;
2678 }
2679 }
2680
2681 // check if it's one of the types we know
2682 switch (QMetaType::Type(type)) {
2683 case QMetaType::Bool:
2684 *reinterpret_cast<bool*>(ptr) = value.toBoolean();
2685 return true;
2686 case QMetaType::Int:
2687 *reinterpret_cast<int*>(ptr) = value.toInt32();
2688 return true;
2689 case QMetaType::UInt:
2690 *reinterpret_cast<uint*>(ptr) = value.toUInt32();
2691 return true;
2692 case QMetaType::LongLong:
2693 *reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger());
2694 return true;
2695 case QMetaType::ULongLong:
2696 *reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger());
2697 return true;
2698 case QMetaType::Double:
2699 *reinterpret_cast<double*>(ptr) = value.toNumber();
2700 return true;
2701 case QMetaType::QString:
2702 if (value.isUndefined() || value.isNull())
2703 *reinterpret_cast<QString*>(ptr) = QString();
2704 else
2705 *reinterpret_cast<QString*>(ptr) = value.toString();
2706 return true;
2707 case QMetaType::Float:
2708 *reinterpret_cast<float*>(ptr) = value.toNumber();
2709 return true;
2710 case QMetaType::Short:
2711 *reinterpret_cast<short*>(ptr) = short(value.toInt32());
2712 return true;
2713 case QMetaType::UShort:
2714 *reinterpret_cast<unsigned short*>(ptr) = value.toUInt16();
2715 return true;
2716 case QMetaType::Char:
2717 *reinterpret_cast<char*>(ptr) = char(value.toInt32());
2718 return true;
2719 case QMetaType::UChar:
2720 *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32());
2721 return true;
2722 case QMetaType::QChar:
2723 if (value.isString()) {
2724 QString str = value.toString();
2725 *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0);
2726 } else {
2727 *reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16());
2728 }
2729 return true;
2730 case QMetaType::QDateTime:
2731 if (value.isDate()) {
2732 *reinterpret_cast<QDateTime *>(ptr) = value.toDateTime();
2733 return true;
2734 } break;
2735 case QMetaType::QDate:
2736 if (value.isDate()) {
2737 *reinterpret_cast<QDate *>(ptr) = value.toDateTime().date();
2738 return true;
2739 } break;
2740#ifndef QT_NO_REGEXP
2741 case QMetaType::QRegExp:
2742 if (value.isRegExp()) {
2743 *reinterpret_cast<QRegExp *>(ptr) = value.toRegExp();
2744 return true;
2745 } break;
2746#endif
2747#ifndef QT_NO_QOBJECT
2748 case QMetaType::QObjectStar:
2749 if (value.isQObject() || value.isNull()) {
2750 *reinterpret_cast<QObject* *>(ptr) = value.toQObject();
2751 return true;
2752 } break;
2753 case QMetaType::QWidgetStar:
2754 if (value.isQObject() || value.isNull()) {
2755 QObject *qo = value.toQObject();
2756 if (!qo || qo->isWidgetType()) {
2757 *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo);
2758 return true;
2759 }
2760 } break;
2761#endif
2762 case QMetaType::QStringList:
2763 if (value.isArray()) {
2764 *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value);
2765 return true;
2766 } break;
2767 case QMetaType::QVariantList:
2768 if (value.isArray()) {
2769 *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value);
2770 return true;
2771 } break;
2772 case QMetaType::QVariantMap:
2773 if (value.isObject()) {
2774 *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value);
2775 return true;
2776 } break;
2777 default:
2778 ;
2779 }
2780
2781 QByteArray name = QMetaType::typeName(type);
2782#ifndef QT_NO_QOBJECT
2783 if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr)))
2784 return true;
2785#endif
2786 if (value.isVariant() && name.endsWith('*')) {
2787 int valueType = QMetaType::type(name.left(name.size()-1));
2788 QVariant &var = QScriptValuePrivate::get(value)->variantValue();
2789 if (valueType == var.userType()) {
2790 *reinterpret_cast<void* *>(ptr) = var.data();
2791 return true;
2792 } else {
2793 // look in the prototype chain
2794 QScriptValue proto = value.prototype();
2795 while (proto.isObject()) {
2796 bool canCast = false;
2797 if (proto.isVariant()) {
2798 canCast = (type == proto.toVariant().userType())
2799 || (valueType && (valueType == proto.toVariant().userType()));
2800 }
2801#ifndef QT_NO_QOBJECT
2802 else if (proto.isQObject()) {
2803 QByteArray className = name.left(name.size()-1);
2804 if (QObject *qobject = proto.toQObject())
2805 canCast = qobject->qt_metacast(className) != 0;
2806 }
2807#endif
2808 if (canCast) {
2809 QByteArray varTypeName = QMetaType::typeName(var.userType());
2810 if (varTypeName.endsWith('*'))
2811 *reinterpret_cast<void* *>(ptr) = *reinterpret_cast<void* *>(var.data());
2812 else
2813 *reinterpret_cast<void* *>(ptr) = var.data();
2814 return true;
2815 }
2816 proto = proto.prototype();
2817 }
2818 }
2819 } else if (value.isNull() && name.endsWith('*')) {
2820 *reinterpret_cast<void* *>(ptr) = 0;
2821 return true;
2822 } else if (type == qMetaTypeId<QScriptValue>()) {
2823 if (!eng)
2824 return false;
2825 *reinterpret_cast<QScriptValue*>(ptr) = value;
2826 return true;
2827 } else if (name == "QVariant") {
2828 *reinterpret_cast<QVariant*>(ptr) = value.toVariant();
2829 return true;
2830 }
2831
2832 // lazy registration of some common list types
2833#ifndef QT_NO_QOBJECT
2834 else if (type == qMetaTypeId<QObjectList>()) {
2835 if (!eng)
2836 return false;
2837 qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
2838 return convert(value, type, ptr, eng);
2839 }
2840#endif
2841 else if (type == qMetaTypeId<QList<int> >()) {
2842 if (!eng)
2843 return false;
2844 qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
2845 return convert(value, type, ptr, eng);
2846 }
2847
2848#if 0
2849 if (!name.isEmpty()) {
2850 qWarning("QScriptEngine::convert: unable to convert value to type `%s'",
2851 name.constData());
2852 }
2853#endif
2854 return false;
2855}
2856
2857bool QScriptEnginePrivate::hasDemarshalFunction(int type) const
2858{
2859 QScriptTypeInfo *info = m_typeInfos.value(type);
2860 return info && (info->demarshal != 0);
2861}
2862
2863/*!
2864 \internal
2865*/
2866bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr)
2867{
2868 Q_D(QScriptEngine);
2869 return QScriptEnginePrivate::convert(value, type, ptr, d);
2870}
2871
2872/*!
2873 \internal
2874*/
2875bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr)
2876{
2877 return QScriptEnginePrivate::convert(value, type, ptr, /*engine=*/0);
2878}
2879
2880/*!
2881 \internal
2882*/
2883void QScriptEngine::registerCustomType(int type, MarshalFunction mf,
2884 DemarshalFunction df,
2885 const QScriptValue &prototype)
2886{
2887 Q_D(QScriptEngine);
2888 QScriptTypeInfo *info = d->m_typeInfos.value(type);
2889 if (!info) {
2890 info = new QScriptTypeInfo();
2891 d->m_typeInfos.insert(type, info);
2892 }
2893 info->marshal = mf;
2894 info->demarshal = df;
2895 info->prototype = d->scriptValueToJSCValue(prototype);
2896}
2897
2898/*!
2899 \since 4.5
2900
2901 Installs translator functions on the given \a object, or on the Global
2902 Object if no object is specified.
2903
2904 The relation between Qt Script translator functions and C++ translator
2905 functions is described in the following table:
2906
2907 \table
2908 \header \o Script Function \o Corresponding C++ Function
2909 \row \o qsTr() \o QObject::tr()
2910 \row \o QT_TR_NOOP() \o QT_TR_NOOP()
2911 \row \o qsTranslate() \o QCoreApplication::translate()
2912 \row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
2913 \endtable
2914
2915 \sa {Internationalization with Qt}
2916*/
2917void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
2918{
2919 Q_D(QScriptEngine);
2920 JSC::ExecState* exec = d->currentFrame;
2921 JSC::JSValue jscObject = d->scriptValueToJSCValue(object);
2922 JSC::JSGlobalObject *glob = d->originalGlobalObject();
2923 if (!jscObject || !jscObject.isObject())
2924 jscObject = glob;
2925// unsigned attribs = JSC::DontEnum;
2926 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate));
2927 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
2928 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
2929 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
2930
2931 glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
2932}
2933
2934/*!
2935 Imports the given \a extension into this QScriptEngine. Returns
2936 undefinedValue() if the extension was successfully imported. You
2937 can call hasUncaughtException() to check if an error occurred; in
2938 that case, the return value is the value that was thrown by the
2939 exception (usually an \c{Error} object).
2940
2941 QScriptEngine ensures that a particular extension is only imported
2942 once; subsequent calls to importExtension() with the same extension
2943 name will do nothing and return undefinedValue().
2944
2945 \sa availableExtensions(), QScriptExtensionPlugin, {Creating QtScript Extensions}
2946*/
2947QScriptValue QScriptEngine::importExtension(const QString &extension)
2948{
2949#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
2950 Q_UNUSED(extension);
2951#else
2952 Q_D(QScriptEngine);
2953 if (d->importedExtensions.contains(extension))
2954 return undefinedValue(); // already imported
2955
2956 QScriptContext *context = currentContext();
2957 QCoreApplication *app = QCoreApplication::instance();
2958 if (!app)
2959 return context->throwError(QLatin1String("No application object"));
2960
2961 QObjectList staticPlugins = QPluginLoader::staticInstances();
2962 QStringList libraryPaths = app->libraryPaths();
2963 QString dot = QLatin1String(".");
2964 QStringList pathComponents = extension.split(dot);
2965 QString initDotJs = QLatin1String("__init__.js");
2966
2967 QString ext;
2968 for (int i = 0; i < pathComponents.count(); ++i) {
2969 if (!ext.isEmpty())
2970 ext.append(dot);
2971 ext.append(pathComponents.at(i));
2972 if (d->importedExtensions.contains(ext))
2973 continue; // already imported
2974
2975 if (d->extensionsBeingImported.contains(ext)) {
2976 return context->throwError(QString::fromLatin1("recursive import of %0")
2977 .arg(extension));
2978 }
2979 d->extensionsBeingImported.insert(ext);
2980
2981 QScriptExtensionInterface *iface = 0;
2982 QString initjsContents;
2983 QString initjsFileName;
2984
2985 // look for the extension in static plugins
2986 for (int j = 0; j < staticPlugins.size(); ++j) {
2987 iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(j));
2988 if (!iface)
2989 continue;
2990 if (iface->keys().contains(ext))
2991 break; // use this one
2992 else
2993 iface = 0; // keep looking
2994 }
2995
2996 {
2997 // look for __init__.js resource
2998 QString path = QString::fromLatin1(":/qtscriptextension");
2999 for (int j = 0; j <= i; ++j) {
3000 path.append(QLatin1Char('/'));
3001 path.append(pathComponents.at(j));
3002 }
3003 path.append(QLatin1Char('/'));
3004 path.append(initDotJs);
3005 QFile file(path);
3006 if (file.open(QIODevice::ReadOnly)) {
3007 QTextStream ts(&file);
3008 initjsContents = ts.readAll();
3009 initjsFileName = path;
3010 file.close();
3011 }
3012 }
3013
3014 if (!iface && initjsContents.isEmpty()) {
3015 // look for the extension in library paths
3016 for (int j = 0; j < libraryPaths.count(); ++j) {
3017 QString libPath = libraryPaths.at(j) + QDir::separator() + QLatin1String("script");
3018 QDir dir(libPath);
3019 if (!dir.exists(dot))
3020 continue;
3021
3022 // look for C++ plugin
3023 QFileInfoList files = dir.entryInfoList(QDir::Files);
3024 for (int k = 0; k < files.count(); ++k) {
3025 QFileInfo entry = files.at(k);
3026 QString filePath = entry.canonicalFilePath();
3027 QPluginLoader loader(filePath);
3028 iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
3029 if (iface) {
3030 if (iface->keys().contains(ext))
3031 break; // use this one
3032 else
3033 iface = 0; // keep looking
3034 }
3035 }
3036
3037 // look for __init__.js in the corresponding dir
3038 QDir dirdir(libPath);
3039 bool dirExists = dirdir.exists();
3040 for (int k = 0; dirExists && (k <= i); ++k)
3041 dirExists = dirdir.cd(pathComponents.at(k));
3042 if (dirExists && dirdir.exists(initDotJs)) {
3043 QFile file(dirdir.canonicalPath()
3044 + QDir::separator() + initDotJs);
3045 if (file.open(QIODevice::ReadOnly)) {
3046 QTextStream ts(&file);
3047 initjsContents = ts.readAll();
3048 initjsFileName = file.fileName();
3049 file.close();
3050 }
3051 }
3052
3053 if (iface || !initjsContents.isEmpty())
3054 break;
3055 }
3056 }
3057
3058 if (!iface && initjsContents.isEmpty()) {
3059 d->extensionsBeingImported.remove(ext);
3060 return context->throwError(
3061 QString::fromLatin1("Unable to import %0: no such extension")
3062 .arg(extension));
3063 }
3064
3065 // initialize the extension in a new context
3066 QScriptContext *ctx = pushContext();
3067 ctx->setThisObject(globalObject());
3068 ctx->activationObject().setProperty(QLatin1String("__extension__"), ext,
3069 QScriptValue::ReadOnly | QScriptValue::Undeletable);
3070 ctx->activationObject().setProperty(QLatin1String("__setupPackage__"),
3071 newFunction(QScript::__setupPackage__));
3072 ctx->activationObject().setProperty(QLatin1String("__postInit__"), QScriptValue(QScriptValue::UndefinedValue));
3073
3074 // the script is evaluated first
3075 if (!initjsContents.isEmpty()) {
3076 QScriptValue ret = evaluate(initjsContents, initjsFileName);
3077 if (hasUncaughtException()) {
3078 popContext();
3079 d->extensionsBeingImported.remove(ext);
3080 return ret;
3081 }
3082 }
3083
3084 // next, the C++ plugin is called
3085 if (iface) {
3086 iface->initialize(ext, this);
3087 if (hasUncaughtException()) {
3088 QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
3089 popContext();
3090 d->extensionsBeingImported.remove(ext);
3091 return ret;
3092 }
3093 }
3094
3095 // if the __postInit__ function has been set, we call it
3096 QScriptValue postInit = ctx->activationObject().property(QLatin1String("__postInit__"));
3097 if (postInit.isFunction()) {
3098 postInit.call(globalObject());
3099 if (hasUncaughtException()) {
3100 QScriptValue ret = uncaughtException(); // ctx_p->returnValue();
3101 popContext();
3102 d->extensionsBeingImported.remove(ext);
3103 return ret;
3104 }
3105 }
3106
3107 popContext();
3108
3109 d->importedExtensions.insert(ext);
3110 d->extensionsBeingImported.remove(ext);
3111 } // for (i)
3112#endif // QT_NO_QOBJECT
3113 return undefinedValue();
3114}
3115
3116/*!
3117 \since 4.4
3118
3119 Returns a list naming the available extensions that can be
3120 imported using the importExtension() function. This list includes
3121 extensions that have been imported.
3122
3123 \sa importExtension(), importedExtensions()
3124*/
3125QStringList QScriptEngine::availableExtensions() const
3126{
3127#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
3128 return QStringList();
3129#else
3130 QCoreApplication *app = QCoreApplication::instance();
3131 if (!app)
3132 return QStringList();
3133
3134 QSet<QString> result;
3135
3136 QObjectList staticPlugins = QPluginLoader::staticInstances();
3137 for (int i = 0; i < staticPlugins.size(); ++i) {
3138 QScriptExtensionInterface *iface;
3139 iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(i));
3140 if (iface) {
3141 QStringList keys = iface->keys();
3142 for (int j = 0; j < keys.count(); ++j)
3143 result << keys.at(j);
3144 }
3145 }
3146
3147 QStringList libraryPaths = app->libraryPaths();
3148 for (int i = 0; i < libraryPaths.count(); ++i) {
3149 QString libPath = libraryPaths.at(i) + QDir::separator() + QLatin1String("script");
3150 QDir dir(libPath);
3151 if (!dir.exists())
3152 continue;
3153
3154 // look for C++ plugins
3155 QFileInfoList files = dir.entryInfoList(QDir::Files);
3156 for (int j = 0; j < files.count(); ++j) {
3157 QFileInfo entry = files.at(j);
3158 QString filePath = entry.canonicalFilePath();
3159 QPluginLoader loader(filePath);
3160 QScriptExtensionInterface *iface;
3161 iface = qobject_cast<QScriptExtensionInterface*>(loader.instance());
3162 if (iface) {
3163 QStringList keys = iface->keys();
3164 for (int k = 0; k < keys.count(); ++k)
3165 result << keys.at(k);
3166 }
3167 }
3168
3169 // look for scripts
3170 QString initDotJs = QLatin1String("__init__.js");
3171 QList<QFileInfo> stack;
3172 stack << dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
3173 while (!stack.isEmpty()) {
3174 QFileInfo entry = stack.takeLast();
3175 QDir dd(entry.canonicalFilePath());
3176 if (dd.exists(initDotJs)) {
3177 QString rpath = dir.relativeFilePath(dd.canonicalPath());
3178 QStringList components = rpath.split(QLatin1Char('/'));
3179 result << components.join(QLatin1String("."));
3180 stack << dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
3181 }
3182 }
3183 }
3184
3185 QStringList lst = result.toList();
3186 qSort(lst);
3187 return lst;
3188#endif
3189}
3190
3191/*!
3192 \since 4.4
3193
3194 Returns a list naming the extensions that have been imported
3195 using the importExtension() function.
3196
3197 \sa availableExtensions()
3198*/
3199QStringList QScriptEngine::importedExtensions() const
3200{
3201 Q_D(const QScriptEngine);
3202 QStringList lst = d->importedExtensions.toList();
3203 qSort(lst);
3204 return lst;
3205}
3206
3207/*! \fn QScriptValue QScriptEngine::toScriptValue(const T &value)
3208
3209 Creates a QScriptValue with the given \a value.
3210
3211 Note that the template type \c{T} must be known to QMetaType.
3212
3213 See \l{Conversion Between QtScript and C++ Types} for a
3214 description of the built-in type conversion provided by
3215 QtScript. By default, the types that are not specially handled by
3216 QtScript are represented as QVariants (e.g. the \a value is passed
3217 to newVariant()); you can change this behavior by installing your
3218 own type conversion functions with qScriptRegisterMetaType().
3219
3220 \warning This function is not available with MSVC 6. Use
3221 qScriptValueFromValue() instead if you need to support that
3222 version of the compiler.
3223
3224 \sa fromScriptValue(), qScriptRegisterMetaType()
3225*/
3226
3227/*! \fn T QScriptEngine::fromScriptValue(const QScriptValue &value)
3228
3229 Returns the given \a value converted to the template type \c{T}.
3230
3231 Note that \c{T} must be known to QMetaType.
3232
3233 See \l{Conversion Between QtScript and C++ Types} for a
3234 description of the built-in type conversion provided by
3235 QtScript.
3236
3237 \warning This function is not available with MSVC 6. Use
3238 qScriptValueToValue() or qscriptvalue_cast() instead if you need
3239 to support that version of the compiler.
3240
3241 \sa toScriptValue(), qScriptRegisterMetaType()
3242*/
3243
3244/*!
3245 \fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value)
3246 \since 4.3
3247 \relates QScriptEngine
3248
3249 Creates a QScriptValue using the given \a engine with the given \a
3250 value of template type \c{T}.
3251
3252 This function is equivalent to QScriptEngine::toScriptValue().
3253 It is provided as a work-around for MSVC 6, which doesn't support
3254 member template functions.
3255
3256 \sa qScriptValueToValue()
3257*/
3258
3259/*!
3260 \fn T qScriptValueToValue(const QScriptValue &value)
3261 \since 4.3
3262 \relates QScriptEngine
3263
3264 Returns the given \a value converted to the template type \c{T}.
3265
3266 This function is equivalent to QScriptEngine::fromScriptValue().
3267 It is provided as a work-around for MSVC 6, which doesn't
3268 support member template functions.
3269
3270 \sa qScriptValueFromValue()
3271*/
3272
3273/*!
3274 \fn QScriptValue qScriptValueFromSequence(QScriptEngine *engine, const Container &container)
3275 \since 4.3
3276 \relates QScriptEngine
3277
3278 Creates an array in the form of a QScriptValue using the given \a engine
3279 with the given \a container of template type \c{Container}.
3280
3281 The \c Container type must provide a \c const_iterator class to enable the
3282 contents of the container to be copied into the array.
3283
3284 Additionally, the type of each element in the sequence should be
3285 suitable for conversion to a QScriptValue. See
3286 \l{Conversion Between QtScript and C++ Types} for more information
3287 about the restrictions on types that can be used with QScriptValue.
3288
3289 \sa qScriptValueFromValue()
3290*/
3291
3292/*!
3293 \fn void qScriptValueToSequence(const QScriptValue &value, Container &container)
3294 \since 4.3
3295 \relates QScriptEngine
3296
3297 Copies the elements in the sequence specified by \a value to the given
3298 \a container of template type \c{Container}.
3299
3300 The \a value used is typically an array, but any container can be copied
3301 as long as it provides a \c length property describing how many elements
3302 it contains.
3303
3304 Additionally, the type of each element in the sequence must be
3305 suitable for conversion to a C++ type from a QScriptValue. See
3306 \l{Conversion Between QtScript and C++ Types} for more information
3307 about the restrictions on types that can be used with
3308 QScriptValue.
3309
3310 \sa qscriptvalue_cast()
3311*/
3312
3313/*!
3314 \fn T qscriptvalue_cast(const QScriptValue &value)
3315 \since 4.3
3316 \relates QScriptValue
3317
3318 Returns the given \a value converted to the template type \c{T}.
3319
3320 \sa qScriptRegisterMetaType(), QScriptEngine::toScriptValue()
3321*/
3322
3323/*! \fn int qScriptRegisterMetaType(
3324 QScriptEngine *engine,
3325 QScriptValue (*toScriptValue)(QScriptEngine *, const T &t),
3326 void (*fromScriptValue)(const QScriptValue &, T &t),
3327 const QScriptValue &prototype = QScriptValue())
3328 \relates QScriptEngine
3329
3330 Registers the type \c{T} in the given \a engine. \a toScriptValue must
3331 be a function that will convert from a value of type \c{T} to a
3332 QScriptValue, and \a fromScriptValue a function that does the
3333 opposite. \a prototype, if valid, is the prototype that's set on
3334 QScriptValues returned by \a toScriptValue.
3335
3336 Returns the internal ID used by QMetaType.
3337
3338 You only need to call this function if you want to provide custom
3339 conversion of values of type \c{T}, i.e. if the default
3340 QVariant-based representation and conversion is not
3341 appropriate. (Note that custom QObject-derived types also fall in
3342 this category; e.g. for a QObject-derived class called MyObject,
3343 you probably want to define conversion functions for MyObject*
3344 that utilize QScriptEngine::newQObject() and
3345 QScriptValue::toQObject().)
3346
3347 If you only want to define a common script interface for values of
3348 type \c{T}, and don't care how those values are represented
3349 (i.e. storing them in QVariants is fine), use
3350 \l{QScriptEngine::setDefaultPrototype()}{setDefaultPrototype}()
3351 instead; this will minimize conversion costs.
3352
3353 You need to declare the custom type first with
3354 Q_DECLARE_METATYPE().
3355
3356 After a type has been registered, you can convert from a
3357 QScriptValue to that type using
3358 \l{QScriptEngine::fromScriptValue()}{fromScriptValue}(), and
3359 create a QScriptValue from a value of that type using
3360 \l{QScriptEngine::toScriptValue()}{toScriptValue}(). The engine
3361 will take care of calling the proper conversion function when
3362 calling C++ slots, and when getting or setting a C++ property;
3363 i.e. the custom type may be used seamlessly on both the C++ side
3364 and the script side.
3365
3366 The following is an example of how to use this function. We will
3367 specify custom conversion of our type \c{MyStruct}. Here's the C++
3368 type:
3369
3370 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 20
3371
3372 We must declare it so that the type will be known to QMetaType:
3373
3374 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 21
3375
3376 Next, the \c{MyStruct} conversion functions. We represent the
3377 \c{MyStruct} value as a script object and just copy the properties:
3378
3379 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 22
3380
3381 Now we can register \c{MyStruct} with the engine:
3382 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 23
3383
3384 Working with \c{MyStruct} values is now easy:
3385 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 24
3386
3387 If you want to be able to construct values of your custom type
3388 from script code, you have to register a constructor function for
3389 the type. For example:
3390
3391 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 25
3392
3393 \sa qScriptRegisterSequenceMetaType(), qRegisterMetaType()
3394*/
3395
3396/*!
3397 \macro Q_SCRIPT_DECLARE_QMETAOBJECT(QMetaObject, ArgType)
3398 \since 4.3
3399 \relates QScriptEngine
3400
3401 Declares the given \a QMetaObject. Used in combination with
3402 QScriptEngine::scriptValueFromQMetaObject() to make enums and
3403 instantiation of \a QMetaObject available to script code. The
3404 constructor generated by this macro takes a single argument of
3405 type \a ArgType; typically the argument is the parent type of the
3406 new instance, in which case \a ArgType is \c{QWidget*} or
3407 \c{QObject*}. Objects created by the constructor will have
3408 QScriptEngine::AutoOwnership ownership.
3409*/
3410
3411/*! \fn int qScriptRegisterSequenceMetaType(
3412 QScriptEngine *engine,
3413 const QScriptValue &prototype = QScriptValue())
3414 \relates QScriptEngine
3415
3416 Registers the sequence type \c{T} in the given \a engine. This
3417 function provides conversion functions that convert between \c{T}
3418 and Qt Script \c{Array} objects. \c{T} must provide a
3419 const_iterator class and begin(), end() and push_back()
3420 functions. If \a prototype is valid, it will be set as the
3421 prototype of \c{Array} objects due to conversion from \c{T};
3422 otherwise, the standard \c{Array} prototype will be used.
3423
3424 Returns the internal ID used by QMetaType.
3425
3426 You need to declare the container type first with
3427 Q_DECLARE_METATYPE(). If the element type isn't a standard Qt/C++
3428 type, it must be declared using Q_DECLARE_METATYPE() as well.
3429 Example:
3430
3431 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 26
3432
3433 \sa qScriptRegisterMetaType()
3434*/
3435
3436/*!
3437 Runs the garbage collector.
3438
3439 The garbage collector will attempt to reclaim memory by locating and
3440 disposing of objects that are no longer reachable in the script
3441 environment.
3442
3443 Normally you don't need to call this function; the garbage collector
3444 will automatically be invoked when the QScriptEngine decides that
3445 it's wise to do so (i.e. when a certain number of new objects have
3446 been created). However, you can call this function to explicitly
3447 request that garbage collection should be performed as soon as
3448 possible.
3449*/
3450void QScriptEngine::collectGarbage()
3451{
3452 Q_D(QScriptEngine);
3453 d->collectGarbage();
3454}
3455
3456/*!
3457
3458 Sets the interval between calls to QCoreApplication::processEvents
3459 to \a interval milliseconds.
3460
3461 While the interpreter is running, all event processing is by default
3462 blocked. This means for instance that the gui will not be updated
3463 and timers will not be fired. To allow event processing during
3464 interpreter execution one can specify the processing interval to be
3465 a positive value, indicating the number of milliseconds between each
3466 time QCoreApplication::processEvents() is called.
3467
3468 The default value is -1, which disables event processing during
3469 interpreter execution.
3470
3471 You can use QCoreApplication::postEvent() to post an event that
3472 performs custom processing at the next interval. For example, you
3473 could keep track of the total running time of the script and call
3474 abortEvaluation() when you detect that the script has been running
3475 for a long time without completing.
3476
3477 \sa processEventsInterval()
3478*/
3479void QScriptEngine::setProcessEventsInterval(int interval)
3480{
3481 Q_D(QScriptEngine);
3482 d->processEventsInterval = interval;
3483
3484 if (interval > 0)
3485 d->globalData->timeoutChecker->setCheckInterval(interval);
3486
3487 d->timeoutChecker()->setShouldProcessEvents(interval > 0);
3488}
3489
3490/*!
3491
3492 Returns the interval in milliseconds between calls to
3493 QCoreApplication::processEvents() while the interpreter is running.
3494
3495 \sa setProcessEventsInterval()
3496*/
3497int QScriptEngine::processEventsInterval() const
3498{
3499 Q_D(const QScriptEngine);
3500 return d->processEventsInterval;
3501}
3502
3503/*!
3504 \since 4.4
3505
3506 Returns true if this engine is currently evaluating a script,
3507 otherwise returns false.
3508
3509 \sa evaluate(), abortEvaluation()
3510*/
3511bool QScriptEngine::isEvaluating() const
3512{
3513 Q_D(const QScriptEngine);
3514 return (d->currentFrame != d->globalExec()) || d->inEval;
3515}
3516
3517/*!
3518 \since 4.4
3519
3520 Aborts any script evaluation currently taking place in this engine.
3521 The given \a result is passed back as the result of the evaluation
3522 (i.e. it is returned from the call to evaluate() being aborted).
3523
3524 If the engine isn't evaluating a script (i.e. isEvaluating() returns
3525 false), this function does nothing.
3526
3527 Call this function if you need to abort a running script for some
3528 reason, e.g. when you have detected that the script has been
3529 running for several seconds without completing.
3530
3531 \sa evaluate(), isEvaluating(), setProcessEventsInterval()
3532*/
3533void QScriptEngine::abortEvaluation(const QScriptValue &result)
3534{
3535 Q_D(QScriptEngine);
3536
3537 d->timeoutChecker()->setShouldAbort(true);
3538 d->abortResult = result;
3539}
3540
3541#ifndef QT_NO_QOBJECT
3542
3543/*!
3544 \since 4.4
3545 \relates QScriptEngine
3546
3547 Creates a connection from the \a signal in the \a sender to the
3548 given \a function. If \a receiver is an object, it will act as the
3549 `this' object when the signal handler function is invoked. Returns
3550 true if the connection succeeds; otherwise returns false.
3551
3552 \sa qScriptDisconnect(), QScriptEngine::signalHandlerException()
3553*/
3554bool qScriptConnect(QObject *sender, const char *signal,
3555 const QScriptValue &receiver, const QScriptValue &function)
3556{
3557 if (!sender || !signal)
3558 return false;
3559 if (!function.isFunction())
3560 return false;
3561 if (receiver.isObject() && (receiver.engine() != function.engine()))
3562 return false;
3563 QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
3564 JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
3565 JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
3566 return engine->scriptConnect(sender, signal, jscReceiver, jscFunction,
3567 Qt::AutoConnection);
3568}
3569
3570/*!
3571 \since 4.4
3572 \relates QScriptEngine
3573
3574 Disconnects the \a signal in the \a sender from the given (\a
3575 receiver, \a function) pair. Returns true if the connection is
3576 successfully broken; otherwise returns false.
3577
3578 \sa qScriptConnect()
3579*/
3580bool qScriptDisconnect(QObject *sender, const char *signal,
3581 const QScriptValue &receiver, const QScriptValue &function)
3582{
3583 if (!sender || !signal)
3584 return false;
3585 if (!function.isFunction())
3586 return false;
3587 if (receiver.isObject() && (receiver.engine() != function.engine()))
3588 return false;
3589 QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
3590 JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
3591 JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
3592 return engine->scriptDisconnect(sender, signal, jscReceiver, jscFunction);
3593}
3594
3595/*!
3596 \since 4.4
3597 \fn void QScriptEngine::signalHandlerException(const QScriptValue &exception)
3598
3599 This signal is emitted when a script function connected to a signal causes
3600 an \a exception.
3601
3602 \sa qScriptConnect()
3603*/
3604
3605QT_BEGIN_INCLUDE_NAMESPACE
3606#include "moc_qscriptengine.cpp"
3607QT_END_INCLUDE_NAMESPACE
3608
3609#endif // QT_NO_QOBJECT
3610
3611/*!
3612 \since 4.4
3613
3614 Installs the given \a agent on this engine. The agent will be
3615 notified of various events pertaining to script execution. This is
3616 useful when you want to find out exactly what the engine is doing,
3617 e.g. when evaluate() is called. The agent interface is the basis of
3618 tools like debuggers and profilers.
3619
3620 The engine maintains ownership of the \a agent.
3621
3622 Calling this function will replace the existing agent, if any.
3623
3624 \sa agent()
3625*/
3626void QScriptEngine::setAgent(QScriptEngineAgent *agent)
3627{
3628 Q_D(QScriptEngine);
3629 if (agent && (agent->engine() != this)) {
3630 qWarning("QScriptEngine::setAgent(): "
3631 "cannot set agent belonging to different engine");
3632 return;
3633 }
3634 if (d->activeAgent)
3635 QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
3636 d->activeAgent = agent;
3637 if (agent) {
3638 QScriptEngineAgentPrivate::get(agent)->attach();
3639 }
3640}
3641
3642/*!
3643 \since 4.4
3644
3645 Returns the agent currently installed on this engine, or 0 if no
3646 agent is installed.
3647
3648 \sa setAgent()
3649*/
3650QScriptEngineAgent *QScriptEngine::agent() const
3651{
3652 Q_D(const QScriptEngine);
3653 return d->activeAgent;
3654}
3655
3656/*!
3657 \since 4.4
3658
3659 Returns a handle that represents the given string, \a str.
3660
3661 QScriptString can be used to quickly look up properties, and
3662 compare property names, of script objects.
3663
3664 \sa QScriptValue::property()
3665*/
3666QScriptString QScriptEngine::toStringHandle(const QString &str)
3667{
3668 Q_D(QScriptEngine);
3669 QScriptString result;
3670 QScriptStringPrivate *p = new QScriptStringPrivate(d, JSC::Identifier(d->currentFrame, str), QScriptStringPrivate::HeapAllocated);
3671 QScriptStringPrivate::init(result, p);
3672 d->registerScriptString(p);
3673 return result;
3674}
3675
3676/*!
3677 \since 4.5
3678
3679 Converts the given \a value to an object, if such a conversion is
3680 possible; otherwise returns an invalid QScriptValue. The conversion
3681 is performed according to the following table:
3682
3683 \table
3684 \header \o Input Type \o Result
3685 \row \o Undefined \o An invalid QScriptValue.
3686 \row \o Null \o An invalid QScriptValue.
3687 \row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean.
3688 \row \o Number \o A new Number object whose internal value is set to the value of the number.
3689 \row \o String \o A new String object whose internal value is set to the value of the string.
3690 \row \o Object \o The result is the object itself (no conversion).
3691 \endtable
3692
3693 \sa newObject()
3694*/
3695QScriptValue QScriptEngine::toObject(const QScriptValue &value)
3696{
3697 Q_D(QScriptEngine);
3698 JSC::JSValue jscValue = d->scriptValueToJSCValue(value);
3699 if (!jscValue || jscValue.isUndefined() || jscValue.isNull())
3700 return QScriptValue();
3701 JSC::ExecState* exec = d->currentFrame;
3702 JSC::JSValue result = jscValue.toObject(exec);
3703 return d->scriptValueFromJSCValue(result);
3704}
3705
3706/*!
3707 \internal
3708
3709 Returns the object with the given \a id, or an invalid
3710 QScriptValue if there is no object with that id.
3711
3712 \sa QScriptValue::objectId()
3713*/
3714QScriptValue QScriptEngine::objectById(qint64 id) const
3715{
3716 Q_D(const QScriptEngine);
3717 // Assumes that the cell was not been garbage collected
3718 return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue((JSC::JSCell*)id);
3719}
3720
3721/*!
3722 \since 4.5
3723 \class QScriptSyntaxCheckResult
3724
3725 \brief The QScriptSyntaxCheckResult class provides the result of a script syntax check.
3726
3727 \ingroup script
3728 \mainclass
3729
3730 QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to
3731 provide information about the syntactical (in)correctness of a script.
3732*/
3733
3734/*!
3735 \enum QScriptSyntaxCheckResult::State
3736
3737 This enum specifies the state of a syntax check.
3738
3739 \value Error The program contains a syntax error.
3740 \value Intermediate The program is incomplete.
3741 \value Valid The program is a syntactically correct Qt Script program.
3742*/
3743
3744/*!
3745 Constructs a new QScriptSyntaxCheckResult from the \a other result.
3746*/
3747QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other)
3748 : d_ptr(other.d_ptr)
3749{
3750}
3751
3752/*!
3753 \internal
3754*/
3755QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d)
3756 : d_ptr(d)
3757{
3758}
3759
3760/*!
3761 \internal
3762*/
3763QScriptSyntaxCheckResult::QScriptSyntaxCheckResult()
3764 : d_ptr(0)
3765{
3766}
3767
3768/*!
3769 Destroys this QScriptSyntaxCheckResult.
3770*/
3771QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult()
3772{
3773}
3774
3775/*!
3776 Returns the state of this QScriptSyntaxCheckResult.
3777*/
3778QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const
3779{
3780 Q_D(const QScriptSyntaxCheckResult);
3781 if (!d)
3782 return Valid;
3783 return d->state;
3784}
3785
3786/*!
3787 Returns the error line number of this QScriptSyntaxCheckResult, or -1 if
3788 there is no error.
3789
3790 \sa state(), errorMessage()
3791*/
3792int QScriptSyntaxCheckResult::errorLineNumber() const
3793{
3794 Q_D(const QScriptSyntaxCheckResult);
3795 if (!d)
3796 return -1;
3797 return d->errorLineNumber;
3798}
3799
3800/*!
3801 Returns the error column number of this QScriptSyntaxCheckResult, or -1 if
3802 there is no error.
3803
3804 \sa state(), errorLineNumber()
3805*/
3806int QScriptSyntaxCheckResult::errorColumnNumber() const
3807{
3808 Q_D(const QScriptSyntaxCheckResult);
3809 if (!d)
3810 return -1;
3811 return d->errorColumnNumber;
3812}
3813
3814/*!
3815 Returns the error message of this QScriptSyntaxCheckResult, or an empty
3816 string if there is no error.
3817
3818 \sa state(), errorLineNumber()
3819*/
3820QString QScriptSyntaxCheckResult::errorMessage() const
3821{
3822 Q_D(const QScriptSyntaxCheckResult);
3823 if (!d)
3824 return QString();
3825 return d->errorMessage;
3826}
3827
3828/*!
3829 Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a
3830 reference to this QScriptSyntaxCheckResult.
3831*/
3832QScriptSyntaxCheckResult &QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult &other)
3833{
3834 d_ptr = other.d_ptr;
3835 return *this;
3836}
3837
3838#ifdef QT_BUILD_INTERNAL
3839Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled()
3840{
3841#if ENABLE(JIT)
3842 return true;
3843#else
3844 return false;
3845#endif
3846}
3847#endif
3848
3849QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.