• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8 
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13 
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19 
20 #include "config.h"
21 
22 #include "qscriptengine.h"
23 
24 #include "qscriptengine_p.h"
25 #include "qscriptprogram_p.h"
26 #include "qscriptsyntaxcheckresult_p.h"
27 #include "qscriptvalue_p.h"
28 #include <QtCore/qdatetime.h>
29 #include <QtCore/qnumeric.h>
30 
31 /*!
32     Constructs a QScriptEngine object.
33 
34     The globalObject() is initialized to have properties as described in ECMA-262, Section 15.1.
35 */
QScriptEngine()36 QScriptEngine::QScriptEngine()
37     : d_ptr(new QScriptEnginePrivate(this))
38 {
39 }
40 
41 /*!
42     Destroys this QScriptEngine.
43 */
~QScriptEngine()44 QScriptEngine::~QScriptEngine()
45 {
46 }
47 
48 /*!
49   Checks the syntax of the given \a program. Returns a
50   QScriptSyntaxCheckResult object that contains the result of the check.
51 */
checkSyntax(const QString & program)52 QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program)
53 {
54     // FIXME This is not optimal.
55     // The JSC C API needs a context to perform a syntax check, it means that a QScriptEnginePrivate
56     // had to be created. This function is static so we have to create QScriptEnginePrivate for each
57     // call. We can't remove the "static" for compatibility reason, at least up to Qt5.
58     // QScriptSyntaxCheckResultPrivate takes ownership of newly created engine. The engine will be
59     // kept as long as it is needed for lazy evaluation of properties of
60     // the QScriptSyntaxCheckResultPrivate.
61     QScriptEnginePrivate* engine = new QScriptEnginePrivate(/* q_ptr */ 0);
62     return QScriptSyntaxCheckResultPrivate::get(engine->checkSyntax(program));
63 }
64 
65 /*!
66     Evaluates \a program, using \a lineNumber as the base line number,
67     and returns the result of the evaluation.
68 
69     The script code will be evaluated in the current context.
70 
71     The evaluation of \a program can cause an exception in the
72     engine; in this case the return value will be the exception
73     that was thrown (typically an \c{Error} object). You can call
74     hasUncaughtException() to determine if an exception occurred in
75     the last call to evaluate().
76 
77     \a lineNumber is used to specify a starting line number for \a
78     program; line number information reported by the engine that pertain
79     to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
80     based on this argument. For example, if \a program consists of two
81     lines of code, and the statement on the second line causes a script
82     exception, uncaughtExceptionLineNumber() would return the given \a
83     lineNumber plus one. When no starting line number is specified, line
84     numbers will be 1-based.
85 
86     \a fileName is used for error reporting. For example in error objects
87     the file name is accessible through the "fileName" property if it's
88     provided with this function.
89 */
evaluate(const QString & program,const QString & fileName,int lineNumber)90 QScriptValue QScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
91 {
92     return QScriptValuePrivate::get(d_ptr->evaluate(program, fileName, lineNumber));
93 }
94 
evaluate(const QScriptProgram & program)95 QScriptValue QScriptEngine::evaluate(const QScriptProgram& program)
96 {
97     return QScriptValuePrivate::get(d_ptr->evaluate(QScriptProgramPrivate::get(program)));
98 }
99 
100 /*!
101     Returns true if the last script evaluation resulted in an uncaught
102     exception; otherwise returns false.
103 
104     The exception state is cleared when evaluate() is called.
105 
106     \sa uncaughtException(), uncaughtExceptionLineNumber(),
107       uncaughtExceptionBacktrace()
108 */
hasUncaughtException() const109 bool QScriptEngine::hasUncaughtException() const
110 {
111     return d_ptr->hasUncaughtException();
112 }
113 
114 /*!
115     Returns the current uncaught exception, or an invalid QScriptValue
116     if there is no uncaught exception.
117 
118     The exception value is typically an \c{Error} object; in that case,
119     you can call toString() on the return value to obtain an error
120     message.
121 
122     \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
123       uncaughtExceptionBacktrace()
124 */
uncaughtException() const125 QScriptValue QScriptEngine::uncaughtException() const
126 {
127     return QScriptValuePrivate::get(d_ptr->uncaughtException());
128 }
129 
130 /*!
131     Clears any uncaught exceptions in this engine.
132 
133     \sa hasUncaughtException()
134 */
clearExceptions()135 void QScriptEngine::clearExceptions()
136 {
137     d_ptr->clearExceptions();
138 }
139 
140 /*!
141     Returns the line number where the last uncaught exception occurred.
142 
143     Line numbers are 1-based, unless a different base was specified as
144     the second argument to evaluate().
145 
146     \sa hasUncaughtException(), uncaughtExceptionBacktrace()
147 */
uncaughtExceptionLineNumber() const148 int QScriptEngine::uncaughtExceptionLineNumber() const
149 {
150     return d_ptr->uncaughtExceptionLineNumber();
151 }
152 
153 /*!
154     Returns a human-readable backtrace of the last uncaught exception.
155 
156     Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
157 
158     \sa uncaughtException()
159 */
uncaughtExceptionBacktrace() const160 QStringList QScriptEngine::uncaughtExceptionBacktrace() const
161 {
162     return d_ptr->uncaughtExceptionBacktrace();
163 }
164 
165 /*!
166     Runs the garbage collector.
167 
168     The garbage collector will attempt to reclaim memory by locating and disposing of objects that are
169     no longer reachable in the script environment.
170 
171     Normally you don't need to call this function; the garbage collector will automatically be invoked
172     when the QScriptEngine decides that it's wise to do so (i.e. when a certain number of new objects
173     have been created). However, you can call this function to explicitly request that garbage
174     collection should be performed as soon as possible.
175 
176     \sa reportAdditionalMemoryCost()
177 */
collectGarbage()178 void QScriptEngine::collectGarbage()
179 {
180     d_ptr->collectGarbage();
181 }
182 
183 /*!
184   Reports an additional memory cost of the given \a size, measured in
185   bytes, to the garbage collector.
186 
187   This function can be called to indicate that a JavaScript object has
188   memory associated with it that isn't managed by Qt Script itself.
189   Reporting the additional cost makes it more likely that the garbage
190   collector will be triggered.
191 
192   Note that if the additional memory is shared with objects outside
193   the scripting environment, the cost should not be reported, since
194   collecting the JavaScript object would not cause the memory to be
195   freed anyway.
196 
197   Negative \a size values are ignored, i.e. this function can't be
198   used to report that the additional memory has been deallocated.
199 
200   \sa collectGarbage()
201 */
reportAdditionalMemoryCost(int cost)202 void QScriptEngine::reportAdditionalMemoryCost(int cost)
203 {
204     d_ptr->reportAdditionalMemoryCost(cost);
205 }
206 
207 /*!
208   Returns a handle that represents the given string, \a str.
209 
210   QScriptString can be used to quickly look up properties, and
211   compare property names, of script objects.
212 
213   \sa QScriptValue::property()
214 */
toStringHandle(const QString & str)215 QScriptString QScriptEngine::toStringHandle(const QString& str)
216 {
217     return QScriptStringPrivate::get(d_ptr->toStringHandle(str));
218 }
219 
220 /*!
221   Converts the given \a value to an object, if such a conversion is
222   possible; otherwise returns an invalid QScriptValue. The conversion
223   is performed according to the following table:
224 
225     \table
226     \header \o Input Type \o Result
227     \row    \o Undefined  \o An invalid QScriptValue.
228     \row    \o Null       \o An invalid QScriptValue.
229     \row    \o Boolean    \o A new Boolean object whose internal value is set to the value of the boolean.
230     \row    \o Number     \o A new Number object whose internal value is set to the value of the number.
231     \row    \o String     \o A new String object whose internal value is set to the value of the string.
232     \row    \o Object     \o The result is the object itself (no conversion).
233     \endtable
234 
235     \sa newObject()
236 */
toObject(const QScriptValue & value)237 QScriptValue QScriptEngine::toObject(const QScriptValue& value)
238 {
239     return QScriptValuePrivate::get(QScriptValuePrivate::get(value)->toObject(d_ptr.data()));
240 }
241 
242 /*!
243   Returns a QScriptValue of the primitive type Null.
244 
245   \sa undefinedValue()
246 */
nullValue()247 QScriptValue QScriptEngine::nullValue()
248 {
249     return QScriptValue(this, QScriptValue::NullValue);
250 }
251 
252 /*!
253   Returns a QScriptValue of the primitive type Undefined.
254 
255   \sa nullValue()
256 */
undefinedValue()257 QScriptValue QScriptEngine::undefinedValue()
258 {
259     return QScriptValue(this, QScriptValue::UndefinedValue);
260 }
261 
262 /*!
263     Creates a QScriptValue that wraps a native (C++) function. \a fun
264     must be a C++ function with signature QScriptEngine::FunctionSignature.
265     \a length is the number of arguments that \a fun expects; this becomes
266     the \c{length} property of the created QScriptValue.
267 
268     Note that \a length only gives an indication of the number of
269     arguments that the function expects; an actual invocation of a
270     function can include any number of arguments. You can check the
271     \l{QScriptContext::argumentCount()}{argumentCount()} of the
272     QScriptContext associated with the invocation to determine the
273     actual number of arguments passed.
274 
275     A \c{prototype} property is automatically created for the resulting
276     function object, to provide for the possibility that the function
277     will be used as a constructor.
278 
279     By combining newFunction() and the property flags
280     QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
281     can create script object properties that behave like normal
282     properties in script code, but are in fact accessed through
283     functions (analogous to how properties work in \l{Qt's Property
284     System}). Example:
285 
286     \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
287 
288     When the property \c{foo} of the script object is subsequently
289     accessed in script code, \c{getSetFoo()} will be invoked to handle
290     the access.  In this particular case, we chose to store the "real"
291     value of \c{foo} as a property of the accessor function itself; you
292     are of course free to do whatever you like in this function.
293 
294     In the above example, a single native function was used to handle
295     both reads and writes to the property; the argument count is used to
296     determine if we are handling a read or write. You can also use two
297     separate functions; just specify the relevant flag
298     (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
299     setting the property, e.g.:
300 
301     \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
302 
303     \sa QScriptValue::call()
304 */
newFunction(QScriptEngine::FunctionSignature fun,int length)305 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
306 {
307     return QScriptValuePrivate::get(d_ptr->newFunction(fun, 0, length));
308 }
309 
310 /*!
311     Creates a constructor function from \a fun, with the given \a length.
312     The \c{prototype} property of the resulting function is set to be the
313     given \a prototype. The \c{constructor} property of \a prototype is
314     set to be the resulting function.
315 
316     When a function is called as a constructor (e.g. \c{new Foo()}), the
317     `this' object associated with the function call is the new object
318     that the function is expected to initialize; the prototype of this
319     default constructed object will be the function's public
320     \c{prototype} property. If you always want the function to behave as
321     a constructor (e.g. \c{Foo()} should also create a new object), or
322     if you need to create your own object rather than using the default
323     `this' object, you should make sure that the prototype of your
324     object is set correctly; either by setting it manually, or, when
325     wrapping a custom type, by having registered the defaultPrototype()
326     of that type. Example:
327 
328     \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
329 
330     To wrap a custom type and provide a constructor for it, you'd typically
331     do something like this:
332 
333     \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
334 */
newFunction(QScriptEngine::FunctionSignature fun,const QScriptValue & prototype,int length)335 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, const QScriptValue& prototype, int length)
336 {
337     return QScriptValuePrivate::get(d_ptr->newFunction(fun, QScriptValuePrivate::get(prototype), length));
338 }
339 
340 /*!
341     \internal
342     \since 4.4
343 */
newFunction(QScriptEngine::FunctionWithArgSignature fun,void * arg)344 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void* arg)
345 {
346     return QScriptValuePrivate::get(d_ptr->newFunction(fun, arg));
347 }
348 
349 /*!
350   Creates a QtScript object of class Object.
351 
352   The prototype of the created object will be the Object
353   prototype object.
354 
355   \sa newArray(), QScriptValue::setProperty()
356 */
newObject()357 QScriptValue QScriptEngine::newObject()
358 {
359     return QScriptValuePrivate::get(d_ptr->newObject());
360 }
361 
362 /*!
363   Creates a QtScript object of class Array with the given \a length.
364 
365   \sa newObject()
366 */
newArray(uint length)367 QScriptValue QScriptEngine::newArray(uint length)
368 {
369     return QScriptValuePrivate::get(d_ptr->newArray(length));
370 }
371 
372 /*!
373     Creates a QtScript object of class Date with the given \a value
374     (the number of milliseconds since 01 January 1970, UTC).
375 */
newDate(qsreal value)376 QScriptValue QScriptEngine::newDate(qsreal value)
377 {
378     return QScriptValuePrivate::get(d_ptr->newDate(value));
379 }
380 
381 /*!
382     Creates a QtScript object of class Date from the given \a value.
383 
384     \sa QScriptValue::toDateTime()
385 */
newDate(const QDateTime & value)386 QScriptValue QScriptEngine::newDate(const QDateTime& value)
387 {
388     if (value.isValid())
389         return QScriptValuePrivate::get(d_ptr->newDate(qsreal(value.toMSecsSinceEpoch())));
390     return QScriptValuePrivate::get(d_ptr->newDate(qSNaN()));
391 }
392 
393 /*!
394   Returns this engine's Global Object.
395 
396   By default, the Global Object contains the built-in objects that are
397   part of \l{ECMA-262}, such as Math, Date and String. Additionally,
398   you can set properties of the Global Object to make your own
399   extensions available to all script code. Non-local variables in
400   script code will be created as properties of the Global Object, as
401   well as local variables in global code.
402 */
globalObject() const403 QScriptValue QScriptEngine::globalObject() const
404 {
405     return QScriptValuePrivate::get(d_ptr->globalObject());
406 }
407 
408 /*!
409     \typedef QScriptEngine::FunctionSignature
410     \relates QScriptEngine
411 
412     The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}.
413 
414     A function with such a signature can be passed to
415     QScriptEngine::newFunction() to wrap the function.
416 */
417 
418 /*!
419     \typedef QScriptEngine::FunctionWithArgSignature
420     \relates QScriptEngine
421 
422     The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}.
423 
424     A function with such a signature can be passed to
425     QScriptEngine::newFunction() to wrap the function.
426 */
427