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*/
36QScriptEngine::QScriptEngine()
37    : d_ptr(new QScriptEnginePrivate(this))
38{
39}
40
41/*!
42    Destroys this QScriptEngine.
43*/
44QScriptEngine::~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*/
52QScriptSyntaxCheckResult 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*/
90QScriptValue QScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
91{
92    return QScriptValuePrivate::get(d_ptr->evaluate(program, fileName, lineNumber));
93}
94
95QScriptValue 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*/
109bool 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*/
125QScriptValue 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*/
135void 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*/
148int 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*/
160QStringList 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*/
178void 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*/
202void 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*/
215QScriptString 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*/
237QScriptValue 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*/
247QScriptValue 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*/
257QScriptValue 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*/
305QScriptValue 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*/
335QScriptValue 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*/
344QScriptValue 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*/
357QScriptValue 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*/
367QScriptValue 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*/
376QScriptValue 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*/
386QScriptValue 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*/
403QScriptValue 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