Home | History | Annotate | Download | only in api
      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 */
     36 QScriptEngine::QScriptEngine()
     37     : d_ptr(new QScriptEnginePrivate(this))
     38 {
     39 }
     40 
     41 /*!
     42     Destroys this QScriptEngine.
     43 */
     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 */
     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 */
     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 
     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 */
    109 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 */
    125 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 */
    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 */
    148 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 */
    160 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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    403 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