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

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

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

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